"use client"; import { useState, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { useTranslation } from "react-i18next"; import { PlusCircle, Building, Home, DollarSign, MapPin, Bed, Bath, Square, Edit, Trash2, Eye, Calendar, Layers, Sofa, DoorOpen, ImageIcon, CheckCircle, XCircle, AlertCircle, ChevronRight, ChevronLeft, Loader2, Save, X, Star, Ban, Check, School, Hospital, Store, GraduationCap, TreePine, CreditCard, Banknote, // تم إضافة Banknote هنا } from "lucide-react"; import toast, { Toaster } from "react-hot-toast"; import AuthService from "../../services/AuthService"; import { buildRentPropertyPayload, getMyRentListings, getMySaleListings, editRentProperty, editSaleProperty, updateRentPropertyStatus, updateSalePropertyStatus, uploadPicture, getPaymentTypes, OwnerPaymentForSaleProperite, // تم إضافة استيراد الدالة هنا } from "../../utils/api"; import { PropertyService } from "../../enums/PropertyService"; import { PropertyTerm } from "../../enums/PropertyTerm"; import Loading from "@/app/loading"; const serviceI18nKeys = { [PropertyService.ELECTRICITY]: "propertyService.electricity", [PropertyService.INTERNET]: "propertyService.internet", [PropertyService.HEATING]: "propertyService.heating", [PropertyService.WATER]: "propertyService.water", [PropertyService.POOL]: "propertyService.pool", [PropertyService.PRIVATE_GARDEN]: "propertyService.privateGarden", [PropertyService.PARKING]: "propertyService.parking", [PropertyService.SECURITY_247]: "propertyService.security247", [PropertyService.CENTRAL_HEATING]: "propertyService.centralHeating", [PropertyService.CENTRAL_AIR_CONDITIONING]: "propertyService.centralAirConditioning", [PropertyService.EQUIPPED_KITCHEN]: "propertyService.equippedKitchen", [PropertyService.MAIDS_ROOM]: "propertyService.maidsRoom", [PropertyService.ELEVATOR]: "propertyService.elevator", }; const termI18nKeys = { [PropertyTerm.NO_SMOKING]: "propertyTerm.noSmoking", [PropertyTerm.NO_ANIMALS]: "propertyTerm.noAnimals", [PropertyTerm.NO_PARTIES]: "propertyTerm.noParties", }; const proximityI18nKeys = { School: "proximity.school", Hospital: "proximity.hospital", Restaurant: "proximity.restaurant", University: "proximity.university", Park: "proximity.park", Mall: "proximity.mall", Supermarket: "proximity.supermarket", Pharmacy: "proximity.pharmacy", Mosque: "proximity.mosque", Bank: "proximity.bank", Airport: "proximity.airport", BusStation: "proximity.busStation", }; const CommissionPaymentDialog = ({ isOpen, property, onClose, selectedPayment, onSelectPayment, onConfirmPay, payingId, paymentMethods, loadingPaymentMethods, receiptImage, onSetReceiptImage, commissionDetails, setCommissionDetails, }) => { const { t } = useTranslation(); if (!isOpen || !property) return null; const commission = Number(property.commission || 0); const selectedMethod = paymentMethods?.find((m) => String(m?.id ?? m?.name) === String(selectedPayment)); const isHaram = selectedMethod?.name?.toLowerCase?.() === "haram"; const hasSelectedMethod = !!selectedMethod; const hasHaramDetails = commissionDetails?.fullName?.trim() && commissionDetails?.governorate?.trim() && commissionDetails?.phoneNumber?.trim(); const canPay = payingId !== property.id && hasSelectedMethod && (!isHaram || (!!receiptImage && !!hasHaramDetails)); return (
e.stopPropagation()} > {/* Header */}

{property.title}

{t("commission")}

{/* Commission amount */}

{t("commission")}

{commission.toLocaleString()} {t("syp")}

{/* Payment methods */}

{t("paymentMethod")}

{loadingPaymentMethods ? (
{t("loadingPaymentMethods", { defaultValue: "جاري تحميل طرق الدفع...", })}
) : !Array.isArray(paymentMethods) || paymentMethods.length === 0 ? (
{t("noPaymentMethodsAvailable", { defaultValue: "لا توجد طرق دفع متاحة حالياً.", })}
) : (
{paymentMethods.map((method, index) => { const isActive = method?.isActive === true || method?.active === true; const optionId = method?.id ?? method?.name ?? `payment-method-${index}`; const label = method?.name || t("paymentMethod", { defaultValue: "طريقة الدفع", }); const isSelected = selectedPayment === optionId; return ( ); })}
)}
{/* Haram payment details */} {isHaram && (

بيانات الدفع

{commissionDetails.split("\n").map((line, idx) => (
{line}
))}
)} {/* Receipt */} {isHaram && (

{t("uploadReceipt", { defaultValue: "إيصال الدفع", })}

{receiptImage ? (
receipt

{receiptImage.name}

) : ( )}
)} {/* Pay */}
onConfirmPay(property)} whileHover={{ scale: 1.01 }} whileTap={{ scale: 0.99 }} className="w-full bg-amber-500 hover:bg-amber-600 disabled:bg-amber-300 text-white font-bold py-4 px-6 rounded-2xl text-lg transition-all flex items-center justify-center gap-3" > {payingId === property.id ? ( <> {t("processingPayment")} ) : ( <> {t("payCommission", { defaultValue: "دفع الكمسيون", })} )}
); }; const DeleteConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle }) => { const { t } = useTranslation(); if (!isOpen) return null; return ( e.stopPropagation()} >

{t("deleteConfirmTitle")}

{t("deleteConfirmMessage", { title: propertyTitle })}

{t("deleteIrreversible")}

); }; const DeactivateConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle, isActivating }) => { const { t } = useTranslation(); if (!isOpen) return null; return ( e.stopPropagation()} >

{isActivating ? t("activateTitle") : t("deactivateTitle")}

"{propertyTitle}"

{!isActivating ? (

⚠️ {t("warning")}

{t("deactivateWarning")}

) : (

✅ {t("activateInfoTitle")}

{t("activateInfo")}

)}
); }; const PropertyViewModal = ({ isOpen, onClose, property }) => { const { t } = useTranslation(); if (!isOpen || !property) return null; return ( e.stopPropagation()} >

{property.title}

{t("addedOn")} {new Date(property.createdAt).toLocaleDateString("ar-SA")}

{property.images && property.images.length > 0 && (

{t("propertyImages")}

{property.images.map((image, index) => (
{t("imageAlt",
))}
)}

{t("basicInfo")}

{t("propertyTypeLabel")} {property.propertyTypeLabel || t("offer")}

{t("displayTypeLabel")} {property.displayType === "Daily rent" ? t("dailyRent") : property.displayType === "Monthly rent" ? t("monthlyRent") : property.displayType === "Both" ? t("dailyAndMonthly") : property.displayType === "For sale" ? t("forSale") : property.rentType === "daily" ? t("dailyRent") : property.rentType === "monthly" ? t("monthlyRent") : property.dailyPrice > 0 && property.monthlyPrice > 0 ? t("dailyAndMonthly") : property.monthlyPrice > 0 ? t("monthlyRent") : property.dailyPrice > 0 ? t("dailyRent") : property.purpose === "sale" ? t("forSale") : t("offer")}

{property.purpose === "rent" && (

{t("furnishedStatusLabel")} {property.furnished ? t("furnished") : t("unfurnished")}

)}

{t("propertyStatusLabel")} {property.status === "available" ? t("available") : t("rented")}

{property.description && (

{t("descriptionLabel")} {property.description}

)}

{t("basicInfo")}

{property.bedrooms} {t("rooms")}
{property.bathrooms} {t("bathrooms")}
{property.area} {t("sqm")}
{property.floor > 0 && (
{property.floor} {t("floor")}
)} {property.salons > 0 && (
{property.salons} {t("salons")}
)} {property.balconies > 0 && (
{property.balconies} {t("balconies")}
)} {property.bookedCount > 0 && (
{property.bookedCount} {t("bookings")}
)}

{t("location")}

{property.address || t("addressNotSpecified")} {property.city && `، ${property.city}`} {property.district && `، ${property.district}`}

{property.services && (Array.isArray(property.services) ? property.services.length > 0 : Object.keys(property.services).length > 0) && (

{t("availableServices")}

{Array.isArray(property.services) ? property.services.map((svc, i) => ( {t(serviceI18nKeys[svc]) || svc} )) : Object.entries(property.services).map(([key, value]) => { if (!value) return null; const detail = typeof value === "object" && value.detail ? value.detail : typeof value === "string" ? value : null; return ( {t(serviceI18nKeys[key]) || key} {detail && · {detail}} ); })}
)} {property.proximity && Object.keys(property.proximity).length > 0 && (

{t("proximityToServices")}

{Object.entries(property.proximity).map(([key, val]) => { if (!val) return null; const dist = typeof val === "object" ? val.distance : val; return (
{key === "School" && } {key === "Hospital" && } {key === "Restaurant" && } {key === "University" && } {key === "Park" && } {key === "Mall" && } {!["School", "Hospital", "Restaurant", "University", "Park", "Mall"].includes(key) && }
{t(proximityI18nKeys[key]) || key} {dist} {typeof dist === "number" ? t("km") : ""}
); })}
)} {property.terms && Object.keys(property.terms).length > 0 && (

{t("termsOfUse")}

{Object.entries(property.terms).map(([key, value]) => { if (!value) return null; return (
{key.startsWith("No") || key.startsWith("Only") ? : } {t(termI18nKeys[key]) || key}
); })}
)}

{t("priceInfo")}

{property.purpose === "rent" ? (
{property.dailyPrice > 0 && (

{t("dailyPriceLabel")} {Number(property.dailyPrice).toLocaleString()} {t("syp")}

)} {property.monthlyPrice > 0 && (

{t("monthlyPriceLabel")} {Number(property.monthlyPrice).toLocaleString()} {t("syp")}

)} {property.deposit > 0 && (

{t("depositLabel")} {Number(property.deposit).toLocaleString()} {t("syp")}

)}

{t("rentTypeLabel")} {property.rentType === "daily" ? t("daily") : property.rentType === "monthly" ? t("monthly") : t("dailyAndMonthly")}

{property.rating > 0 && (

{t("ratingLabel")} {Number(property.rating).toFixed(1)}

)}
) : (

{t("salePriceLabel")} {Number(property.salePrice).toLocaleString()} {t("syp")}

)}
); }; const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const { t } = useTranslation(); const [formData, setFormData] = useState({ propertyType: "apartment", furnished: false, description: "", bedrooms: 0, bathrooms: 0, floor: 0, salons: 0, balconies: 0, livingRooms: 0, area: 0, services: {}, serviceDetails: {}, terms: {}, customTerms: [], nearbySchool: "", nearbyHospital: "", nearbyRestaurant: "", nearbyUniversity: "", nearbyPark: "", nearbyMall: "", nearbyMosque: "", purpose: "rent", currencyId: 1, dailyPrice: 0, commission: "", monthlyPrice: 0, deposit: 0, rentType: "monthly", allowedPaymentPeriod: "", salePrice: 0, }); const [newCustomTerm, setNewCustomTerm] = useState(""); const [isSaving, setIsSaving] = useState(false); const [existingImages, setExistingImages] = useState([]); const [newImages, setNewImages] = useState([]); const editApiBase = process.env.NEXT_PUBLIC_API_URL || "https://45.93.137.91.nip.io/api"; const editImgUrl = (path) => { if (!path) return null; if (path.startsWith("http://") || path.startsWith("https://")) return path; return `${editApiBase}${path}`; }; useEffect(() => { if (!property || !isOpen) return; const raw = property._raw || {}; const info = raw.propertyInformation || {}; let details = {}; try { details = typeof info.detailsJSON === "object" && info.detailsJSON ? info.detailsJSON : JSON.parse(info.detailsJSON || "{}"); } catch { details = {}; } const propServices = property.services || {}; const services = {}; const serviceDetails = {}; Object.keys(serviceI18nKeys).forEach((key) => { const val = propServices[key]; if (val && typeof val === "string") { services[key] = true; serviceDetails[key] = val; } else if (val && typeof val === "object" && val.detail) { services[key] = true; serviceDetails[key] = val.detail; } else { services[key] = !!val; serviceDetails[key] = details.serviceDetails?.[key] || ""; } }); const rawSvcArray = Array.isArray(details.services) ? details.services : []; rawSvcArray.forEach((key) => { if (!(key in services)) { services[key] = true; serviceDetails[key] = details.serviceDetails?.[key] || ""; } }); const propTerms = property.terms || {}; const terms = {}; Object.keys(termI18nKeys).forEach((key) => { terms[key] = !!propTerms[key]; }); if (details.terms && typeof details.terms === "object") { Object.entries(details.terms).forEach(([key, val]) => { if (val && !(key in terms)) { terms[key] = true; } }); } const prox = property.proximity || details.nearbyDistances || {}; setFormData({ propertyType: property.propertyType || "apartment", furnished: property.furnished ?? false, description: property.description || details.description || "", bedrooms: property.bedrooms || 0, bathrooms: property.bathrooms || 0, floor: property.floor ?? details.floorNumber ?? details.floor ?? 0, salons: property.salons ?? details.numberOfSalons ?? details.salons ?? 0, balconies: property.balconies ?? details.numberOfBalconies ?? details.balconies ?? 0, livingRooms: property.livingRooms ?? details.numberOfLivingRooms ?? details.livingRooms ?? 0, area: property.area || 0, services, serviceDetails, terms, customTerms: details.customTerms || [], nearbyMosque: prox.nearbyMosque || prox.neaebymosque || "", nearbySchool: prox.School ?? prox.school ?? prox.nearbySchool ?? "", nearbyHospital: prox.Hospital ?? prox.hospital ?? prox.nearbyHospital ?? "", nearbyRestaurant: prox.Restaurant ?? prox.restaurant ?? prox.nearbyRestaurant ?? "", nearbyUniversity: prox.University ?? prox.university ?? prox.nearbyUniversity ?? "", nearbyPark: prox.Park ?? prox.park ?? prox.nearbyPark ?? "", nearbyMall: prox.Mall ?? prox.mall ?? prox.nearbyMall ?? "", purpose: property.purpose || "rent", currencyId: property.currencyId || 1, commission: property.commission || prox.commission || "", ...(property.purpose === "rent" ? { dailyPrice: property.dailyPrice || 0, monthlyPrice: property.monthlyPrice || 0, deposit: property.deposit || 0, rentType: property.rentType || "monthly", allowedPaymentPeriod: property.allowedPaymentPeriod || details.allowedPaymentPeriod || "", } : { salePrice: property.salePrice || 0 }), }); setNewCustomTerm(""); setNewImages([]); const rawImages = Array.isArray(property.images) ? property.images : Array.isArray(info.images) ? info.images : []; setExistingImages(rawImages.filter((p) => p && p.trim())); }, [property, isOpen]); const handleChange = (field, value) => { setFormData((prev) => ({ ...prev, [field]: value })); }; const handleServiceToggle = (key, checked) => { setFormData((prev) => ({ ...prev, services: { ...prev.services, [key]: checked }, })); }; const handleServiceDetail = (key, value) => { setFormData((prev) => ({ ...prev, serviceDetails: { ...prev.serviceDetails, [key]: value }, })); }; const handleTermToggle = (key, checked) => { setFormData((prev) => ({ ...prev, terms: { ...prev.terms, [key]: checked }, })); }; const addCustomTerm = () => { const term = newCustomTerm.trim(); if (!term) return; setFormData((prev) => ({ ...prev, customTerms: [...(prev.customTerms || []), term], })); setNewCustomTerm(""); }; const removeCustomTerm = (index) => { setFormData((prev) => ({ ...prev, customTerms: prev.customTerms.filter((_, i) => i !== index), })); }; const handleRemoveExistingImage = (index) => { setExistingImages((prev) => prev.filter((_, i) => i !== index)); }; const handleMoveExistingImage = (index, direction) => { setExistingImages((prev) => { const next = [...prev]; const target = index + direction; if (target < 0 || target >= next.length) return prev; [next[index], next[target]] = [next[target], next[index]]; return next; }); }; const handleAddImages = async (files) => { const validFiles = Array.from(files).filter((f) => { if (!f.type.startsWith("image/")) return false; if (f.size > 5 * 1024 * 1024) { toast.error(t("fileTooLarge") || "الصورة كبيرة جداً"); return false; } return true; }); if (validFiles.length === 0) return; const maxTotal = 10; const currentCount = existingImages.length + newImages.length; const slots = maxTotal - currentCount; if (slots <= 0) { toast.error(t("maxImagesReached") || "الحد الأقصى 10 صور"); return; } const toAdd = validFiles.slice(0, slots); const entries = toAdd.map((file) => ({ file, preview: URL.createObjectURL(file), path: null, uploading: true, })); setNewImages((prev) => [...prev, ...entries]); for (let i = 0; i < entries.length; i++) { const entry = entries[i]; try { const result = await uploadPicture(entry.file); const path = result?.value || result?.path || result?.url || result; entry.path = path; } catch { toast.error(t("uploadFailed") || "فشل رفع الصورة"); } finally { entry.uploading = false; setNewImages((prev) => [...prev]); } } }; const handleRemoveNewImage = (index) => { const entry = newImages[index]; if (entry?.preview) URL.revokeObjectURL(entry.preview); setNewImages((prev) => prev.filter((_, i) => i !== index)); }; const handleMoveNewImage = (index, direction) => { setNewImages((prev) => { const next = [...prev]; const target = index + direction; if (target < 0 || target >= next.length) return prev; [next[index], next[target]] = [next[target], next[index]]; return next; }); }; const handleSave = async () => { const errors = []; if (!formData.description?.trim()) errors.push(t("descriptionRequired") || "الوصف مطلوب"); if (formData.bedrooms < 1) errors.push(t("bedroomsRequired") || "يجب أن يكون عدد الغرف على الأقل 1"); if (formData.bathrooms < 1) errors.push(t("bathroomsRequired") || "يجب أن يكون عدد الحمامات على الأقل 1"); if (!formData.area || formData.area <= 0) errors.push(t("areaRequired") || "المساحة مطلوبة"); if (formData.purpose === "rent") { if ((!formData.dailyPrice || formData.dailyPrice <= 0) && (!formData.monthlyPrice || formData.monthlyPrice <= 0)) { errors.push(t("priceRequired") || "يجب إدخال سعر الأجر الشهري أو اليومي"); } } else if (formData.purpose === "sale") { if (!formData.salePrice || formData.salePrice <= 0) errors.push(t("priceRequired") || "السعر مطلوب"); } if (errors.length > 0) { toast.error(errors[0]); return; } setIsSaving(true); try { const uploadedPaths = newImages.filter((e) => e.path && !e.uploading).map((e) => e.path); const allImages = [...existingImages, ...uploadedPaths]; await onSave({ ...formData, _images: allImages }); } catch { setIsSaving(false); } }; if (!isOpen || !property) return null; return ( e.stopPropagation()} >

{t("editProperty")}

{t("editSubtitle")}

{/* Basic Info */}

{t("basicInfo")}

{[ { value: true, label: t("furnished") }, { value: false, label: t("unfurnished") }, ].map((opt) => ( ))}