diff --git a/app/property/[id]/PropertyDetail.js b/app/property/[id]/PropertyDetail.js
index 599d82d..cf96cfd 100644
--- a/app/property/[id]/PropertyDetail.js
+++ b/app/property/[id]/PropertyDetail.js
@@ -1,91 +1,213 @@
-'use client';
+"use client";
-import { useState, useEffect, useMemo } from 'react';
-import { motion, AnimatePresence } from 'framer-motion';
-import toast, { Toaster } from 'react-hot-toast';
-import Link from 'next/link';
-import { useParams, useRouter } from 'next/navigation';
+import { useState, useEffect, useMemo } from "react";
+import { motion, AnimatePresence } from "framer-motion";
+import toast, { Toaster } from "react-hot-toast";
+import Link from "next/link";
+import { useParams, useRouter } from "next/navigation";
import {
- MapPin, Bed, Bath, Square, DollarSign, Heart, Share2,
- Phone, Mail, MessageCircle, Calendar, Shield, Star,
- ChevronLeft, ChevronRight, Check, X, Wifi, Car, Wind,
- Camera, Home, Building2, Users, Clock, FileText,
- LogIn, Loader2, ArrowLeft, ImageIcon, ChevronDown,
- Layers, Sofa, DoorOpen, School, Hospital, Store,
- TreePine, Building, GraduationCap, ExternalLink,
- Smile, Ban, Wine, Dog, CassetteTape, Info
-} from 'lucide-react';
-import { getRentProperty, getSaleProperty, getSalePropertyById, bookReservation, getAvailableDateRanges, getOwnerContactInformation, getMyRentListings, getMySaleListings } from '../../utils/api';
-import AuthService from '../../services/AuthService';
-import { useFavorites } from '@/app/contexts/FavoritesContext';
-import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from '../../enums';
-import PropertyRatingList from '@/app/components/ratings/PropertyRatingList';
-import { getPropertyAverageRating } from '../../utils/ratings';
-import dynamic from 'next/dynamic';
-import 'leaflet/dist/leaflet.css';
+ MapPin,
+ Bed,
+ Bath,
+ Square,
+ DollarSign,
+ Heart,
+ Share2,
+ Phone,
+ Mail,
+ MessageCircle,
+ Calendar,
+ Shield,
+ Star,
+ ChevronLeft,
+ ChevronRight,
+ Check,
+ X,
+ Wifi,
+ Car,
+ Wind,
+ Camera,
+ Home,
+ Building2,
+ Users,
+ Clock,
+ FileText,
+ LogIn,
+ Loader2,
+ ArrowLeft,
+ ImageIcon,
+ ChevronDown,
+ Layers,
+ Sofa,
+ DoorOpen,
+ School,
+ Hospital,
+ Store,
+ TreePine,
+ Building,
+ GraduationCap,
+ ExternalLink,
+ Smile,
+ Ban,
+ Wine,
+ Dog,
+ CassetteTape,
+ Info,
+} from "lucide-react";
+import {
+ getRentProperty,
+ getSaleProperty,
+ getSalePropertyById,
+ bookReservation,
+ getAvailableDateRanges,
+ getOwnerContactInformation,
+ getMyRentListings,
+ getMySaleListings,
+} from "../../utils/api";
+import AuthService from "../../services/AuthService";
+import { useFavorites } from "@/app/contexts/FavoritesContext";
+import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from "../../enums";
+import PropertyRatingList from "@/app/components/ratings/PropertyRatingList";
+import { getPropertyAverageRating } from "../../utils/ratings";
+import dynamic from "next/dynamic";
+import "leaflet/dist/leaflet.css";
-const MapContainer = dynamic(() => import('react-leaflet').then(m => m.MapContainer), { ssr: false });
-const TileLayer = dynamic(() => import('react-leaflet').then(m => m.TileLayer), { ssr: false });
-const Marker = dynamic(() => import('react-leaflet').then(m => m.Marker), { ssr: false });
-const Popup = dynamic(() => import('react-leaflet').then(m => m.Popup), { ssr: false });
+const MapContainer = dynamic(
+ () => import("react-leaflet").then((m) => m.MapContainer),
+ { ssr: false },
+);
+const TileLayer = dynamic(
+ () => import("react-leaflet").then((m) => m.TileLayer),
+ { ssr: false },
+);
+const Marker = dynamic(() => import("react-leaflet").then((m) => m.Marker), {
+ ssr: false,
+});
+const Popup = dynamic(() => import("react-leaflet").then((m) => m.Popup), {
+ ssr: false,
+});
function formatCurrency(amount) {
- if (!amount || isNaN(amount)) return '0';
- return Number(amount).toLocaleString('ar-SA');
+ if (!amount || isNaN(amount)) return "0";
+ return Number(amount).toLocaleString("ar-SA");
}
function buildImageUrl(img) {
- if (!img) return '';
- const apiBase = typeof window !== 'undefined'
- ? (process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api')
- : '';
- if (img.startsWith('http')) return img;
- return `${apiBase}${img.startsWith('/') ? '' : '/Pictures/'}${img}`;
+ if (!img) return "";
+ const apiBase =
+ typeof window !== "undefined"
+ ? process.env.NEXT_PUBLIC_API_URL || "https://45.93.137.91.nip.io/api"
+ : "";
+ if (img.startsWith("http")) return img;
+ return `${apiBase}${img.startsWith("/") ? "" : "/Pictures/"}${img}`;
}
const serviceLabels = {
- Electricity: 'كهرباء', Internet: 'إنترنت', Heating: 'تدفئة', Water: 'ماء',
- Pool: 'مسبح', PrivateGarden: 'حديقة خاصة', Parking: 'موقف سيارات',
- Security247: 'حراسة 24 س', CentralHeating: 'تدفئة مركزية',
- CentralAirConditioning: 'تكييف مركزي', EquippedKitchen: 'مطبخ مجهز',
- MaidsRoom: 'غرفة خادمة', Elevator: 'مصعد', Gym: 'نادي رياضي',
- Sauna: 'ساونا', Jacuzzi: 'جاكوزي', Balcony: 'بلكونة',
- Rooftop: 'سطح', Furnished: 'مفروش', AirConditioning: 'تكييف',
- SatelliteTV: 'تلفاز', Fireplace: 'مدفأة', StudyRoom: 'غرفة دراسة',
- Storage: 'مستودع', Laundry: 'غرفة غسيل', SmartHome: 'منزل ذكي',
+ Electricity: "كهرباء",
+ Internet: "إنترنت",
+ Heating: "تدفئة",
+ Water: "ماء",
+ Pool: "مسبح",
+ PrivateGarden: "حديقة خاصة",
+ Parking: "موقف سيارات",
+ Security247: "حراسة 24 س",
+ CentralHeating: "تدفئة مركزية",
+ CentralAirConditioning: "تكييف مركزي",
+ EquippedKitchen: "مطبخ مجهز",
+ MaidsRoom: "غرفة خادمة",
+ Elevator: "مصعد",
+ Gym: "نادي رياضي",
+ Sauna: "ساونا",
+ Jacuzzi: "جاكوزي",
+ Balcony: "بلكونة",
+ Rooftop: "سطح",
+ Furnished: "مفروش",
+ AirConditioning: "تكييف",
+ SatelliteTV: "تلفاز",
+ Fireplace: "مدفأة",
+ StudyRoom: "غرفة دراسة",
+ Storage: "مستودع",
+ Laundry: "غرفة غسيل",
+ SmartHome: "منزل ذكي",
};
const termLabels = {
- NoSmoking: 'ممنوع التدخين', NoAnimals: 'ممنوع الحيوانات الأليفة',
- NoParties: 'ممنوع الحفلات', NoAlcohol: 'ممنوع الكحول',
- SuitableForChildren: 'مناسب للأطفال', SuitableForFamilies: 'مناسب للعائلات',
- SuitableForStudents: 'مناسب للطلاب', SuitableForElderly: 'مناسب لكبار السن',
- OnlyFemales: 'إناث فقط', OnlyMales: 'ذكور فقط',
+ NoSmoking: "ممنوع التدخين",
+ NoAnimals: "ممنوع الحيوانات الأليفة",
+ NoParties: "ممنوع الحفلات",
+ NoAlcohol: "ممنوع الكحول",
+ SuitableForChildren: "مناسب للأطفال",
+ SuitableForFamilies: "مناسب للعائلات",
+ SuitableForStudents: "مناسب للطلاب",
+ SuitableForElderly: "مناسب لكبار السن",
+ OnlyFemales: "إناث فقط",
+ OnlyMales: "ذكور فقط",
};
const proximityLabels = {
- School: 'مدرسة', Hospital: 'مستشفى', Restaurant: 'مطعم',
- University: 'جامعة', Park: 'حديقة', Mall: 'مركز تسوق',
- Supermarket: 'سوبر ماركت', Pharmacy: 'صيدلية', Mosque: 'مسجد',
- Bank: 'بنك', Airport: 'مطار', BusStation: 'موقف باص',
+ School: "مدرسة",
+ Hospital: "مستشفى",
+ Restaurant: "مطعم",
+ University: "جامعة",
+ Park: "حديقة",
+ Mall: "مركز تسوق",
+ Supermarket: "سوبر ماركت",
+ Pharmacy: "صيدلية",
+ Mosque: "مسجد",
+ Bank: "بنك",
+ Airport: "مطار",
+ BusStation: "موقف باص",
};
function mapApiDetail(item) {
if (!item) return null;
const info = item.propertyInformation || {};
- const details = typeof info.detailsJSON === 'object' && info.detailsJSON ? info.detailsJSON : (() => { try { return JSON.parse(info.detailsJSON || '{}'); } catch { return {}; } })();
+ const details =
+ typeof info.detailsJSON === "object" && info.detailsJSON
+ ? info.detailsJSON
+ : (() => {
+ try {
+ return JSON.parse(info.detailsJSON || "{}");
+ } catch {
+ return {};
+ }
+ })();
const isRent = item.dailyRent != null || item.monthlyRent != null;
const dailyPrice = item.dailyRent || 0;
const monthlyPrice = item.monthlyRent || 0;
const salePrice = item.price || 0;
- const price = isRent ? (monthlyPrice || dailyPrice) : salePrice;
- const priceUnit = isRent ? (monthlyPrice ? 'monthly' : 'daily') : 'sale';
+ const price = isRent ? monthlyPrice || dailyPrice : salePrice;
+ const priceUnit = isRent ? (monthlyPrice ? "monthly" : "daily") : "sale";
- const propType = BuildingTypeKeys[info.buildingType] ?? BuildingTypeKeys[item.type] ?? 'apartment';
- const typeLabel = { apartment: 'شقة', villa: 'فيلا', house: 'بيت', sweet: 'سويت', studio: 'استوديو', office: 'مكتب', shop: 'متجر', warehouse: 'مستودع', farms: 'مزرعة', room: 'غرفة ضمن شقة' }[propType] || 'عقار';
- const status = PropertyStatusKeys[info.status] ?? PropertyStatusKeys[item.status] ?? 'available';
- const statusLabel = { available: 'متاح', booked: 'محجوز', notAvailable: 'غير متاح', maintenance: 'صيانة' }[status] || 'متاح';
+ const propType =
+ BuildingTypeKeys[info.buildingType] ??
+ BuildingTypeKeys[item.type] ??
+ "apartment";
+ const typeLabel =
+ {
+ apartment: "شقة",
+ villa: "فيلا",
+ house: "بيت",
+ sweet: "سويت",
+ studio: "استوديو",
+ office: "مكتب",
+ shop: "متجر",
+ warehouse: "مستودع",
+ farms: "مزرعة",
+ room: "غرفة ضمن شقة",
+ }[propType] || "عقار";
+ const status =
+ PropertyStatusKeys[info.status] ??
+ PropertyStatusKeys[item.status] ??
+ "available";
+ const statusLabel =
+ {
+ available: "متاح",
+ booked: "محجوز",
+ notAvailable: "غير متاح",
+ maintenance: "صيانة",
+ }[status] || "متاح";
const rawImages = Array.isArray(info.images) ? info.images : [];
const photosFallback = Array.isArray(details.photos) ? details.photos : [];
@@ -94,18 +216,29 @@ function mapApiDetail(item) {
// Normalize services: Flutter sends list of strings or object with boolean values
const rawServices = details.services || {};
- const serviceList = Array.isArray(rawServices) ? rawServices : Object.keys(rawServices).filter(k => rawServices[k]);
+ const serviceList = Array.isArray(rawServices)
+ ? rawServices
+ : Object.keys(rawServices).filter((k) => rawServices[k]);
const serviceDetails = details.serviceDetails || {};
const services = {};
- serviceList.forEach(s => { services[s] = serviceDetails[s] || true; });
+ serviceList.forEach((s) => {
+ services[s] = serviceDetails[s] || true;
+ });
const rawTerms = details.terms || {};
- const terms = Array.isArray(rawTerms) ? rawTerms.reduce((acc, t) => ({ ...acc, [t]: true }), {}) : rawTerms;
+ const terms = Array.isArray(rawTerms)
+ ? rawTerms.reduce((acc, t) => ({ ...acc, [t]: true }), {})
+ : rawTerms;
// Try multiple key aliases like Flutter does
const floor = details.floorNumber ?? details.floor ?? 0;
- const salons = details.numberOfSalons ?? details.salonsCount ?? details.salons ?? 0;
- const balconies = details.numberOfBalconies ?? details.balconiesCount ?? details.balconies ?? 0;
+ const salons =
+ details.numberOfSalons ?? details.salonsCount ?? details.salons ?? 0;
+ const balconies =
+ details.numberOfBalconies ??
+ details.balconiesCount ??
+ details.balconies ??
+ 0;
const rawProximity = details.nearbyDistances || details.proximity || {};
const proximity = {};
Object.entries(rawProximity).forEach(([k, v]) => {
@@ -115,15 +248,25 @@ function mapApiDetail(item) {
});
const roomDetails = details.room || details.roomDetails || {};
- const displayType = details.displayType || (isRent ? (monthlyPrice && dailyPrice ? 'Both' : monthlyPrice ? 'Monthly' : 'Daily') : 'Sale');
- const propertyCondition = details.propertyCondition || '';
- const furnished = propertyCondition.toLowerCase().includes('furniture') ? propertyCondition.toLowerCase() === 'withfurniture' : !!item.isFurnished;
+ const displayType =
+ details.displayType ||
+ (isRent
+ ? monthlyPrice && dailyPrice
+ ? "Both"
+ : monthlyPrice
+ ? "Monthly"
+ : "Daily"
+ : "Sale");
+ const propertyCondition = details.propertyCondition || "";
+ const furnished = propertyCondition.toLowerCase().includes("furniture")
+ ? propertyCondition.toLowerCase() === "withfurniture"
+ : !!item.isFurnished;
return {
id: item.id,
propertyInformationId: info.id,
title: details.description || info.address || `عقار #${item.id}`,
- description: details.description || info.description || '',
+ description: details.description || info.description || "",
type: propType,
typeLabel,
price,
@@ -134,8 +277,8 @@ function mapApiDetail(item) {
propertyCondition,
furnished,
location: {
- city: extractCity(info.address) || 'دمشق',
- address: info.address || '',
+ city: extractCity(info.address) || "دمشق",
+ address: info.address || "",
lat: parseFloat(info.cordsX) || 0,
lng: parseFloat(info.cordsY) || 0,
},
@@ -173,17 +316,21 @@ export default function PropertyDetailsPage() {
const [loading, setLoading] = useState(true);
const [currentImage, setCurrentImage] = useState(0);
const [showLoginDialog, setShowLoginDialog] = useState(false);
- const [bookingDates, setBookingDates] = useState({ start: '', end: '' });
+ const [bookingDates, setBookingDates] = useState({ start: "", end: "" });
const [bookingLoading, setBookingLoading] = useState(false);
const [bookingError, setBookingError] = useState(null);
const [bookingSuccess, setBookingSuccess] = useState(false);
const [availableRanges, setAvailableRanges] = useState([]);
- const [bookingStep, setBookingStep] = useState('entry');
+ const [bookingStep, setBookingStep] = useState("entry");
const [selectedStart, setSelectedStart] = useState(null);
const [selectedEnd, setSelectedEnd] = useState(null);
- const [calendarMonth, setCalendarMonth] = useState(() => new Date().getMonth());
- const [calendarYear, setCalendarYear] = useState(() => new Date().getFullYear());
- const [pricingMode, setPricingMode] = useState('daily');
+ const [calendarMonth, setCalendarMonth] = useState(() =>
+ new Date().getMonth(),
+ );
+ const [calendarYear, setCalendarYear] = useState(() =>
+ new Date().getFullYear(),
+ );
+ const [pricingMode, setPricingMode] = useState("daily");
const [isOwnProperty, setIsOwnProperty] = useState(false);
const [favLoading, setFavLoading] = useState(false);
const [avgRating, setAvgRating] = useState(null);
@@ -199,9 +346,20 @@ export default function PropertyDetailsPage() {
async function fetchProperty() {
try {
let data = null;
- try { data = await getRentProperty(id); } catch {}
- if (!data) { try { data = await getSalePropertyById(id) || await getSaleProperty(id); } catch {} }
- if (!data) { try { data = await getSaleProperty(id); } catch {} }
+ try {
+ data = await getRentProperty(id);
+ } catch {}
+ if (!data) {
+ try {
+ data =
+ (await getSalePropertyById(id)) || (await getSaleProperty(id));
+ } catch {}
+ }
+ if (!data) {
+ try {
+ data = await getSaleProperty(id);
+ } catch {}
+ }
if (data) {
const mapped = mapApiDetail(data);
@@ -209,13 +367,14 @@ export default function PropertyDetailsPage() {
if (mapped) fetchAvgRating(mapped.id);
if (mapped && mapped.isRent) {
try {
- const propInfoId = mapped._raw?.propertyInformationId || mapped.id;
+ const propInfoId =
+ mapped._raw?.propertyInformationId || mapped.id;
const ranges = await getAvailableDateRanges(propInfoId);
if (ranges && Array.isArray(ranges)) {
setAvailableRanges(ranges);
}
} catch (e) {
- console.warn('Failed to fetch date ranges', e);
+ console.warn("Failed to fetch date ranges", e);
}
}
// Check if current user owns this property via their own listings
@@ -227,9 +386,11 @@ export default function PropertyDetailsPage() {
]);
const myPropIds = new Set();
const collectIds = (result) => {
- if (result.status !== 'fulfilled' || !result.value) return;
- const list = Array.isArray(result.value) ? result.value : [result.value];
- list.filter(Boolean).forEach(p => {
+ if (result.status !== "fulfilled" || !result.value) return;
+ const list = Array.isArray(result.value)
+ ? result.value
+ : [result.value];
+ list.filter(Boolean).forEach((p) => {
const info = p.propertyInformation || {};
if (info.id) myPropIds.add(Number(info.id));
if (p.id) myPropIds.add(Number(p.id));
@@ -238,16 +399,19 @@ export default function PropertyDetailsPage() {
collectIds(myRent);
collectIds(mySale);
const propInfoId = mapped._raw?.propertyInformation?.id;
- if (myPropIds.has(Number(mapped.id)) || (propInfoId && myPropIds.has(Number(propInfoId)))) {
+ if (
+ myPropIds.has(Number(mapped.id)) ||
+ (propInfoId && myPropIds.has(Number(propInfoId)))
+ ) {
setIsOwnProperty(true);
}
} catch (e) {
- console.warn('[OwnerCheck] failed:', e);
+ console.warn("[OwnerCheck] failed:", e);
}
}
}
} catch (err) {
- console.error('[PropertyDetail] Failed:', err);
+ console.error("[PropertyDetail] Failed:", err);
} finally {
setLoading(false);
}
@@ -266,16 +430,21 @@ export default function PropertyDetailsPage() {
const fetchContactInfo = async () => {
if (!property) return;
try {
- const info = await getOwnerContactInformation(property._raw?.propertyInformationId || property.id);
+ const info = await getOwnerContactInformation(
+ property._raw?.propertyInformationId || property.id,
+ );
setContactInfo(info);
setShowContact(true);
} catch (err) {
- toast.error('فشل تحميل معلومات الاتصال');
+ toast.error("فشل تحميل معلومات الاتصال");
}
};
const handleFavorite = async () => {
- if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; }
+ if (!AuthService.isAuthenticated()) {
+ setShowLoginDialog(true);
+ return;
+ }
if (!property) return;
setFavLoading(true);
try {
@@ -285,42 +454,62 @@ export default function PropertyDetailsPage() {
await addFavorite(property.id);
}
} catch (err) {
- toast.error('حدث خطأ');
+ toast.error("حدث خطأ");
} finally {
setFavLoading(false);
}
};
const handleBookNow = async () => {
- if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; }
+ if (!AuthService.isAuthenticated()) {
+ setShowLoginDialog(true);
+ return;
+ }
if (!bookingDates.start || !bookingDates.end) {
- setBookingError('يرجى تحديد تاريخ البداية والنهاية');
+ setBookingError("يرجى تحديد تاريخ البداية والنهاية");
return;
}
setBookingLoading(true);
setBookingError(null);
try {
- await bookReservation(property._raw?.propertyInformationId || property.id, bookingDates.start, bookingDates.end);
+ await bookReservation(
+ property._raw?.propertyInformationId || property.id,
+ bookingDates.start,
+ bookingDates.end,
+ );
setBookingSuccess(true);
- toast.success('تم إرسال طلب الحجز بنجاح');
+ toast.success("تم إرسال طلب الحجز بنجاح");
} catch (err) {
- setBookingError(err.message || 'فشل الحجز');
+ setBookingError(err.message || "فشل الحجز");
} finally {
setBookingLoading(false);
}
};
- const MONTHS_AR = ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'];
- const DAYS_AR = ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'];
+ const MONTHS_AR = [
+ "يناير",
+ "فبراير",
+ "مارس",
+ "أبريل",
+ "مايو",
+ "يونيو",
+ "يوليو",
+ "أغسطس",
+ "سبتمبر",
+ "أكتوبر",
+ "نوفمبر",
+ "ديسمبر",
+ ];
+ const DAYS_AR = ["ح", "ن", "ث", "ر", "خ", "ج", "س"];
const availableDatesSet = useMemo(() => {
const dates = new Set();
if (!Array.isArray(availableRanges)) return dates;
- availableRanges.forEach(r => {
+ availableRanges.forEach((r) => {
const start = new Date(r.startDate || r.start);
const end = new Date(r.endDate || r.end);
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
- dates.add(d.toISOString().split('T')[0]);
+ dates.add(d.toISOString().split("T")[0]);
}
});
return dates;
@@ -334,39 +523,42 @@ export default function PropertyDetailsPage() {
};
const handleDayClick = (dateStr) => {
- if (bookingStep === 'entry') {
+ if (bookingStep === "entry") {
setSelectedStart(dateStr);
setSelectedEnd(null);
- setBookingStep('exit');
+ setBookingStep("exit");
} else {
if (new Date(dateStr) <= new Date(selectedStart)) {
setSelectedStart(dateStr);
setSelectedEnd(null);
- setBookingStep('exit');
+ setBookingStep("exit");
} else {
setSelectedEnd(dateStr);
- setBookingStep('entry');
+ setBookingStep("entry");
}
}
};
const handleBookingConfirm = async () => {
- if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; }
+ if (!AuthService.isAuthenticated()) {
+ setShowLoginDialog(true);
+ return;
+ }
if (!selectedStart || !selectedEnd) {
- setBookingError('يرجى تحديد تاريخ البداية والنهاية');
+ setBookingError("يرجى تحديد تاريخ البداية والنهاية");
return;
}
setBookingLoading(true);
setBookingError(null);
try {
const propInfoId = property._raw?.propertyInformationId || property.id;
- const startDate = new Date(selectedStart + 'T00:00:00.000').toISOString();
- const endDate = new Date(selectedEnd + 'T00:00:00.000').toISOString();
+ const startDate = new Date(selectedStart + "T00:00:00.000").toISOString();
+ const endDate = new Date(selectedEnd + "T00:00:00.000").toISOString();
await bookReservation(propInfoId, startDate, endDate);
setBookingSuccess(true);
- toast.success('تم إرسال طلب الحجز بنجاح');
+ toast.success("تم إرسال طلب الحجز بنجاح");
} catch (err) {
- setBookingError(err.message || 'فشل الحجز');
+ setBookingError(err.message || "فشل الحجز");
} finally {
setBookingLoading(false);
}
@@ -375,8 +567,14 @@ export default function PropertyDetailsPage() {
const navigateMonth = (delta) => {
let month = calendarMonth + delta;
let year = calendarYear;
- if (month < 0) { month = 11; year--; }
- if (month > 11) { month = 0; year++; }
+ if (month < 0) {
+ month = 11;
+ year--;
+ }
+ if (month > 11) {
+ month = 0;
+ year++;
+ }
setCalendarMonth(month);
setCalendarYear(year);
};
@@ -404,9 +602,14 @@ export default function PropertyDetailsPage() {
- العقار غير موجود
+
+ العقار غير موجود
+
لم يتم العثور على العقار المطلوب
-
+
العودة إلى العقارات
@@ -416,18 +619,32 @@ export default function PropertyDetailsPage() {
}
const isFav = isFavorite(property.id);
- const isRoomType = property.type === 'room';
+ const isRoomType = property.type === "room";
const isMostRequested = avgRating !== null && avgRating >= 4.5;
- const showPricingToggle = property.isRent && property.priceDisplay?.daily > 0 && property.priceDisplay?.monthly > 0;
- const effectivePricingMode = showPricingToggle ? pricingMode : (property.isRent && property.priceDisplay?.monthly > 0 ? 'monthly' : 'daily');
+ const showPricingToggle =
+ property.isRent &&
+ property.priceDisplay?.daily > 0 &&
+ property.priceDisplay?.monthly > 0;
+ const effectivePricingMode = showPricingToggle
+ ? pricingMode
+ : property.isRent && property.priceDisplay?.monthly > 0
+ ? "monthly"
+ : "daily";
return (
-
-
+
+
العودة إلى العقارات
@@ -436,14 +653,27 @@ export default function PropertyDetailsPage() {
{/* Image Gallery */}
-
-
+
+
{property.images.length > 0 ? (
-

+ style={{ minHeight: "380px", maxHeight: "460px" }}
+ />
) : (
-
+
لا توجد صور
@@ -461,20 +691,38 @@ export default function PropertyDetailsPage() {
{property.images.length > 1 && (
<>
-