'use client';
import { useState, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
CheckCircle,
XCircle,
Clock,
User,
Home,
Calendar,
DollarSign,
AlertCircle,
Key,
DoorOpen,
Shield,
Phone,
Mail,
MessageCircle,
ChevronDown,
ChevronUp,
FileText,
Download,
Printer,
History,
Loader2,
CreditCard
} from 'lucide-react';
import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
import toast, { Toaster } from 'react-hot-toast';
import AuthService from '../../services/AuthService';
import { adminConfirmDeposit } from '../../utils/api';
const ReasonDialog = ({ isOpen, onClose, onConfirm, title, defaultReason = '' }) => {
const [reason, setReason] = useState(defaultReason);
const [otherReason, setOtherReason] = useState('');
const commonReasons = [
'ط£ط¹ظ…ط§ظ„ طµظٹط§ظ†ط© ظپظٹ ط§ظ„ط¹ظ‚ط§ط±',
'ط§ظ„ط¹ظ‚ط§ط± ط؛ظٹط± ظ…طھط§ط ظپظٹ ظ‡ط°ظ‡ ط§ظ„طھظˆط§ط±ظٹط®',
'ظ…ط´ظƒظ„ط© ظپظٹ ظˆط«ط§ط¦ظ‚ ط§ظ„ظ…ط³طھط£ط¬ط±',
'ط§ظ„ظ…ط§ظ„ظƒ ط؛ظٹط± ظ…طھط§ط ظ„ظ„طھط³ظ„ظٹظ…',
'طھط£ط®ط± ظپظٹ ط¯ظپط¹ ط§ظ„ط¶ظ…ط§ظ†',
'ط³ط¨ط¨ ط¢ط®ط±'
];
if (!isOpen) return null;
return (
e.stopPropagation()}
>
{title}
ظٹط±ط¬ظ‰ طھطط¯ظٹط¯ ط³ط¨ط¨ ط§ظ„ط±ظپط¶
{commonReasons.map((r) => (
))}
);
};
const PDFExportButton = ({ request, onExportComplete }) => {
const [isExporting, setIsExporting] = useState(false);
const formatCurrency = (amount) => {
return amount?.toLocaleString() + ' ظ„.ط³';
};
const generatePDF = async () => {
if (!request) {
toast.error('ظ„ط§ طھظˆط¬ط¯ ط¨ظٹط§ظ†ط§طھ ظ„ظ„طھطµط¯ظٹط±');
return;
}
setIsExporting(true);
const loadingToast = toast.loading('ط¬ط§ط±ظٹ ط¥ظ†ط´ط§ط، ظ…ظ„ظپ PDF...', { id: 'pdf-export' });
try {
const printContent = document.createElement('div');
printContent.style.width = '800px';
printContent.style.padding = '40px';
printContent.style.backgroundColor = 'white';
printContent.style.fontFamily = 'Cairo, Arial, sans-serif';
printContent.style.direction = 'rtl';
printContent.style.position = 'absolute';
printContent.style.left = '-9999px';
printContent.style.top = '-9999px';
printContent.style.zIndex = '-9999';
printContent.innerHTML = `
ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ظ…ط³طھط£ط¬ط±
ط§ظ„ط§ط³ظ… ط§ظ„ظƒط§ظ…ظ„:
${request.user || 'ط؛ظٹط± ظ…طط¯ط¯'}
ظ†ظˆط¹ ط§ظ„ظ‡ظˆظٹط©:
${request.userType === 'syrian' ? 'ظ‡ظˆظٹط© ط³ظˆط±ظٹط©' : 'ط¬ظˆط§ط² ط³ظپط±'}
ط±ظ‚ظ… ط§ظ„ظ‡ظˆظٹط©:
${request.identityNumber || 'ط؛ظٹط± ظ…طط¯ط¯'}
ط§ظ„ط¨ط±ظٹط¯ ط§ظ„ط¥ظ„ظƒطھط±ظˆظ†ظٹ:
${request.userEmail || 'ط؛ظٹط± ظ…طط¯ط¯'}
ط±ظ‚ظ… ط§ظ„ظ‡ط§طھظپ:
${request.userPhone || 'ط؛ظٹط± ظ…طط¯ط¯'}
ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ط¹ظ‚ط§ط±
ط§ظ„ط¹ظ‚ط§ط±:
${request.property || 'ط؛ظٹط± ظ…طط¯ط¯'}
ط§ظ„ط³ط¹ط± ط§ظ„ظٹظˆظ…ظٹ:
${formatCurrency(request.dailyPrice)}
طھظپط§طµظٹظ„ ط§ظ„طط¬ط²
طھط§ط±ظٹط® ط§ظ„ط¨ط¯ط§ظٹط©:
${request.startDate || 'ط؛ظٹط± ظ…طط¯ط¯'}
طھط§ط±ظٹط® ط§ظ„ظ†ظ‡ط§ظٹط©:
${request.endDate || 'ط؛ظٹط± ظ…طط¯ط¯'}
ط¹ط¯ط¯ ط§ظ„ط£ظٹط§ظ…:
${request.days || 0} ظٹظˆظ…
ط§ظ„طط§ظ„ط©:
${request.status === 'pending' ? 'ظ‚ظٹط¯ ط§ظ„ط§ظ†طھط¸ط§ط±' :
request.status === 'owner_approved' ? 'ظ…ظˆط§ظپظ‚ط© ط§ظ„ظ…ط§ظ„ظƒ' :
request.status === 'admin_approved' ? 'ظ…ظˆط§ظپظ‚ط© ط§ظ„ط¥ط¯ط§ط±ط©' :
request.status === 'active' ? 'ط¥ظٹط¬ط§ط± ظ†ط´ط·' :
request.status === 'completed' ? 'ظ…ظ†طھظ‡ظٹ' : 'ظ…ط±ظپظˆط¶'}
ط§ظ„ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ظ…ط§ظ„ظٹط©
ط³ظ„ظپط© ط§ظ„ط¶ظ…ط§ظ†:
${formatCurrency(request.securityDeposit)}
ط§ظ„ظ…ط¨ظ„ط؛ ط§ظ„ط¥ط¬ظ…ط§ظ„ظٹ:
${formatCurrency(request.totalAmount)}
ظ†ط³ط¨ط© ط§ظ„ط¹ظ…ظˆظ„ط©:
${request.commissionRate || 0}%
ظ†ظˆط¹ ط§ظ„ط¹ظ…ظˆظ„ط©:
${request.commissionType || 'ط؛ظٹط± ظ…طط¯ط¯'}
ظ‚ظٹظ…ط© ط§ظ„ط¹ظ…ظˆظ„ط©:
${formatCurrency(request.commissionAmount)}
${request.notes ? `
ظ…ظ„ط§طط¸ط§طھ
${request.notes}
` : ''}
ط³ط¬ظ„ ط§ظ„ط¥ط¬ط±ط§ط،ط§طھ
${request.requestDate}
طھظ… ط¥ظ†ط´ط§ط، ط§ظ„ط·ظ„ط¨
${request.ownerApproved ? `
✓
طھظ…طھ ظ…ظˆط§ظپظ‚ط© ط§ظ„ظ…ط§ظ„ظƒ
` : ''}
${request.adminApproved ? `
✓
طھظ…طھ ظ…ظˆط§ظپظ‚ط© ط§ظ„ط¥ط¯ط§ط±ط©
` : ''}
${request.ownerDelivered ? `
طھظ… طھط³ظ„ظٹظ… ط§ظ„ظ…ظپطھط§ط
` : ''}
${request.tenantReceived ? `
طھظ… ط§ط³طھظ„ط§ظ… ط§ظ„ط¹ظ‚ط§ط±
` : ''}
`;
document.body.appendChild(printContent);
await new Promise(resolve => setTimeout(resolve, 200));
const canvas = await html2canvas(printContent, {
scale: 2.5,
backgroundColor: '#ffffff',
logging: false,
useCORS: true,
windowWidth: printContent.scrollWidth,
windowHeight: printContent.scrollHeight,
onclone: (clonedDoc, element) => {
}
});
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'a4',
compress: true
});
const imgWidth = 210;
const pageHeight = 297;
const imgHeight = (canvas.height * imgWidth) / canvas.width;
let heightLeft = imgHeight;
let position = 0;
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
let pageCount = 1;
while (heightLeft > 0) {
position = heightLeft - imgHeight;
pdf.addPage();
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
pageCount++;
}
const fileName = `طھظ‚ط±ظٹط±_ط·ظ„ط¨_${request.id}_${new Date().toISOString().split('T')[0]}.pdf`;
pdf.save(fileName);
document.body.removeChild(printContent);
toast.success(`طھظ… طھطµط¯ظٹط± ط§ظ„طھظ‚ط±ظٹط± ط¨ظ†ط¬ط§ط! (${pageCount} طµظپطط©)`, { id: 'pdf-export' });
if (onExportComplete) {
onExportComplete();
}
} catch (error) {
console.error('Error generating PDF:', error);
toast.error('طط¯ط« ط®ط·ط£ ط£ط«ظ†ط§ط، ط¥ظ†ط´ط§ط، ظ…ظ„ظپ PDF', { id: 'pdf-export' });
} finally {
setIsExporting(false);
}
};
return (
);
};
const RequestDetailsDialog = ({ request, isOpen, onClose }) => {
if (!isOpen || !request) return null;
const formatCurrency = (amount) => {
return amount?.toLocaleString() + ' ظ„.ط³';
};
return (
e.stopPropagation()}
>
طھظپط§طµظٹظ„ ط§ظ„ط·ظ„ط¨ #{request.id}
ط¬ظ…ظٹط¹ ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ط·ظ„ط¨ ظپظٹ ظ…ظƒط§ظ† ظˆط§طط¯
ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ظ…ط³طھط£ط¬ط±
{request.user}
{request.userType === 'syrian' ? 'ًں‡¸ًں‡¾ ظ‡ظˆظٹط© ط³ظˆط±ظٹط©' : 'ط¬ظˆط§ط² ط³ظپط±'}
{request.identityNumber}
{request.userEmail}
ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ط¹ظ‚ط§ط±
{request.property}
{formatCurrency(request.dailyPrice)}
طھظپط§طµظٹظ„ ط§ظ„طط¬ط²
{request.startDate}
{request.endDate}
{request.days} ظٹظˆظ…
{formatCurrency(request.totalAmount)}
ط§ظ„ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ظ…ط§ظ„ظٹط©
{formatCurrency(request.securityDeposit)}
{request.securityDepositPaid ? '✓ طھظ… ط§ظ„ط¯ظپط¹' : 'âڈ³ ظپظٹ ط§ظ†طھط¸ط§ط± ط§ظ„ط¯ظپط¹'}
{request.commissionRate}%
{request.commissionType}
{formatCurrency(request.commissionAmount)}
ط³ط¬ظ„ ط§ظ„ط¥ط¬ط±ط§ط،ط§طھ
طھظ… ط¥ظ†ط´ط§ط، ط§ظ„ط·ظ„ط¨: {request.requestDate}
{request.ownerApproved && (
ظ…ظˆط§ظپظ‚ط© ط§ظ„ظ…ط§ظ„ظƒ
)}
{request.adminApproved && (
ظ…ظˆط§ظپظ‚ط© ط§ظ„ط¥ط¯ط§ط±ط©
)}
{request.ownerDelivered && (
طھظ… طھط³ظ„ظٹظ… ط§ظ„ظ…ظپطھط§ط ظ…ظ† ط§ظ„ظ…ط§ظ„ظƒ
)}
{request.notes && (
)}
);
};
const RequestCard = ({ request, onAction, onViewDetails, confirmingDepositId }) => {
const [expanded, setExpanded] = useState(false);
const isConfirmingDeposit = confirmingDepositId === request.id;
const formatCurrency = (amount) => {
return amount?.toLocaleString() + ' ظ„.ط³';
};
const getStatusColor = (status) => {
switch(status) {
case 'pending': return 'border-yellow-400 bg-yellow-50';
case 'owner_approved': return 'border-blue-400 bg-blue-50';
case 'admin_approved': return 'border-green-400 bg-green-50';
case 'active': return 'border-purple-400 bg-purple-50';
case 'completed': return 'border-gray-400 bg-gray-50';
case 'rejected': return 'border-red-400 bg-red-50';
default: return 'border-gray-200 bg-white';
}
};
const getStatusBadge = (status) => {
const styles = {
pending: 'bg-yellow-500 text-white',
owner_approved: 'bg-blue-500 text-white',
admin_approved: 'bg-green-500 text-white',
active: 'bg-purple-500 text-white',
completed: 'bg-gray-500 text-white',
rejected: 'bg-red-500 text-white'
};
const labels = {
pending: 'ط¨ط§ظ†طھط¸ط§ط± ط§ظ„ظ…ظˆط§ظپظ‚ط©',
owner_approved: 'ظ…ظˆط§ظپظ‚ط© ط§ظ„ظ…ط§ظ„ظƒ',
admin_approved: 'ظ…ظˆط§ظپظ‚ط© ط§ظ„ط¥ط¯ط§ط±ط©',
active: 'ط¥ظٹط¬ط§ط± ظ†ط´ط·',
completed: 'ظ…ظ†طھظ‡ظٹ',
rejected: 'ظ…ط±ظپظˆط¶'
};
return (
{labels[status]}
);
};
return (
setExpanded(!expanded)}>
ط·ظ„ط¨ #{request.id}
{getStatusBadge(request.status)}
{request.requestDate}
{expanded ? (
) : (
)}
{request.user}
{request.property}
{request.days} ط£ظٹط§ظ…
{formatCurrency(request.totalAmount)}
{expanded && (
ط³ظ„ظپط© ط¶ظ…ط§ظ†
{formatCurrency(request.securityDeposit)}
طط§ظ„ط© ط§ظ„ط±ط¹ط¨ظˆظ†
{request.securityDepositPaid ? 'طھظ… ط§ظ„ط¯ظپط¹' : ' ط¨ط§ظ†طھط¸ط§ط±'}
ط§ظ„ط¹ظ…ظˆظ„ط©
{request.commissionRate}% ({request.commissionType})
ظ…ط¯ط© ط§ظ„ط¥ظٹط¬ط§ط±
{request.startDate} ط¥ظ„ظ‰ {request.endDate}
{(request.ownerApproved || request.adminApproved) && (
ظ…ط¹ظ„ظˆظ…ط§طھ ط§ظ„ط§طھطµط§ظ„
)}
{request.status === 'pending' && (
)}
{request.status === 'owner_approved' && (
)}
{request.status === 'admin_approved' && (
)}
{request.status === 'active' && (
{request.actualStartDate && (
ط¨ط¯ط£ ط§ظ„ط¥ظٹط¬ط§ط±: {request.actualStartDate}
ط§ظ„ظ…ط¯ط©: {request.days} ظٹظˆظ…
)}
)}
)}
);
};
export default function BookingRequests() {
const [requests, setRequests] = useState([
{
id: 'REQ001',
user: 'ط£طظ…ط¯ ظ…طظ…ط¯',
userEmail: 'ahmed@example.com',
userPhone: '0938123456',
userType: 'syrian',
identityNumber: '123456789',
property: 'ظپظٹظ„ط§ ظپط§ط®ط±ط© ظپظٹ ط¯ظ…ط´ظ‚',
propertyId: 1,
startDate: '2024-03-01',
endDate: '2024-03-10',
days: 10,
totalAmount: 5000000,
dailyPrice: 500000,
commissionRate: 5,
commissionType: 'ظ…ظ† ط§ظ„ظ…ط§ظ„ظƒ',
commissionAmount: 250000,
securityDeposit: 500000,
status: 'pending',
requestDate: '2024-02-25',
ownerApproved: false,
adminApproved: false,
ownerDelivered: false,
tenantReceived: false,
tenantLeft: false,
ownerReceived: false,
securityDepositPaid: false,
securityDepositReturned: null,
contractSigned: false,
notes: '',
actualStartDate: null,
actualEndDate: null
},
{
id: 'REQ002',
user: 'ط³ط§ط±ط© ط£طظ…ط¯',
userEmail: 'sara@example.com',
userPhone: '0945123789',
userType: 'passport',
identityNumber: 'AB123456',
property: 'ط´ظ‚ط© طط¯ظٹط«ط© ظپظٹ طظ„ط¨',
propertyId: 2,
startDate: '2024-03-05',
endDate: '2024-03-15',
days: 10,
totalAmount: 2500000,
dailyPrice: 250000,
commissionRate: 7,
commissionType: 'ظ…ظ† ط§ظ„ظ…ط³طھط£ط¬ط±',
commissionAmount: 175000,
securityDeposit: 250000,
status: 'owner_approved',
requestDate: '2024-02-24',
ownerApproved: true,
adminApproved: false,
ownerDelivered: false,
tenantReceived: false,
tenantLeft: false,
ownerReceived: false,
securityDepositPaid: false,
securityDepositReturned: null,
contractSigned: false,
notes: '',
actualStartDate: null,
actualEndDate: null
},
{
id: 'REQ003',
user: 'ظ…طظ…ط¯ ط§ظ„طظ„ط¨ظٹ',
userEmail: 'mohammed@example.com',
userPhone: '0956123456',
userType: 'syrian',
identityNumber: '987654321',
property: 'ط´ظ‚ط© ط¨ط¬ط§ظ†ط¨ ط§ظ„ط¨طط± ظپظٹ ط§ظ„ظ„ط§ط°ظ‚ظٹط©',
propertyId: 3,
startDate: '2024-02-20',
endDate: '2024-03-20',
days: 30,
totalAmount: 9000000,
dailyPrice: 300000,
commissionRate: 5,
commissionType: 'ظ…ظ† ط§ظ„ط§ط«ظ†ظٹظ†',
commissionAmount: 450000,
securityDeposit: 500000,
status: 'active',
requestDate: '2024-02-15',
ownerApproved: true,
adminApproved: true,
ownerDelivered: true,
tenantReceived: true,
tenantLeft: false,
ownerReceived: false,
securityDepositPaid: true,
securityDepositReturned: null,
contractSigned: true,
notes: 'ط¹ظ‚ط¯ ظ…ظˆظ‚ط¹ ط¥ظ„ظƒطھط±ظˆظ†ظٹط§ظ‹',
actualStartDate: '2024-02-20',
actualEndDate: null
}
]);
const [filter, setFilter] = useState('all');
const [reasonDialog, setReasonDialog] = useState({ isOpen: false, requestId: null, type: null });
const [detailsDialog, setDetailsDialog] = useState({ isOpen: false, request: null });
const [confirmingDepositId, setConfirmingDepositId] = useState(null);
const handleAction = (action, data) => {
switch(action) {
case 'owner_approve':
handleOwnerApprove(data);
break;
case 'owner_reject':
setReasonDialog({ isOpen: true, requestId: data, type: 'owner' });
break;
case 'admin_approve':
handleAdminApprove(data);
break;
case 'admin_reject':
setReasonDialog({ isOpen: true, requestId: data, type: 'admin' });
break;
case 'confirm_deposit':
handleDepositConfirmation(data);
break;
case 'deliver_key':
handleKeyDelivery(data.id, data.type);
break;
case 'receive_property':
handleKeyDelivery(data.id, data.type);
break;
case 'tenant_leave':
handleEndRental(data.id, data.type);
break;
case 'owner_receive':
handleEndRental(data.id, data.type);
break;
case 'view_details':
setDetailsDialog({ isOpen: true, request: data });
break;
default:
break;
}
};
const handleRejectWithReason = (reason) => {
const { requestId, type } = reasonDialog;
setRequests(prev =>
prev.map(req =>
req.id === requestId
? {
...req,
status: 'rejected',
[type === 'owner' ? 'ownerApproved' : 'adminApproved']: false,
rejectionReason: reason,
rejectionType: type,
notes: `${type === 'owner' ? 'رفض من المالك' : 'رفض إداري'}: ${reason}`
}
: req
)
);
setReasonDialog({ isOpen: false, requestId: null, type: null });
};
const handleOwnerApprove = (requestId) => {
setRequests(prev =>
prev.map(req =>
req.id === requestId
? {
...req,
ownerApproved: true,
status: 'owner_approved',
notes: 'طھظ…طھ ط§ظ„ظ…ظˆط§ظپظ‚ط© ظ…ظ† ظ‚ط¨ظ„ ط§ظ„ظ…ط§ظ„ظƒ'
}
: req
)
);
};
const handleAdminApprove = (requestId) => {
setRequests(prev =>
prev.map(req =>
req.id === requestId
? {
...req,
adminApproved: true,
status: 'admin_approved',
notes: 'طھظ…طھ ط§ظ„ظ…ظˆط§ظپظ‚ط© ظ…ظ† ظ‚ط¨ظ„ ط§ظ„ط¥ط¯ط§ط±ط©'
}
: req
)
);
};
const handleDepositConfirmation = async (request) => {
if (!AuthService.isAdmin()) {
toast.error('هذا الإجراء متاح للإدارة فقط');
return;
}
const reservationId = Number(request?.reservationId ?? request?.id);
if (!Number.isFinite(reservationId)) {
toast.error('هذا الطلب تجريبي ولا يحتوي على reservationId من الخادم');
return;
}
const adminUser = AuthService.getUser();
const parsedAdminId = Number(adminUser?.id);
const adminId = Number.isFinite(parsedAdminId) ? parsedAdminId : adminUser?.id;
if (adminId == null || adminId === '') {
toast.error('لم نتمكن من تحديد هوية المدير');
return;
}
setConfirmingDepositId(request.id);
try {
const result = await adminConfirmDeposit(reservationId, adminId, null);
if (!result.ok) {
throw new Error(result.message || result.data?.message || `HTTP ${result.status}`);
}
setRequests((prev) =>
prev.map((req) =>
req.id === request.id
? {
...req,
securityDepositPaid: true,
notes: 'تم تأكيد العربون من قبل الإدارة',
}
: req,
),
);
toast.success('تم تأكيد العربون بنجاح');
} catch (err) {
console.error('[Admin] Deposit confirmation failed:', err);
toast.error(err.message || 'فشل تأكيد العربون');
} finally {
setConfirmingDepositId(null);
}
};
const handleKeyDelivery = (requestId, userType) => {
setRequests(prev =>
prev.map(req => {
if (req.id === requestId) {
const updates = {};
if (userType === 'owner') {
updates.ownerDelivered = true;
updates.notes = 'طھظ… طھط³ظ„ظٹظ… ط§ظ„ظ…ظپطھط§ط ظ…ظ† ظ‚ط¨ظ„ ط§ظ„ظ…ط§ظ„ظƒ';
}
if (userType === 'tenant') {
updates.tenantReceived = true;
updates.notes = 'طھظ… ط§ط³طھظ„ط§ظ… ط§ظ„ط¹ظ‚ط§ط± ظ…ظ† ظ‚ط¨ظ„ ط§ظ„ظ…ط³طھط£ط¬ط±';
}
if ((userType === 'owner' && req.tenantReceived) ||
(userType === 'tenant' && req.ownerDelivered)) {
updates.status = 'active';
updates.contractSigned = true;
updates.actualStartDate = new Date().toISOString().split('T')[0];
updates.notes = 'ط¨ط¯ط£طھ ظپطھط±ط© ط§ظ„ط¥ظٹط¬ط§ط± ط§ظ„ظپط¹ظ„ظٹط©';
}
return { ...req, ...updates };
}
return req;
})
);
};
const handleEndRental = (requestId, userType) => {
setRequests(prev =>
prev.map(req => {
if (req.id === requestId) {
const updates = {};
if (userType === 'tenant') {
updates.tenantLeft = true;
updates.notes = 'ط؛ط§ط¯ط± ط§ظ„ظ…ط³طھط£ط¬ط± ط§ظ„ط¹ظ‚ط§ط±';
}
if (userType === 'owner') {
updates.ownerReceived = true;
updates.notes = 'ط§ط³طھظ„ظ… ط§ظ„ظ…ط§ظ„ظƒ ط§ظ„ط¹ظ‚ط§ط±';
}
if ((userType === 'tenant' && req.ownerReceived) ||
(userType === 'owner' && req.tenantLeft)) {
const actualEndDate = new Date();
const actualStartDate = new Date(req.actualStartDate || req.startDate);
const actualDays = Math.ceil((actualEndDate - actualStartDate) / (1000 * 60 * 60 * 24));
const actualAmount = req.dailyPrice * actualDays;
const damageDeduction = 0;
const refundAmount = req.securityDeposit - damageDeduction;
updates.status = 'completed';
updates.actualEndDate = actualEndDate.toISOString().split('T')[0];
updates.actualDays = actualDays;
updates.actualAmount = actualAmount;
updates.securityDepositReturned = refundAmount;
updates.damageDeduction = damageDeduction;
updates.notes = `ط§ظ†طھظ‡ظ‰ ط§ظ„ط¥ظٹط¬ط§ط± ط¨ط¹ط¯ ${actualDays} ظٹظˆظ… - ط§ظ„ظ…ط¨ظ„ط؛ ط§ظ„ظپط¹ظ„ظٹ: ${actualAmount.toLocaleString()} ظ„.ط³ - ظ…ط³طھط±ط¯ ط§ظ„ط¶ظ…ط§ظ†: ${refundAmount.toLocaleString()} ظ„.ط³`;
}
return { ...req, ...updates };
}
return req;
})
);
};
const filteredRequests = requests.filter(req =>
filter === 'all' ? true : req.status === filter
);
const stats = {
total: requests.length,
pending: requests.filter(r => r.status === 'pending').length,
active: requests.filter(r => r.status === 'active').length,
completed: requests.filter(r => r.status === 'completed').length
};
return (
{stats.total}
ط¥ط¬ظ…ط§ظ„ظٹ ط§ظ„ط·ظ„ط¨ط§طھ
{stats.pending}
ظ‚ظٹط¯ ط§ظ„ط§ظ†طھط¸ط§ط±
{stats.active}
ط¥ظٹط¬ط§ط±ط§طھ ظ†ط´ط·ط©
{stats.completed}
ظ…ظ†طھظ‡ظٹط©
طھطµظپظٹط© طط³ط¨ ط§ظ„طط§ظ„ط©
{filteredRequests.length} ط·ظ„ط¨
{[
{ id: 'all', label: 'ط§ظ„ظƒظ„', color: 'gray' },
{ id: 'pending', label: 'ظ‚ظٹط¯ ط§ظ„ط§ظ†طھط¸ط§ط±', color: 'yellow' },
{ id: 'owner_approved', label: 'ظ…ظˆط§ظپظ‚ط© ط§ظ„ظ…ط§ظ„ظƒ', color: 'blue' },
{ id: 'admin_approved', label: 'ظ…ظˆط§ظپظ‚ط© ط§ظ„ط¥ط¯ط§ط±ط©', color: 'green' },
{ id: 'active', label: 'ط¥ظٹط¬ط§ط±ط§طھ ظ†ط´ط·ط©', color: 'purple' },
{ id: 'completed', label: 'ظ…ظ†طھظ‡ظٹط©', color: 'gray' }
].map((tab) => (
))}
{filteredRequests.map((request) => (
setDetailsDialog({ isOpen: true, request })}
confirmingDepositId={confirmingDepositId}
/>
))}
{filteredRequests.length === 0 && (
ظ„ط§ طھظˆط¬ط¯ ط·ظ„ط¨ط§طھ طط¬ط²
ظ„ط§ طھظˆط¬ط¯ ط·ظ„ط¨ط§طھ طط¬ط² ظپظٹ ظ‡ط°ظ‡ ط§ظ„ظپط¦ط©
)}
setReasonDialog({ isOpen: false, requestId: null, type: null })}
onConfirm={handleRejectWithReason}
title={reasonDialog.type === 'owner' ? 'ط±ظپط¶ ظ…ظ† ط§ظ„ظ…ط§ظ„ظƒ' : 'ط±ظپط¶ ط¥ط¯ط§ط±ظٹ'}
/>
setDetailsDialog({ isOpen: false, request: null })}
/>
);
}