From 4924e7c2f367e2c266a4151a117c7730d3b658a1 Mon Sep 17 00:00:00 2001 From: hamzaobed7 Date: Tue, 11 Aug 2026 02:29:54 +0300 Subject: [PATCH] fixed payment ,colors , add Mosque distance and fixed some elemnent --- app/components/BottomNav.js | 16 +- app/i18n/config.js | 11 +- app/loading.js | 6 +- app/owner/properties/add/loading.js | 14 - app/owner/properties/add/page.js | 61 +- app/owner/properties/loading.js | 14 - app/owner/properties/page.js | 1203 +++++++++------------------ app/property/[id]/PropertyDetail.js | 14 +- app/register/tenant/page.js | 2 +- app/validations/OwnerValidatoin.js | 7 +- 10 files changed, 474 insertions(+), 874 deletions(-) delete mode 100644 app/owner/properties/add/loading.js delete mode 100644 app/owner/properties/loading.js diff --git a/app/components/BottomNav.js b/app/components/BottomNav.js index 5d39f76..fbb16aa 100644 --- a/app/components/BottomNav.js +++ b/app/components/BottomNav.js @@ -24,12 +24,12 @@ export default function BottomNav({ isOwner, isOwnerOrAgent }) { ...(isOwnerOrAgent ? [ { href: "/owner/properties", label: t("myProperties"), icon: Building }, - { href: "/owner/bookings", label: "عقاراتي المحجوزة", icon: CalendarCheck }, - { href: "/reservations", label: "حجوزاتي", icon: CalendarDays }, + { href: "/owner/bookings", label: t("Myseizedproperties"), icon: CalendarCheck }, + { href: "/reservations", label: t("Mybookings"), icon: CalendarDays }, ] - : [{ href: "/booked-properties", label: "حجوزاتي", icon: CalendarDays }]), + : [{ href: "/booked-properties", label: t("Mybookings"), icon: CalendarDays }]), - { href: bookingsHref, label: "طلبات الحجز", icon: ClipboardList }, + { href: bookingsHref, label: t("Orders"), icon: ClipboardList }, { href: "/payments", label: t("payments"), icon: CreditCard }, ...(isOwnerOrAgent ? [{ href: "/owner/account-book", label: t("accountBook"), icon: BookOpenCheck }] : []), @@ -61,20 +61,16 @@ export default function BottomNav({ isOwner, isOwnerOrAgent }) { @@ -99,7 +95,7 @@ export default function BottomNav({ isOwner, isOwnerOrAgent }) { )} -
{it.label}
+
{it.label}
); })} diff --git a/app/i18n/config.js b/app/i18n/config.js index be9a31b..240ebb0 100644 --- a/app/i18n/config.js +++ b/app/i18n/config.js @@ -314,7 +314,9 @@ const resources = { /* ─── Bottom nav ─── */ payments: "Payments", - + Myseizedproperties:"Seized Properties", + Mybookings:"My bookings", + Orders:"Orders", /* ─── Footer ─── */ footerDescription: "Your trusted platform for finding and listing premium properties across Syria.", quickLinks: "Quick Links", @@ -1658,10 +1660,14 @@ const resources = { "calendar.mockTenant1": "Ahmed Mohammed", "calendar.mockTenant2": "Sara Ahmed", "calendar.mockTenant3": "Mohammed Ali", + "loading":"Loading", + "neaebymosque":"Distance to nearest mosque (km)" }, }, ar: { translation: { + "loading":"جار التحميل", + "neaebymosque":"المسافة الى اقرب جامع", /* Block*/ "blocked.fillAllFields": "يرجى تعبئة جميع الحقول المطلوبة", "blocked.reportSent": "تم إرسال الرسالة بنجاح", @@ -1776,6 +1782,7 @@ const resources = { "chooseRole.createAgentAccount": "إنشاء حساب وكيل", "chooseRole.alreadyHaveAccount": "لديك حساب بالفعل؟", + Myseizedproperties:"عقاراتي المحجوزة", /* ─── Role badges ─── */ visitor: "زائر", owner: "مالك", @@ -2032,6 +2039,8 @@ const resources = { /* ─── Bottom nav ─── */ payments: "المدفوعات", + Orders:"الطلبات", + Mybookings:"حجوزاتي", /* ─── Footer ─── */ footerDescription: "منصتك الموثوقة لإيجاد وإدراج العقارات الفاخرة في جميع أنحاء سوريا.", diff --git a/app/loading.js b/app/loading.js index 0f62f9d..4a0348a 100644 --- a/app/loading.js +++ b/app/loading.js @@ -1,8 +1,10 @@ "use client"; import { motion } from "framer-motion"; +import { useTranslation } from "react-i18next"; export default function Loading() { + const { t } = useTranslation(); return (
@@ -27,7 +29,9 @@ export default function Loading() {
-

... جاري التحميل

+

+ ... {t("loading")} +

); diff --git a/app/owner/properties/add/loading.js b/app/owner/properties/add/loading.js deleted file mode 100644 index 0c01106..0000000 --- a/app/owner/properties/add/loading.js +++ /dev/null @@ -1,14 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; - -export default function Loading() { - return ( -
- -
-

جاري التحميل...

- -
- ); -} diff --git a/app/owner/properties/add/page.js b/app/owner/properties/add/page.js index cf8e0f4..93852ec 100644 --- a/app/owner/properties/add/page.js +++ b/app/owner/properties/add/page.js @@ -141,6 +141,7 @@ export default function AddPropertyPage() { nearbyUniversity: "", nearbyPark: "", nearbyMall: "", + neaebymosque: "", roomAreaType: "Private room", roomPeopleAllowed: "", @@ -693,6 +694,7 @@ export default function AddPropertyPage() { university: formData.nearbyUniversity || "", park: formData.nearbyPark || "", mall: formData.nearbyMall || "", + mosque: formData.neaebymosque || "", }, }; @@ -747,11 +749,9 @@ export default function AddPropertyPage() { try { if (purpose === "sale") { const payload = { - - propInfo, - price: parseFloat(formData.salePrice), - deposit: parseFloat(formData.deposit) || 0, - + propInfo, + price: parseFloat(formData.salePrice), + deposit: parseFloat(formData.deposit) || 0, }; console.log("ff", payload); const res = await addSaleProperty(payload); @@ -862,7 +862,7 @@ export default function AddPropertyPage() { type="button" onClick={() => setFormData({ ...formData, propertyType: type.id })} className={`p-4 border rounded-xl flex flex-col items-center gap-2 transition-all ${ - formData.propertyType === type.id ? "border-amber-500 bg-amber-50 text-amber-700" : "border-gray-200 hover:border-amber-200 hover:bg-amber-50/50" + formData.propertyType === type.id ? "border-amber-500 bg-[#1E293B] text-amber-700" : "border-gray-200 hover:border-amber-200 hover:bg-amber-50/50" }`} > @@ -895,7 +895,7 @@ export default function AddPropertyPage() { toggleService(service.id)} className="w-4 h-4 text-amber-500 rounded" /> + toggleService(service.id)} className="w-4 h-4 bg-[#1E293B] text-amber-500 rounded" /> {service.label} {isSelected && ( -
+
updateServiceDetail(service.id, e.target.value)} - className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-amber-500" + className="w-full px-3 py-2 border bg-[#1E293B] border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-amber-500" placeholder={t("addProperty.serviceDetailPlaceholder")} />
@@ -1060,7 +1060,7 @@ export default function AddPropertyPage() {
-
+

{t("addProperty.nearbyServicesTitle")} @@ -1090,6 +1090,19 @@ export default function AddPropertyPage() { placeholder={t("addProperty.nearbyPlaceholder")} />

+
+ + setFormData({ ...formData, neaebymosque: e.target.value })} + className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500" + placeholder={t("addProperty.nearbyPlaceholder")} + /> +
toggleTerm(term.id)} className="hidden" /> @@ -1208,7 +1221,7 @@ export default function AddPropertyPage() { {step === 3 && purpose === "sale" && (
-
+

{t("addProperty.salePriceTitle")}

@@ -1234,7 +1247,7 @@ export default function AddPropertyPage() { onKeyDown={(e) => { if (["-", "e", "E", "+"].includes(e.key)) e.preventDefault(); }} - className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${errors.salePrice ? "border-red-500" : "border-gray-300"}`} + className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${errors.salePrice ? "border-red-500" : "border-gray-300"}`} placeholder={t("addProperty.salePricePlaceholder")} />
@@ -1248,7 +1261,7 @@ export default function AddPropertyPage() { setSelectedCurrencyId(parseInt(e.target.value))} - className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500" + className="w-full px-4 py-3 border bg-[#1E293B] border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500" > @@ -1506,8 +1519,8 @@ export default function AddPropertyPage() { )} {step === 4 && ( - -
+ +
@@ -1515,7 +1528,7 @@ export default function AddPropertyPage() {

{t("addProperty.locationAndImagesSubtitle")}

-
+
@@ -1568,7 +1581,7 @@ export default function AddPropertyPage() { {t("addProperty.searchButton")}
-
+
{t("addProperty.clickMapHint")}
@@ -1589,7 +1602,7 @@ export default function AddPropertyPage() { {t("addProperty.confirmLocation")} ) : ( -
+
{t("addProperty.clickMapHint")}
diff --git a/app/owner/properties/loading.js b/app/owner/properties/loading.js deleted file mode 100644 index 0c01106..0000000 --- a/app/owner/properties/loading.js +++ /dev/null @@ -1,14 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; - -export default function Loading() { - return ( -
- -
-

جاري التحميل...

- -
- ); -} diff --git a/app/owner/properties/page.js b/app/owner/properties/page.js index 3776376..b687d1b 100644 --- a/app/owner/properties/page.js +++ b/app/owner/properties/page.js @@ -55,18 +55,10 @@ import { } 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 { 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", @@ -105,12 +97,7 @@ const proximityI18nKeys = { BusStation: "proximity.busStation", }; -const DeleteConfirmationModal = ({ - isOpen, - onClose, - onConfirm, - propertyTitle, -}) => { +const DeleteConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle }) => { const { t } = useTranslation(); if (!isOpen) return null; @@ -133,27 +120,17 @@ const DeleteConfirmationModal = ({
-

{t('deleteConfirmTitle')}

-

- {t('deleteConfirmMessage', { title: propertyTitle })} -

-

- {t('deleteIrreversible')} -

+

{t("deleteConfirmTitle")}

+

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

+

{t("deleteIrreversible")}

- -
@@ -161,13 +138,7 @@ const DeleteConfirmationModal = ({ ); }; -const DeactivateConfirmationModal = ({ - isOpen, - onClose, - onConfirm, - propertyTitle, - isActivating, -}) => { +const DeactivateConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle, isActivating }) => { const { t } = useTranslation(); if (!isOpen) return null; @@ -190,49 +161,32 @@ const DeactivateConfirmationModal = ({
-

- {isActivating ? t('activateTitle') : t('deactivateTitle')} -

+

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

"{propertyTitle}"

{!isActivating ? (
-

- ⚠️ {t('warning')} -

-

- {t('deactivateWarning')} -

+

⚠️ {t("warning")}

+

{t("deactivateWarning")}

) : (
-

- ✅ {t('activateInfoTitle')} -

-

- {t('activateInfo')} -

+

✅ {t("activateInfoTitle")}

+

{t("activateInfo")}

)}
-
@@ -263,14 +217,11 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => {

{property.title}

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

-
@@ -278,20 +229,11 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => {
{property.images && property.images.length > 0 && (
-

- {t('propertyImages')} -

+

{t("propertyImages")}

{property.images.map((image, index) => ( -
- {t('imageAlt', +
+ {t("imageAlt",
))}
@@ -300,117 +242,101 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => {
-

{t('basicInfo')}

+

{t("basicInfo")}

- {t('propertyTypeLabel')} - - {property.propertyTypeLabel || t('offer')} - + {t("propertyTypeLabel")} + {property.propertyTypeLabel || t("offer")}

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

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

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

)}

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

{property.description && (

- {t('descriptionLabel')} - - {property.description} - + {t("descriptionLabel")} + {property.description}

)}
-

{t('basicInfo')}

+

{t("basicInfo")}

{property.bedrooms} - {t('rooms')} + {t("rooms")}
- - {property.bathrooms} - - {t('bathrooms')} + {property.bathrooms} + {t("bathrooms")}
{property.area} - {t('sqm')} + {t("sqm")}
{property.floor > 0 && (
{property.floor} - {t('floor')} + {t("floor")}
)} {property.salons > 0 && (
{property.salons} - {t('salons')} + {t("salons")}
)} {property.balconies > 0 && (
- - {property.balconies} - - {t('balconies')} + {property.balconies} + {t("balconies")}
)} {property.bookedCount > 0 && (
- - {property.bookedCount} - - {t('bookings')} + {property.bookedCount} + {t("bookings")}
)}
@@ -420,79 +346,60 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => {

- {t('location')} + {t("location")}

- {property.address || t('addressNotSpecified')} + {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} + {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}} - )) - : 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')}

+

{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) && } + {!["School", "Hospital", "Restaurant", "University", "Park", "Mall"].includes(key) && }
{t(proximityI18nKeys[key]) || key} - {dist} {typeof dist === "number" ? t('km') : ""} + + {dist} {typeof dist === "number" ? t("km") : ""} +
); @@ -503,23 +410,14 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => { {property.terms && Object.keys(property.terms).length > 0 && (
-

{t('termsOfUse')}

+

{t("termsOfUse")}

{Object.entries(property.terms).map(([key, value]) => { if (!value) return null; return ( -
- {key.startsWith("No") || key.startsWith("Only") ? ( - - ) : ( - - )} - - {t(termI18nKeys[key]) || key} - +
+ {key.startsWith("No") || key.startsWith("Only") ? : } + {t(termI18nKeys[key]) || key}
); })} @@ -528,56 +426,50 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => { )}
-

{t('priceInfo')}

+

{t("priceInfo")}

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

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

)} {property.monthlyPrice > 0 && (

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

)} {property.deposit > 0 && (

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

)}

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

{property.rating > 0 && (

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

)}
) : (

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

)} @@ -591,9 +483,9 @@ const PropertyViewModal = ({ isOpen, onClose, property }) => { const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const { t } = useTranslation(); const [formData, setFormData] = useState({ - propertyType: 'apartment', + propertyType: "apartment", furnished: false, - description: '', + description: "", bedrooms: 0, bathrooms: 0, floor: 0, @@ -605,31 +497,30 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { serviceDetails: {}, terms: {}, customTerms: [], - nearbySchool: '', - nearbyHospital: '', - nearbyRestaurant: '', - nearbyUniversity: '', - nearbyPark: '', - nearbyMall: '', - purpose: 'rent', + nearbySchool: "", + nearbyHospital: "", + nearbyRestaurant: "", + nearbyUniversity: "", + nearbyPark: "", + nearbyMall: "", + purpose: "rent", currencyId: 1, dailyPrice: 0, monthlyPrice: 0, deposit: 0, - rentType: 'monthly', - allowedPaymentPeriod: '', + rentType: "monthly", + allowedPaymentPeriod: "", salePrice: 0, }); - const [newCustomTerm, setNewCustomTerm] = useState(''); + 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 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; + if (path.startsWith("http://") || path.startsWith("https://")) return path; return `${editApiBase}${path}`; }; @@ -639,10 +530,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const info = raw.propertyInformation || {}; let details = {}; try { - details = - typeof info.detailsJSON === 'object' && info.detailsJSON - ? info.detailsJSON - : JSON.parse(info.detailsJSON || '{}'); + details = typeof info.detailsJSON === "object" && info.detailsJSON ? info.detailsJSON : JSON.parse(info.detailsJSON || "{}"); } catch { details = {}; } @@ -653,15 +541,15 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { Object.keys(serviceI18nKeys).forEach((key) => { const val = propServices[key]; - if (val && typeof val === 'string') { + if (val && typeof val === "string") { services[key] = true; serviceDetails[key] = val; - } else if (val && typeof val === 'object' && val.detail) { + } else if (val && typeof val === "object" && val.detail) { services[key] = true; serviceDetails[key] = val.detail; } else { services[key] = !!val; - serviceDetails[key] = details.serviceDetails?.[key] || ''; + serviceDetails[key] = details.serviceDetails?.[key] || ""; } }); @@ -669,7 +557,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { rawSvcArray.forEach((key) => { if (!(key in services)) { services[key] = true; - serviceDetails[key] = details.serviceDetails?.[key] || ''; + serviceDetails[key] = details.serviceDetails?.[key] || ""; } }); @@ -678,7 +566,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { Object.keys(termI18nKeys).forEach((key) => { terms[key] = !!propTerms[key]; }); - if (details.terms && typeof details.terms === 'object') { + if (details.terms && typeof details.terms === "object") { Object.entries(details.terms).forEach(([key, val]) => { if (val && !(key in terms)) { terms[key] = true; @@ -689,52 +577,41 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const prox = property.proximity || details.nearbyDistances || {}; setFormData({ - propertyType: property.propertyType || 'apartment', + propertyType: property.propertyType || "apartment", furnished: property.furnished ?? false, - description: property.description || details.description || '', + 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, + 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', + 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' + ...(property.purpose === "rent" ? { dailyPrice: property.dailyPrice || 0, monthlyPrice: property.monthlyPrice || 0, deposit: property.deposit || 0, - rentType: property.rentType || 'monthly', - allowedPaymentPeriod: - property.allowedPaymentPeriod || - details.allowedPaymentPeriod || - '', + rentType: property.rentType || "monthly", + allowedPaymentPeriod: property.allowedPaymentPeriod || details.allowedPaymentPeriod || "", } : { salePrice: property.salePrice || 0 }), }); - setNewCustomTerm(''); + setNewCustomTerm(""); setNewImages([]); - const rawImages = Array.isArray(property.images) - ? property.images - : Array.isArray(info.images) - ? info.images - : []; + const rawImages = Array.isArray(property.images) ? property.images : Array.isArray(info.images) ? info.images : []; setExistingImages(rawImages.filter((p) => p && p.trim())); }, [property, isOpen]); @@ -770,7 +647,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { ...prev, customTerms: [...(prev.customTerms || []), term], })); - setNewCustomTerm(''); + setNewCustomTerm(""); }; const removeCustomTerm = (index) => { @@ -796,9 +673,9 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const handleAddImages = async (files) => { const validFiles = Array.from(files).filter((f) => { - if (!f.type.startsWith('image/')) return false; + if (!f.type.startsWith("image/")) return false; if (f.size > 5 * 1024 * 1024) { - toast.error(t('fileTooLarge') || 'الصورة كبيرة جداً'); + toast.error(t("fileTooLarge") || "الصورة كبيرة جداً"); return false; } return true; @@ -808,7 +685,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const currentCount = existingImages.length + newImages.length; const slots = maxTotal - currentCount; if (slots <= 0) { - toast.error(t('maxImagesReached') || 'الحد الأقصى 10 صور'); + toast.error(t("maxImagesReached") || "الحد الأقصى 10 صور"); return; } const toAdd = validFiles.slice(0, slots); @@ -826,7 +703,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { const path = result?.value || result?.path || result?.url || result; entry.path = path; } catch { - toast.error(t('uploadFailed') || 'فشل رفع الصورة'); + toast.error(t("uploadFailed") || "فشل رفع الصورة"); } finally { entry.uploading = false; setNewImages((prev) => [...prev]); @@ -852,16 +729,16 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { 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.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') || 'يجب إدخال سعر الأجر الشهري أو اليومي'); + errors.push(t("priceRequired") || "يجب إدخال سعر الأجر الشهري أو اليومي"); } - } else if (formData.purpose === 'sale') { - if (!formData.salePrice || formData.salePrice <= 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]); @@ -869,9 +746,7 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { } setIsSaving(true); try { - const uploadedPaths = newImages - .filter((e) => e.path && !e.uploading) - .map((e) => e.path); + const uploadedPaths = newImages.filter((e) => e.path && !e.uploading).map((e) => e.path); const allImages = [...existingImages, ...uploadedPaths]; await onSave({ ...formData, _images: allImages }); } catch { @@ -898,15 +773,10 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => { >
-

{t('editProperty')}

-

- {t('editSubtitle')} -

+

{t("editProperty")}

+

{t("editSubtitle")}

-
@@ -914,66 +784,45 @@ const PropertyEditModal = ({ isOpen, onClose, property, onSave }) => {
{/* Basic Info */}
-

- {t('basicInfo')} -

+

{t("basicInfo")}

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