"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, TrendingUp, Users, FileText, Image as ImageIcon, CheckCircle, XCircle, AlertCircle, ChevronRight, ChevronLeft, Loader2, Clock, Wifi, Zap, Flame, Droplets, Cigarette, Dog, Music, Warehouse, Layers, Sofa, DoorOpen, Wind, Pencil, Save, X, Star, Ban, Check, School, Hospital, Store, GraduationCap, TreePine, } from "lucide-react"; import toast, { Toaster } from "react-hot-toast"; import AuthService from "../../services/AuthService"; import { buildRentPropertyPayload, getMyRentListings, getMySaleListings, editRentProperty, editSaleProperty, updateRentPropertyStatus, updateSalePropertyStatus, uploadPicture } 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 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: "", purpose: "rent", currencyId: 1, dailyPrice: 0, 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 || [], 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, ...(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) => ( ))}