"use client"; import { useState, useEffect, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; 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 "leaflet/dist/leaflet.css"; function PropertyDetailMap({ lat, lng, title }) { const mapRef = useRef(null); const mapInstanceRef = useRef(null); const markerRef = useRef(null); useEffect(() => { if (!mapRef.current || mapInstanceRef.current) return; if (mapRef.current._leaflet_id && !mapInstanceRef.current) { delete mapRef.current._leaflet_id; } const L = require("leaflet"); delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png", iconUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png", shadowUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png", }); const map = L.map(mapRef.current, { center: [lat, lng], zoom: 14, scrollWheelZoom: false, }); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: '© OpenStreetMap contributors', maxZoom: 19, }).addTo(map); const marker = L.marker([lat, lng]).addTo(map).bindPopup(title); mapInstanceRef.current = map; markerRef.current = marker; map.invalidateSize(); return () => { markerRef.current?.remove(); markerRef.current = null; if (mapInstanceRef.current) { mapInstanceRef.current.remove(); mapInstanceRef.current = null; } }; }, [lat, lng, title]); useEffect(() => { if (mapInstanceRef.current) { mapInstanceRef.current.setView([lat, lng], 14); markerRef.current?.setLatLng([lat, lng]); markerRef.current?.setPopupContent(title); mapInstanceRef.current.invalidateSize(); } }, [lat, lng, title]); return
; } function formatCurrency(amount) { 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}`; } const svcKey = (k) => "propertyService." + k.charAt(0).toLowerCase() + k.slice(1); const termKey = (k) => "propertyTerm." + k.charAt(0).toLowerCase() + k.slice(1); const proxKey = (k) => "proximity." + k.toLowerCase(); 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 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 propType = BuildingTypeKeys[info.buildingType] ?? BuildingTypeKeys[item.type] ?? "apartment"; const status = PropertyStatusKeys[info.status] ?? PropertyStatusKeys[item.status] ?? "available"; const rawImages = Array.isArray(info.images) ? info.images : []; const photosFallback = Array.isArray(details.photos) ? details.photos : []; const allRaw = rawImages.length > 0 ? rawImages : photosFallback; const images = allRaw.length > 0 ? allRaw.map(buildImageUrl).filter(Boolean) : []; // 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 serviceDetails = details.serviceDetails || {}; const services = {}; 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; // 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 rawProximity = details.nearbyDistances || details.proximity || {}; const proximity = {}; Object.entries(rawProximity).forEach(([k, v]) => { if (!v) return; const normalizedKey = k.charAt(0).toUpperCase() + k.slice(1); proximity[normalizedKey] = v; }); 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; return { id: item.id, propertyInformationId: info.id, title: details.description || info.address || "", description: details.description || info.description || "", type: propType, typeLabel: propType, price, priceUnit, priceDisplay: { daily: dailyPrice, monthly: monthlyPrice, sale: salePrice }, isRent, displayType, propertyCondition, furnished, location: { city: extractCity(info.address) || "damascus", address: info.address || "", lat: parseFloat(info.cordsX) || 0, lng: parseFloat(info.cordsY) || 0, }, bedrooms: info.numberOfBedRooms || 0, bathrooms: info.numberOfBathRooms || 0, area: info.space || 0, floor, salons, balconies, images, status, statusLabel: status, services, terms, proximity, roomDetails, details, bookedCount: details.bookedCount || 0, deposit: item.deposit || 0, currencyId: item.currencyId, isSmokeAllow: item.isSmokeAllow, isVisitorAllow: item.isVisitorAllow, specializedFor: item.specializedFor, ownerId: info.ownerId ?? info.userId ?? item.ownerId ?? item.userId ?? null, _raw: item, }; } export default function PropertyDetailsPage() { const { t, i18n } = useTranslation(); const params = useParams(); const router = useRouter(); const { isFavorite, addFavorite, removeFavorite } = useFavorites(); const [property, setProperty] = useState(null); const [loading, setLoading] = useState(true); const [currentImage, setCurrentImage] = useState(0); const [showLoginDialog, setShowLoginDialog] = useState(false); 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 [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 [isOwnProperty, setIsOwnProperty] = useState(false); const [favLoading, setFavLoading] = useState(false); const [avgRating, setAvgRating] = useState(null); const [showContact, setShowContact] = useState(false); const [contactInfo, setContactInfo] = useState(null); const [ownerData, setOwnerData] = useState(null); useEffect(() => { const id = params.id; if (!id) return; setLoading(true); 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 {} } if (data) { const mapped = mapApiDetail(data); setProperty(mapped); if (mapped) fetchAvgRating(mapped.id); if (mapped && mapped.isRent) { try { 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); } } // Check if current user owns this property via their own listings if (AuthService.isAuthenticated() && AuthService.isOwner()) { try { const [myRent, mySale] = await Promise.allSettled([ getMyRentListings(), getMySaleListings(), ]); 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) => { const info = p.propertyInformation || {}; if (info.id) myPropIds.add(Number(info.id)); if (p.id) myPropIds.add(Number(p.id)); }); }; collectIds(myRent); collectIds(mySale); const propInfoId = mapped._raw?.propertyInformation?.id; if ( myPropIds.has(Number(mapped.id)) || (propInfoId && myPropIds.has(Number(propInfoId))) ) { setIsOwnProperty(true); } } catch (e) { console.warn("[OwnerCheck] failed:", e); } } } } catch (err) { console.error("[PropertyDetail] Failed:", err); } finally { setLoading(false); } } fetchProperty(); }, [params.id]); const fetchAvgRating = async (propId) => { try { const avg = await getPropertyAverageRating(propId); setAvgRating(avg); } catch {} }; const fetchContactInfo = async () => { if (!property) return; try { const info = await getOwnerContactInformation( property._raw?.propertyInformationId || property.id, ); setContactInfo(info); setShowContact(true); } catch (err) { toast.error(t("contactLoadFailed")); } }; const handleFavorite = async () => { if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; } if (!property) return; setFavLoading(true); try { if (isFavorite(property.id)) { await removeFavorite(property.id); } else { await addFavorite(property.id); } } catch (err) { toast.error(t("errorOccurred")); } finally { setFavLoading(false); } }; const handleBookNow = async () => { if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; } if (!bookingDates.start || !bookingDates.end) { setBookingError(t("validationDateRequired")); return; } setBookingLoading(true); setBookingError(null); try { await bookReservation( property._raw?.propertyInformationId || property.id, bookingDates.start, bookingDates.end, ); setBookingSuccess(true); toast.success(t("bookingSentSuccess")); } catch (err) { setBookingError(err.message || t("bookingFailed")); } finally { setBookingLoading(false); } }; const MONTH_KEYS = [ "month.january", "month.february", "month.march", "month.april", "month.may", "month.june", "month.july", "month.august", "month.september", "month.october", "month.november", "month.december", ]; const DAY_KEYS = [ "dayAbbr.sun", "dayAbbr.mon", "dayAbbr.tue", "dayAbbr.wed", "dayAbbr.thu", "dayAbbr.fri", "dayAbbr.sat", ]; const availableDatesSet = useMemo(() => { const dates = new Set(); if (!Array.isArray(availableRanges)) return dates; 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]); } }); return dates; }, [availableRanges]); const isDateAvailable = (dateStr) => availableDatesSet.has(dateStr); const isPastDate = (dateStr) => { const today = new Date(); today.setHours(0, 0, 0, 0); return new Date(dateStr) < today; }; const handleDayClick = (dateStr) => { if (bookingStep === "entry") { setSelectedStart(dateStr); setSelectedEnd(null); setBookingStep("exit"); } else { if (new Date(dateStr) <= new Date(selectedStart)) { setSelectedStart(dateStr); setSelectedEnd(null); setBookingStep("exit"); } else { setSelectedEnd(dateStr); setBookingStep("entry"); } } }; const handleBookingConfirm = async () => { if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; } if (!selectedStart || !selectedEnd) { setBookingError(t("validationDateRequired")); 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(); await bookReservation(propInfoId, startDate, endDate); setBookingSuccess(true); toast.success(t("bookingSentSuccess")); } catch (err) { setBookingError(err.message || t("bookingFailed")); } finally { setBookingLoading(false); } }; const navigateMonth = (delta) => { let month = calendarMonth + delta; let year = calendarYear; if (month < 0) { month = 11; year--; } if (month > 11) { month = 0; year++; } setCalendarMonth(month); setCalendarYear(year); }; const handleRatingSuccess = () => { setShowRatingForm(false); if (property) fetchAvgRating(property.id); }; if (loading) { return (

{t("loadingProperty")}

); } if (!property) { return (

{t("propertyNotFound")}

{t("propertyNotFoundDesc")}

{t("backToProperties")}
); } const isFav = isFavorite(property.id); 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"; return (
{t("backToProperties")}
{/* Image Gallery */}
{property.images.length > 0 ? ( {property.title} ) : (

{t("noImages")}

)} {isMostRequested && (
{t("mostRequested")}
)} {property.images.length > 1 && ( <> )}
{t("propertyStatus." + property.statusLabel)} {t("buildingType." + property.typeLabel)}
{currentImage + 1} / {property.images.length || 1}
{property.images.length > 1 && (
{property.images.map((img, idx) => ( ))}
)}
{/* Property Info */}
{t("buildingType." + property.typeLabel)} {t("propertyStatus." + property.statusLabel)} {property.isRent && property.displayType && ( {(() => { const dt = property.displayType.toLowerCase(); if (dt === "both" || dt.includes("both")) return t("dailyAndMonthly"); if (dt.includes("daily")) return t("rentType.daily"); if (dt.includes("monthly")) return t("rentType.monthly"); return dt; })()} )} {property.furnished ? t("rentCondition.furnished") : t("rentCondition.unfurnished")}

{property.title || t("propertyWithId", { id: property.id })}

{property.location.address || t("city." + property.location.city)}
{/* Price */}
{property.isRent ? (
{property.priceDisplay.monthly > 0 && (
{formatCurrency(property.priceDisplay.monthly)} {t("sypPerMonth")}
)} {property.priceDisplay.daily > 0 && (
{formatCurrency(property.priceDisplay.daily)} {t("sypPerDay")}
)} {property.deposit > 0 && (
{t("depositLabel")}{" "} {formatCurrency(property.deposit)} {t("syp")}
)}
) : (
{formatCurrency(property.price)} {t("syp")} {t("forSale")}
)}
{/* Specs Tiles */}
{property.bedrooms > 0 && (
{property.bedrooms}
{t("bedrooms")}
)} {property.bathrooms > 0 && (
{property.bathrooms}
{t("bathrooms")}
)} {property.area > 0 && (
{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")}
)} {avgRating !== null && avgRating > 0 && (
{avgRating.toFixed(1)}
{t("rateAndReview")}
)} {property.bookedCount > 0 && (
{property.bookedCount}
{t("bookingCount")}
)}
{/* Description */} {property.description && (

{t("description")}

{property.description}

)} {/* Features */}
{property.isSmokeAllow && ( {t("smokingAllowed")} )} {!property.isSmokeAllow && ( {t("propertyTerm.noSmoking")} )} {property.isVisitorAllow && ( {t("visitorsAllowed")} )} {property.specializedFor && ( {property.specializedFor} )}
{/* Services with detail text */} {property.services && (Array.isArray(property.services) ? property.services.length > 0 : Object.keys(property.services).length > 0) && (

{t("services")}

{Array.isArray(property.services) ? property.services.map((svc, i) => ( {t(svcKey(svc))} )) : Object.entries(property.services).map( ([key, val]) => { if (!val) return null; const detail = typeof val === "object" && val.detail ? val.detail : typeof val === "string" ? val : null; return ( {t(svcKey(key))} {detail && ( · {detail} )} ); }, )}
)} {/* Room Details (only for room type) */} {isRoomType && Object.keys(property.roomDetails).length > 0 && (

{t("roomDetails")}

{(() => { const rd = property.roomDetails; const items = []; if (rd.areaType) items.push({ label: t("roomDetail.areaType"), value: rd.areaType === "private room" ? t("roomDetail.privateRoom") : rd.areaType === "shared room" ? t("roomDetail.sharedRoom") : rd.areaType, }); if (rd.peopleAllowed) items.push({ label: t("roomDetail.numberOfPeople"), value: rd.peopleAllowed, }); if (rd.furnitureDetails || rd.furniture) items.push({ label: t("roomDetail.furniture"), value: rd.furnitureDetails || rd.furniture, }); if (rd.entranceType) items.push({ label: t("roomDetail.entranceType"), value: rd.entranceType === "shared entrance" ? t("roomDetail.sharedEntrance") : rd.entranceType === "independent entrance" ? t("roomDetail.independentEntrance") : rd.entranceType, }); if (rd.bathroomType) items.push({ label: t("roomDetail.bathroom"), value: rd.bathroomType === "room specific" ? t("roomDetail.bathroomPrivate") : rd.bathroomType === "shared" ? t("roomDetail.bathroomShared") : rd.bathroomType, }); if (rd.kitchenType) items.push({ label: t("roomDetail.kitchen"), value: rd.kitchenType === "shared" ? t("roomDetail.kitchenShared") : rd.kitchenType === "not available" ? t("roomDetail.kitchenNotAvailable") : rd.kitchenType, }); if (rd.homeResidentsCount ?? rd.residents) items.push({ label: t("roomDetail.residents"), value: rd.homeResidentsCount ?? rd.residents, }); if (rd.currentPopulationGender) items.push({ label: t("roomDetail.gender"), value: rd.currentPopulationGender === "men" ? t("roomDetail.men") : rd.currentPopulationGender === "women" ? t("roomDetail.women") : rd.currentPopulationGender === "family" ? t("roomDetail.family") : rd.currentPopulationGender, }); if (rd.dedicatedTo) items.push({ label: t("roomDetail.dedicatedTo"), value: rd.dedicatedTo === "men only" ? t("roomDetail.menOnly") : rd.dedicatedTo === "women only" ? t("roomDetail.womenOnly") : rd.dedicatedTo === "families only" ? t("roomDetail.familiesOnly") : rd.dedicatedTo === "everyone" ? t("roomDetail.everyone") : rd.dedicatedTo, }); if (rd.hasRestrictedOwnerAreas !== undefined) items.push({ label: t("roomDetail.restrictedAreas"), value: rd.hasRestrictedOwnerAreas ? t("roomDetail.yes") : t("roomDetail.no"), }); if (rd.hasChildren !== undefined) items.push({ label: t("roomDetail.children"), value: rd.hasChildren ? t("roomDetail.allowed") : t("roomDetail.notAllowed"), }); if (rd.hasPets !== undefined) items.push({ label: t("roomDetail.pets"), value: rd.hasPets ? t("roomDetail.allowed") : t("roomDetail.notAllowed"), }); if (rd.languageDialect) items.push({ label: t("roomDetail.language"), value: rd.languageDialect, }); if (rd.visitorsAllowed !== undefined) items.push({ label: t("roomDetail.visitors"), value: rd.visitorsAllowed ? t("roomDetail.allowed") : t("roomDetail.forbidden"), }); if (rd.quietTimesEnabled ?? rd.quietTimes) items.push({ label: t("roomDetail.quietHours"), value: rd.quietTimesDetails || rd.quietTimes || (rd.quietTimesEnabled ? t("roomDetail.quietHoursEnabled") : ""), }); return items.map((item, i) => (
{item.label}
{item.value}
)); })()}
)} {/* 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(proxKey(key))}
{dist} {typeof dist === "number" ? t("km") : ""}
); })}
)} {/* Terms as checklist */} {Object.keys(property.terms).length > 0 && (

{t("terms")}

{Object.entries(property.terms).map(([key, val]) => { if (!val) return null; return (
{key.startsWith("No") || key.startsWith("Only") ? ( ) : ( )} {t(termKey(key))}
); })}
)}
{/* Map */} {property.location.lat && property.location.lng && (
{t("approximateLocation")}
)} {/* Ratings Section */}
{/* Sidebar */}
{/* Booking Card */} {property.isRent && ( {isOwnProperty ? (

{t("thisIsYourProperty")}

{t("cannotBookOwnProperty")}

) : bookingSuccess ? (

{t("bookingRequestSent")}

{t("bookingRequestWillBeReviewed")}

) : ( <> {/* Pricing Mode Toggle */} {showPricingToggle && (
)} {/* Step Indicator */}
{t("selectStartDate")}
{t("selectEndDate")}
{/* Calendar */} {effectivePricingMode === "daily" ? (
{t(MONTH_KEYS[calendarMonth])} {calendarYear}
{DAY_KEYS.map((dk, i) => (
{t(dk)}
))}
{(() => { const firstDay = new Date( calendarYear, calendarMonth, 1, ).getDay(); const daysInMonth = new Date( calendarYear, calendarMonth + 1, 0, ).getDate(); const adjustedFirstDay = (firstDay + 1) % 7; const cells = []; for (let i = 0; i < adjustedFirstDay; i++) { cells.push(
); } for (let day = 1; day <= daysInMonth; day++) { const dateStr = `${calendarYear}-${String(calendarMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; const past = isPastDate(dateStr); const available = isDateAvailable(dateStr); const isSelStart = dateStr === selectedStart; const isSelEnd = dateStr === selectedEnd; const inRange = selectedStart && selectedEnd && new Date(dateStr) > new Date(selectedStart) && new Date(dateStr) < new Date(selectedEnd); const disabled = past || !available; cells.push( , ); } return (
{cells}
); })()}
) : (
{calendarYear}
{MONTH_KEYS.map((mk, idx) => { const monthStr = `${calendarYear}-${String(idx + 1).padStart(2, "0")}`; const isSelStart = selectedStart && selectedStart.startsWith(monthStr); const isSelEnd = selectedEnd && selectedEnd.startsWith(monthStr); const inRange = selectedStart && selectedEnd && monthStr > selectedStart.substring(0, 7) && monthStr < selectedEnd.substring(0, 7); return ( ); })}
)} {/* Summary */} {selectedStart && (
{t("startDateLabel")} {selectedStart}
{selectedEnd && ( <>
{t("endDateLabel")} {selectedEnd}
{effectivePricingMode === "daily" ? t("numberOfDays") : t("numberOfMonths")} {effectivePricingMode === "daily" ? Math.max( 1, Math.round( (new Date(selectedEnd) - new Date(selectedStart)) / (1000 * 60 * 60 * 24), ) + 1, ) : new Date(selectedEnd).getMonth() - new Date(selectedStart).getMonth() + (new Date(selectedEnd).getFullYear() - new Date(selectedStart).getFullYear()) * 12 + 1}
{t("total")} {formatCurrency( effectivePricingMode === "daily" ? Math.max( 1, Math.round( (new Date(selectedEnd) - new Date(selectedStart)) / (1000 * 60 * 60 * 24), ) + 1, ) * property.priceDisplay.daily : (new Date(selectedEnd).getMonth() - new Date(selectedStart).getMonth() + (new Date(selectedEnd).getFullYear() - new Date( selectedStart, ).getFullYear()) * 12 + 1) * property.priceDisplay.monthly, )}{" "} {t("syp")}
{property.deposit > 0 && (
{t("deposit")} {formatCurrency(property.deposit)} {t("syp")}
)} )}
)} {bookingError && (
{bookingError}
)} )} )} {/* Contact Card */} {/* {!isOwnProperty && (

{t("ownerInfo")}

{showContact && contactInfo ? (
{contactInfo.phone || contactInfo.phoneNumber || '—'}
{contactInfo.whatsAppNumber && ( {contactInfo.whatsAppNumber} )}
) : ( )}
)} */}
{/* Login Dialog */} {showLoginDialog && (
setShowLoginDialog(false)} >
e.stopPropagation()} >

{t("loginRequiredTitle")}

{t("loginRequiredDesc")}

{t("login")} {t("createAccount")}
)}
); } //reset