'use client'; import { useState, useRef, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ShieldCheck, Lock, Zap, Star, Rocket, Search, MapPin, Home, DollarSign, ChevronDown, Shield, Award, Sparkles, UserCircle, LogOut, Calendar, Building, PlusCircle, Heart, MessageCircle } from 'lucide-react'; import HeroSearch from './components/home/HeroSearch'; import PropertyMap from './components/home/PropertyMap'; import Link from 'next/link'; import Image from 'next/image'; import { getRentProperties, getSaleProperties } from './utils/api'; // Map API property data to the format the UI expects // API returns { propInfoId, deposit, monthlyRent, dailyRent, rating, ... } // If propertyInformation is nested, use it; otherwise use flat response with defaults function mapApiProperty(item, index) { const info = item.propertyInformation || {}; const hasNestedInfo = !!item.propertyInformation; const dailyPrice = item.dailyRent ?? item.monthlyRent ?? item.price ?? 0; const monthlyPrice = item.monthlyRent ?? 0; // BuildingType: 0=Apartment, 1=Villa, 2=House const buildingTypeMap = { 0: 'apartment', 1: 'villa', 2: 'house' }; const propType = buildingTypeMap[info.buildingType] ?? buildingTypeMap[item.type] ?? 'apartment'; // Status: 0=Available, 1=Booked, 2=Maintenance const statusMap = { 0: 'available', 1: 'booked', 2: 'maintenance' }; const status = statusMap[info.status] ?? statusMap[item.status] ?? 'available'; const features = []; if (item.isSmokeAllow) features.push('يسمح بالتدخين'); if (item.isVisitorAllow) features.push('يسمح بالزوار'); if (item.specializedFor) features.push('متخصص'); if (info.numberOfBedRooms) features.push(`${info.numberOfBedRooms} غرف نوم`); if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} حمامات`); return { id: item.id ?? index + 1, propInfoId: item.propInfoId, title: info.address || `عقار #${item.id || index + 1}`, description: info.description || '', type: propType, price: dailyPrice, priceUSD: 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, images: ['/property-placeholder.jpg'], status, rating: item.rating || 4.5, isNew: false, allowedIdentities: ['syrian', 'passport'], priceDisplay: { daily: dailyPrice, monthly: monthlyPrice, }, bookings: [], _raw: item, }; } function extractCity(address) { if (!address) return ''; const cities = ['دمشق', 'حلب', 'حمص', 'اللاذقية', 'درعا', 'طرطوس', 'السويداء', 'دير الزور', 'الرقة', 'إدلب', 'الحسكة', 'القامشلي', 'ريف دمشق']; for (const city of cities) { if (address.includes(city)) return city; } return ''; } // Fallback dummy data const FALLBACK_PROPERTIES = [ { id: 1, title: 'فيلا فاخرة في المزة', description: 'فيلا فاخرة مع حديقة خاصة ومسبح في أفضل أحياء دمشق.', type: 'villa', price: 500000, priceUSD: 50, priceUnit: 'daily', location: { city: 'دمشق', district: 'المزة', address: 'شارع المزة - فيلات غربية', lat: 33.5138, lng: 36.2765 }, bedrooms: 5, bathrooms: 4, area: 450, features: ['مسبح', 'حديقة خاصة', 'موقف سيارات', 'أمن 24/7', 'تدفئة مركزية', 'تكييف مركزي'], images: ['/villa1.jpg', '/villa2.jpg', '/villa3.jpg'], status: 'available', rating: 4.8, isNew: true, allowedIdentities: ['syrian', 'passport'], priceDisplay: { daily: 500000, monthly: 15000000 }, bookings: [{ startDate: '2024-03-10', endDate: '2024-03-15' }, { startDate: '2024-03-20', endDate: '2024-03-25' }] }, { id: 2, title: 'شقة حديثة في الشهباء', description: 'شقة عصرية في حي الشهباء الراقي بحلب.', type: 'apartment', price: 250000, priceUSD: 25, priceUnit: 'daily', location: { city: 'حلب', district: 'الشهباء', address: 'شارع النيل - بناء الرحاب', lat: 36.2021, lng: 37.1347 }, bedrooms: 3, bathrooms: 2, area: 180, features: ['مطبخ مجهز', 'بلكونة', 'موقف سيارات', 'مصعد'], images: ['/apartment1.jpg', '/apartment2.jpg'], status: 'available', rating: 4.5, isNew: false, allowedIdentities: ['syrian'], priceDisplay: { daily: 250000, monthly: 7500000 }, bookings: [{ startDate: '2024-03-05', endDate: '2024-03-08' }] }, { id: 3, title: 'بيت عائلي في بابا عمرو', description: 'بيت واسع مناسب للعائلات في حمص.', type: 'house', price: 350000, priceUSD: 35, priceUnit: 'daily', location: { city: 'حمص', district: 'بابا عمرو', address: 'حي الزهور', lat: 34.7265, lng: 36.7186 }, bedrooms: 4, bathrooms: 3, area: 300, features: ['حديقة كبيرة', 'موقف سيارات', 'مدفأة', 'كراج'], images: ['/house1.jpg'], status: 'booked', rating: 4.3, isNew: false, allowedIdentities: ['syrian', 'passport'], priceDisplay: { daily: 350000, monthly: 10500000 }, bookings: [] }, { id: 4, title: 'شقة بجانب البحر', description: 'شقة رائعة مع إطلالة بحرية في اللاذقية.', type: 'apartment', price: 300000, priceUSD: 30, priceUnit: 'daily', location: { city: 'اللاذقية', district: 'الشاطئ الأزرق', address: 'الكورنيش الغربي', lat: 35.5306, lng: 35.7801 }, bedrooms: 3, bathrooms: 2, area: 200, features: ['إطلالة بحرية', 'شرفة', 'تكييف', 'أمن'], images: ['/seaside1.jpg', '/seaside2.jpg', '/seaside3.jpg'], status: 'available', rating: 4.9, isNew: true, allowedIdentities: ['passport'], priceDisplay: { daily: 300000, monthly: 9000000 }, bookings: [] }, { id: 5, title: 'فيلا في درعا', description: 'فيلا فاخرة في حي الأطباء بدرعا.', type: 'villa', price: 400000, priceUSD: 40, priceUnit: 'daily', location: { city: 'درعا', district: 'حي الأطباء', address: 'شارع الشفاء', lat: 32.6237, lng: 36.1016 }, bedrooms: 4, bathrooms: 3, area: 350, features: ['حديقة مثمرة', 'أنظمة أمن', 'مسبح', 'كراج'], images: ['/villa4.jpg', '/villa5.jpg'], status: 'available', rating: 4.6, isNew: false, allowedIdentities: ['syrian', 'passport'], priceDisplay: { daily: 400000, monthly: 12000000 }, bookings: [] } ]; export default function HomePage() { const mapSectionRef = useRef(null); const [searchFilters, setSearchFilters] = useState(null); const [showMap, setShowMap] = useState(false); const [filteredProperties, setFilteredProperties] = useState([]); const [isScrolling, setIsScrolling] = useState(false); const [user, setUser] = useState(null); const [showUserMenu, setShowUserMenu] = useState(false); const menuRef = useRef(null); const [allProperties, setAllProperties] = useState(FALLBACK_PROPERTIES); const [loading, setLoading] = useState(true); // Fetch properties from API on mount useEffect(() => { const storedUser = localStorage.getItem('user'); if (storedUser) { setUser(JSON.parse(storedUser)); } async function fetchProperties() { try { const [rentData, saleData] = await Promise.all([ getRentProperties().catch(() => []), getSaleProperties().catch(() => []), ]); const rentList = Array.isArray(rentData) ? rentData : []; const saleList = Array.isArray(saleData) ? saleData : []; const mapped = [ ...rentList.map((p, i) => mapApiProperty(p, i)), ...saleList.map((p, i) => mapApiProperty(p, rentList.length + i)), ]; if (mapped.length > 0) { setAllProperties(mapped); } // If API returns empty, keep fallback } catch (err) { console.warn('Failed to fetch properties, using fallback data:', err); // keep fallback data } finally { setLoading(false); } } fetchProperties(); }, []); useEffect(() => { const handleClickOutside = (event) => { if (menuRef.current && !menuRef.current.contains(event.target)) { setShowUserMenu(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const logout = () => { localStorage.removeItem('user'); setUser(null); setShowUserMenu(false); }; const applyFilters = (filters) => { setSearchFilters(filters); const filtered = allProperties.filter(property => { if (filters.city && filters.city !== 'all' && property.location.city !== filters.city) { return false; } if (filters.propertyType && filters.propertyType !== 'all' && property.type !== filters.propertyType) { return false; } if (filters.priceRange && filters.priceRange !== 'all') { const priceUSD = property.priceUSD; switch (filters.priceRange) { case '0-500': if (priceUSD > 50) return false; break; case '500-1000': if (priceUSD < 51 || priceUSD > 100) return false; break; case '1000-2000': if (priceUSD < 101 || priceUSD > 200) return false; break; case '2000-3000': if (priceUSD < 201 || priceUSD > 300) return false; break; case '3000+': if (priceUSD < 301) return false; break; } } if (filters.identityType && property.allowedIdentities) { if (!property.allowedIdentities.includes(filters.identityType)) { return false; } } return true; }); setFilteredProperties(filtered); if (!showMap) { setShowMap(true); setTimeout(() => { if (mapSectionRef.current) { setIsScrolling(true); mapSectionRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' }); setTimeout(() => setIsScrolling(false), 1000); } }, 300); } else { if (mapSectionRef.current) { setIsScrolling(true); mapSectionRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' }); setTimeout(() => setIsScrolling(false), 1000); } } }; const resetSearch = () => { setShowMap(false); setSearchFilters(null); setFilteredProperties([]); window.scrollTo({ top: 0, behavior: 'smooth' }); }; const getUserInitial = () => { if (user?.name) { return user.name.charAt(0).toUpperCase(); } return null; }; const isOwner = user?.role === 'owner'; return (
يمكنك إدارة عقاراتك من خلال لوحة التحكم الخاصة بك
تم العثور على {filteredProperties.length} عقار يطابق معايير البحث
) : (لا توجد عقارات تطابق معايير البحث. جرب تغيير الفلاتر.
)}حاول تغيير معايير البحث
نجعل عملية إيجاد منزلك المثالي سهلة وسريعة
كل عقار يتم التحقق منه بدقة لضمان الدقة والجودة.
سلامتك هي أولويتنا. نوفر معاملات آمنة ونحمي معلوماتك الشخصية.
اعثر على منزلك المثالي في دقائق باستخدام خوارزميات البحث والمطابقة المتقدمة لدينا.