'use client'; import { useState, useEffect } from 'react'; import { motion } from 'framer-motion'; import toast, { Toaster } from 'react-hot-toast'; import Image from 'next/image'; import Link from 'next/link'; import { useParams } from 'next/navigation'; import { MapPin, Bed, Bath, Square, DollarSign, Heart, Share2, Phone, Mail, MessageCircle, Calendar, Shield, Star, ChevronLeft, ChevronRight, Check, X, Wifi, Car, Coffee, Wind, Thermometer, Lock, Camera, Home, Building2, Users, Ruler, CalendarDays, Clock, Award, FileText, Printer, Download, ArrowLeft, LogIn, Copy } from 'lucide-react'; import { getRentProperty, getSaleProperty, bookReservation, checkAvailability, getAvailableDateRanges } from '../../utils/api'; import AuthService from '../../services/AuthService'; import { useFavorites } from '@/app/contexts/FavoritesContext'; import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from '../../enums'; // Copy to clipboard that works on HTTP too async function copyToClipboard(text) { try { await navigator.clipboard.writeText(text); return true; } catch { // Fallback for HTTP / older browsers const textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); return true; } catch { return false; } finally { document.body.removeChild(textarea); } } } // Map API response to the UI format function mapApiDetail(item) { if (!item) return null; const info = item.propertyInformation || {}; const dailyPrice = item.dailyRent ?? item.monthlyRent ?? item.price ?? 0; const monthlyPrice = item.monthlyRent ?? 0; const propType = BuildingTypeKeys[info.buildingType] ?? BuildingTypeKeys[item.type] ?? 'apartment'; const status = PropertyStatusKeys[info.status] ?? PropertyStatusKeys[item.status] ?? 'available'; const features = []; if (item.isSmokeAllow) features.push({ name: 'يسمح بالتدخين', available: true, description: '' }); if (item.isVisitorAllow) features.push({ name: 'يسمح بالزوار', available: true, description: '' }); if (item.specializedFor) features.push({ name: 'متخصص', available: true, description: '' }); if (info.numberOfBedRooms) features.push({ name: 'غرف النوم', available: true, description: `${info.numberOfBedRooms} غرف` }); if (info.numberOfBathRooms) features.push({ name: 'الحمامات', available: true, description: `${info.numberOfBathRooms} حمامات` }); if (info.space) features.push({ name: 'المساحة', available: true, description: `${info.space} م²` }); const typeLabels = { 0: 'شقة', 1: 'فيلا', 2: 'بيت' }; // Extract images from API and build full URLs const apiBase = typeof window !== 'undefined' ? (process.env.NEXT_PUBLIC_API_URL || 'http://45.93.137.91/api') : ''; const rawImages = Array.isArray(info.images) ? info.images : []; const images = rawImages.length > 0 ? rawImages.map(img => img.startsWith('http') ? img : `${apiBase}${img.startsWith('/') ? '' : '/Pictures/'}${img}`) : ['/property-placeholder.jpg', '/villa1.jpg', '/villa2.jpg']; return { id: item.id, title: info.address || `عقار #${item.id}`, description: info.description || 'عقار سكني مميز في موقع استراتيجي.', type: propType, price: dailyPrice, priceUnit: 'daily', location: { city: extractCity(info.address) || 'دمشق', district: info.address || '', 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, features: features.length > 0 ? features : [ { name: 'متاح للإيجار', available: true, description: '' }, ], images, status, rating: item.rating || 4.5, reviews: 0, reviewList: [], owner: { name: 'المالك', phone: '—', email: '—', rating: 4.8, properties: 1, memberSince: '2024', responseRate: '95%', responseTime: 'خلال ساعات', }, nearby: [], specifications: { constructionYear: null, floor: '-', parking: 0, gardenArea: 0, poolArea: 0, furnished: false, airConditioning: '-', heating: '-', electricity: '220V', water: 'شبكة عامة', }, rules: [], _raw: item, }; } // extractCity is now imported from @/app/enums // API-only — no fallback data export default function PropertyDetailsPage() { const params = useParams(); const { isFavorite, addFavorite, removeFavorite } = useFavorites(); const [currentImage, setCurrentImage] = useState(0); const [showContact, setShowContact] = useState(false); const [showShareMenu, setShowShareMenu] = useState(false); const [bookingDates, setBookingDates] = useState({ start: '', end: '' }); const [selectedDuration, setSelectedDuration] = useState(1); const [property, setProperty] = useState(null); const [loading, setLoading] = useState(true); const [bookingError, setBookingError] = useState(null); const [bookingSuccess, setBookingSuccess] = useState(false); const [availableRanges, setAvailableRanges] = useState([]); const [calendarMonth, setCalendarMonth] = useState(new Date()); const [favLoading, setFavLoading] = useState(false); const [selectingEnd, setSelectingEnd] = useState(false); const [showLoginDialog, setShowLoginDialog] = useState(false); useEffect(() => { const id = params.id; setLoading(true); setBookingError(null); setBookingSuccess(false); async function fetchProperty() { try { // Try RentProperties first, then SaleProperties let data = null; try { data = await getRentProperty(id); } catch { try { data = await getSaleProperty(id); } catch { // neither worked } } if (data) { const mapped = mapApiDetail(data); if (mapped) { setProperty(mapped); setLoading(false); return; } } setProperty(null); } catch (err) { console.error('[Property] Failed to fetch property:', err); setProperty(null); } finally { setLoading(false); } } fetchProperty(); }, [params.id]); // Fetch available date ranges useEffect(() => { if (!property) return; const propId = property._raw?.id || params.id; console.log('[Property] Fetching available dates for:', propId); getAvailableDateRanges(propId) .then((data) => { const ranges = Array.isArray(data) ? data : []; console.log('[Property] Available date ranges:', ranges); setAvailableRanges(ranges); }) .catch((err) => { console.warn('[Property] Failed to fetch available dates:', err); }); }, [property, params.id]); // Set Open Graph meta tags dynamically for Facebook/Twitter sharing useEffect(() => { if (!property) return; const typeLabel = property.type === 'villa' ? 'فيلا' : property.type === 'apartment' ? 'شقة' : 'بيت'; const priceLabel = `${formatCurrency(property.price)} / ${property.priceUnit === 'daily' ? 'يوم' : 'شهر'}`; const desc = `${typeLabel} في ${property.location?.address || ''} · ${property.bedrooms} غرف نوم · ${property.bathrooms} حمامات · ${property.area} م²`; const imageUrl = property.images?.[0] ? (property.images[0].startsWith('http') ? property.images[0] : `http://45.93.137.91${property.images[0]}`) : ''; const setMeta = (prop, content) => { let tag = document.querySelector(`meta[property="${prop}"]`); if (!tag) { tag = document.createElement('meta'); tag.setAttribute('property', prop); document.head.appendChild(tag); } tag.setAttribute('content', content); }; const setMetaName = (name, content) => { let tag = document.querySelector(`meta[name="${name}"]`); if (!tag) { tag = document.createElement('meta'); tag.setAttribute('name', name); document.head.appendChild(tag); } tag.setAttribute('content', content); }; setMeta('og:title', `${property.title} - ${priceLabel}`); setMeta('og:description', desc); if (imageUrl) setMeta('og:image', imageUrl); setMeta('og:url', window.location.href); setMeta('og:type', 'website'); setMeta('og:site_name', 'SweetHome'); // Twitter cards setMetaName('twitter:card', 'summary_large_image'); setMetaName('twitter:title', `${property.title} - ${priceLabel}`); setMetaName('twitter:description', desc); if (imageUrl) setMetaName('twitter:image', imageUrl); }, [property]); const formatCurrency = (amount) => { return amount?.toLocaleString() + ' ل.س'; }; const calculateTotalPrice = () => { if (!property) return 0; const days = bookingDates.start && bookingDates.end ? Math.ceil((new Date(bookingDates.end) - new Date(bookingDates.start)) / (1000 * 60 * 60 * 24)) : selectedDuration; return property.price * (days > 0 ? days : 1); }; // Calendar helpers const isDateAvailable = (dateStr) => { const d = new Date(dateStr + 'T00:00:00'); return availableRanges.some((range) => { const start = new Date(range.startDate); const end = new Date(range.endDate); return d >= start && d <= end; }); }; const isInRange = (dateStr) => { if (!bookingDates.start) return false; const d = new Date(dateStr + 'T00:00:00'); const start = new Date(bookingDates.start + 'T00:00:00'); const end = bookingDates.end ? new Date(bookingDates.end + 'T00:00:00') : start; return d >= start && d <= end; }; const isRangeFullyAvailable = (startStr, endStr) => { const start = new Date(startStr + 'T00:00:00'); const end = new Date(endStr + 'T00:00:00'); for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { if (!isDateAvailable(d.toISOString().split('T')[0])) return false; } return true; }; const handleCalendarClick = (dateStr) => { if (!isDateAvailable(dateStr)) return; if (!bookingDates.start || selectingEnd) { if (!bookingDates.start) { setBookingDates({ start: dateStr, end: '' }); setSelectingEnd(true); } else { const start = bookingDates.start; const end = dateStr; const [s, e] = end > start ? [start, end] : [end, start]; if (isRangeFullyAvailable(s, e)) { setBookingDates({ start: s, end: e }); setSelectingEnd(false); } else { toast.error('بعض التواريخ في هذه الفترة غير متاحة'); } } } else { setBookingDates({ start: dateStr, end: '' }); setSelectingEnd(true); } }; const getDaysInMonth = (year, month) => new Date(year, month + 1, 0).getDate(); const getFirstDayOfMonth = (year, month) => new Date(year, month, 1).getDay(); const formatDateStr = (year, month, day) => { return `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; }; const monthNames = ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر']; const dayNames = ['أح', 'إث', 'ثل', 'أر', 'خم', 'جم', 'سب']; const handleBooking = async () => { if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; } setBookingError(null); setBookingSuccess(false); if (!bookingDates.start || !bookingDates.end) { setBookingError('يرجى اختيار تاريخ البداية والنهاية'); return; } const propId = property?._raw?.id || parseInt(params.id); const startDate = new Date(bookingDates.start).toISOString(); const endDate = new Date(bookingDates.end).toISOString(); console.log('[Booking] Reserving:', { propertyId: propId, startDate, endDate }); try { const res = await bookReservation(propId, startDate, endDate); console.log('[Booking] Success:', res); setBookingSuccess(true); toast.success('تم إرسال طلب الحجز بنجاح!'); } catch (err) { console.error('[Booking] Failed:', err); setBookingError(err.message || 'فشل في إرسال طلب الحجز'); } }; if (loading) { return (
جاري تحميل تفاصيل العقار...
لم نتمكن من العثور على العقار المطلوب
العودة إلى العقارات{property.description || 'لا يوجد وصف متاح.'}
{feature.description}
)}{review.comment}
يجب عليك إنشاء حساب أو تسجيل الدخول لحجز هذا العقار