'use client'; import { useState, useRef, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { usePathname } from 'next/navigation'; 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'; import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from './enums'; import AuthService from './services/AuthService'; // Map API property data to the format the UI expects // API returns { propertyInformationId, deposit, monthlyRent, dailyRent, rating, propertyInformation: {...}, ... } function mapApiProperty(item, index) { 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('يسمح بالتدخين'); 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, 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, }; } // extractCity is now imported from @/app/enums // API-only — no fallback data 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 pathname = usePathname(); const [allProperties, setAllProperties] = useState([]); const [loading, setLoading] = useState(true); // Re-read user from JWT on every route change useEffect(() => { const authUser = AuthService.getUser(); if (authUser) { setUser({ name: authUser.name || authUser.email, email: authUser.email, role: AuthService.isOwner() ? 'owner' : 'customer', }); } else { setUser(null); } }, [pathname]); // Fetch properties from API on mount useEffect(() => { 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.error('[Home] Failed to fetch properties:', err); } 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 = () => { AuthService.deleteToken(); 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} عقار يطابق معايير البحث
) : (لا توجد عقارات تطابق معايير البحث. جرب تغيير الفلاتر.
)}حاول تغيير معايير البحث
نجعل عملية إيجاد منزلك المثالي سهلة وسريعة
كل عقار يتم التحقق منه بدقة لضمان الدقة والجودة.
سلامتك هي أولويتنا. نوفر معاملات آمنة ونحمي معلوماتك الشخصية.
اعثر على منزلك المثالي في دقائق باستخدام خوارزميات البحث والمطابقة المتقدمة لدينا.