2026-02-15 01:53:37 +03:00
'use client' ;
2026-03-26 22:20:33 +00:00
import { useState , useEffect } from 'react' ;
2026-02-15 01:53:37 +03:00
import { motion , AnimatePresence } from 'framer-motion' ;
import {
Search ,
MapPin ,
Bed ,
Bath ,
Square ,
DollarSign ,
Filter ,
Grid3x3 ,
List ,
Heart ,
Share2 ,
ChevronDown ,
Star ,
Camera ,
Home ,
Building2 ,
Trees ,
Waves ,
Warehouse ,
Sparkles ,
Shield ,
Calendar ,
Phone ,
Mail ,
MessageCircle
} from 'lucide-react' ;
import Image from 'next/image' ;
import Link from 'next/link' ;
2026-03-26 22:20:33 +00:00
import { getRentProperties , getSaleProperties } from '../utils/api' ;
// Map API data to UI format
function mapApiProperty ( item , index ) {
const info = item . propertyInformation || item ;
const dailyPrice = item . dailyRent ? ? item . monthlyRent ? ? item . price ? ? 0 ;
const monthlyPrice = item . monthlyRent ? ? 0 ;
const buildingTypeMap = { 0 : 'apartment' , 1 : 'villa' , 2 : 'house' } ;
const propType = buildingTypeMap [ info . buildingType ] || 'apartment' ;
const statusMap = { 0 : 'available' , 1 : 'booked' , 2 : 'maintenance' } ;
const status = statusMap [ info . status ] || 'available' ;
const features = [ ] ;
if ( item . isSmokeAllow ) features . push ( 'يسمح بالتدخين' ) ;
if ( item . isVisitorAllow ) features . push ( 'يسمح بالزوار' ) ;
if ( info . numberOfRooms ) features . push ( ` ${ info . numberOfRooms } غرف ` ) ;
if ( info . numberOfBathRooms ) features . push ( ` ${ info . numberOfBathRooms } حمامات ` ) ;
return {
id : item . id ? ? index + 1 ,
title : info . address || info . description ? . substring ( 0 , 40 ) || 'عقار' ,
description : info . description || '' ,
type : propType ,
price : dailyPrice ,
priceUnit : 'daily' ,
location : {
city : extractCity ( info . address ) ,
district : info . address || '' ,
} ,
bedrooms : info . numberOfBedRooms || info . numberOfRooms || 0 ,
bathrooms : info . numberOfBathRooms || 0 ,
area : info . space || 0 ,
features ,
images : [ '/property-placeholder.jpg' ] ,
status ,
rating : item . rating || 4.5 ,
isNew : false ,
_raw : item ,
} ;
}
2026-02-15 01:53:37 +03:00
2026-03-26 22:20:33 +00:00
function extractCity ( address ) {
if ( ! address ) return '' ;
const cities = [ 'دمشق' , 'حلب' , 'حمص' , 'اللاذقية' , 'درعا' , 'طرطوس' , 'السويداء' , 'دير الزور' , 'الرقة' , 'إدلب' , 'الحسكة' , 'القامشلي' , 'ريف دمشق' ] ;
for ( const city of cities ) {
if ( address . includes ( city ) ) return city ;
}
return '' ;
}
// Fallback data
const FALLBACK _PROPERTIES = [
{ id : 1 , title : 'فيلا فاخرة في المزة' , description : 'فيلا فاخرة مع حديقة خاصة ومسبح في أفضل أحياء دمشق.' , type : 'villa' , price : 500000 , priceUnit : 'daily' , location : { city : 'دمشق' , district : 'المزة' } , bedrooms : 5 , bathrooms : 4 , area : 450 , features : [ 'مسبح' , 'حديقة خاصة' , 'موقف سيارات' , 'أمن' ] , images : [ '/villa1.jpg' ] , status : 'available' , rating : 4.8 , isNew : true } ,
{ id : 2 , title : 'شقة حديثة في الشهباء' , description : 'شقة عصرية في حي الشهباء الراقي بحلب.' , type : 'apartment' , price : 250000 , priceUnit : 'daily' , location : { city : 'حلب' , district : 'الشهباء' } , bedrooms : 3 , bathrooms : 2 , area : 180 , features : [ 'مطبخ مجهز' , 'بلكونة' , 'موقف سيارات' , 'مصعد' ] , images : [ '/apartment1.jpg' ] , status : 'available' , rating : 4.5 , isNew : false } ,
{ id : 3 , title : 'بيت عائلي في بابا عمرو' , description : 'بيت واسع مناسب للعائلات في حمص.' , type : 'house' , price : 350000 , priceUnit : 'daily' , location : { city : 'حمص' , district : 'بابا عمرو' } , bedrooms : 4 , bathrooms : 3 , area : 300 , features : [ 'حديقة كبيرة' , 'موقف سيارات' , 'مدفأة' ] , images : [ '/house1.jpg' ] , status : 'booked' , rating : 4.3 , isNew : false } ,
{ id : 4 , title : 'شقة بجانب البحر' , description : 'شقة رائعة مع إطلالة بحرية في اللاذقية.' , type : 'apartment' , price : 300000 , priceUnit : 'daily' , location : { city : 'اللاذقية' , district : 'الشاطئ الأزرق' } , bedrooms : 3 , bathrooms : 2 , area : 200 , features : [ 'إطلالة بحرية' , 'شرفة' , 'تكييف' ] , images : [ '/seaside1.jpg' ] , status : 'available' , rating : 4.9 , isNew : true } ,
{ id : 5 , title : 'فيلا في درعا' , description : 'فيلا فاخرة في حي الأطباء بدرعا.' , type : 'villa' , price : 400000 , priceUnit : 'daily' , location : { city : 'درعا' , district : 'حي الأطباء' } , bedrooms : 4 , bathrooms : 3 , area : 350 , features : [ 'حديقة مثمرة' , 'أنظمة أمن' , 'مسبح' ] , images : [ '/villa4.jpg' ] , status : 'available' , rating : 4.6 , isNew : false } ,
] ;
2026-03-07 07:34:31 +03:00
2026-02-15 01:53:37 +03:00
const PropertyCard = ( { property , viewMode = 'grid' } ) => {
const [ isFavorite , setIsFavorite ] = useState ( false ) ;
const [ currentImage , setCurrentImage ] = useState ( 0 ) ;
const formatCurrency = ( amount ) => {
return amount ? . toLocaleString ( ) + ' ل.س' ;
} ;
const getPropertyTypeIcon = ( type ) => {
2026-03-26 22:20:33 +00:00
switch ( type ) {
2026-02-15 01:53:37 +03:00
case 'villa' : return < Home className = "w-4 h-4" / > ;
case 'apartment' : return < Building2 className = "w-4 h-4" / > ;
case 'house' : return < Home className = "w-4 h-4" / > ;
case 'studio' : return < Building2 className = "w-4 h-4" / > ;
default : return < Home className = "w-4 h-4" / > ;
}
} ;
const getPropertyTypeLabel = ( type ) => {
2026-03-26 22:20:33 +00:00
switch ( type ) {
2026-02-15 01:53:37 +03:00
case 'villa' : return 'فيلا' ;
case 'apartment' : return 'شقة' ;
case 'house' : return 'بيت' ;
case 'studio' : return 'استوديو' ;
default : return type ;
}
} ;
if ( viewMode === 'list' ) {
return (
< motion . div
initial = { { opacity : 0 , y : 20 } }
animate = { { opacity : 1 , y : 0 } }
className = "bg-white rounded-2xl shadow-sm hover:shadow-md transition-all duration-300 overflow-hidden border border-gray-100"
>
< div className = "flex flex-col md:flex-row" >
< div className = "md:w-1/3 relative h-64 md:h-auto bg-gray-100" >
< Image
src = { property . images [ currentImage ] || '/property-placeholder.jpg' }
alt = { property . title }
fill
className = "object-cover"
/ >
{ property . images . length > 1 && (
< div className = "absolute bottom-2 left-2 right-2 flex justify-center gap-1" >
{ property . images . map ( ( _ , idx ) => (
< button
key = { idx }
onClick = { ( ) => setCurrentImage ( idx ) }
2026-03-26 22:20:33 +00:00
className = { ` w-1.5 h-1.5 rounded-full transition-all ${ idx === currentImage ? 'bg-gray-800 w-3' : 'bg-white/70' } ` }
2026-02-15 01:53:37 +03:00
/ >
) ) }
< / d i v >
) }
< div className = "absolute top-2 right-2 flex gap-2" >
< button
onClick = { ( ) => setIsFavorite ( ! isFavorite ) }
className = "w-8 h-8 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center hover:bg-white transition-colors shadow-sm"
>
< Heart className = { ` w-4 h-4 ${ isFavorite ? 'fill-red-500 text-red-500' : 'text-gray-600' } ` } / >
< / b u t t o n >
< / d i v >
< / d i v >
< div className = "md:w-2/3 p-6" >
< div className = "flex justify-between items-start mb-3" >
< div >
< div className = "flex items-center gap-2 mb-2" >
< span className = "px-2 py-1 bg-gray-100 text-gray-700 rounded-lg text-xs font-medium flex items-center gap-1" >
{ getPropertyTypeIcon ( property . type ) }
{ getPropertyTypeLabel ( property . type ) }
< / s p a n >
2026-03-26 22:20:33 +00:00
< span className = { ` px-2 py-1 rounded-lg text-xs font-medium ${ property . status === 'available' ? 'bg-gray-800 text-white' : 'bg-gray-200 text-gray-600' } ` } >
2026-02-15 01:53:37 +03:00
{ property . status === 'available' ? 'متاح' : 'محجوز' }
< / s p a n >
< / d i v >
< h3 className = "text-xl font-bold text-gray-900 mb-1" > { property . title } < / h 3 >
< div className = "flex items-center gap-1 text-gray-500 text-sm mb-3" >
< MapPin className = "w-4 h-4" / >
{ property . location . city } ، { property . location . district }
< / d i v >
< / d i v >
< div className = "text-left" >
< div className = "text-2xl font-bold text-gray-900" > { formatCurrency ( property . price ) } < / d i v >
< div className = "text-xs text-gray-500" > / { p r o p e r t y . p r i c e U n i t = = = ' d a i l y ' ? ' ي و م ' : ' ش ه ر ' } < / d i v >
< / d i v >
< / d i v >
< div className = "flex flex-wrap gap-4 mb-4" >
< div className = "flex items-center gap-1 text-gray-600" >
< Bed className = "w-4 h-4" / >
< span > { property . bedrooms } غرف < / s p a n >
< / d i v >
< div className = "flex items-center gap-1 text-gray-600" >
< Bath className = "w-4 h-4" / >
< span > { property . bathrooms } حمامات < / s p a n >
< / d i v >
< div className = "flex items-center gap-1 text-gray-600" >
< Square className = "w-4 h-4" / >
< span > { property . area } م² < / s p a n >
< / d i v >
< / d i v >
2026-03-26 22:20:33 +00:00
< p className = "text-gray-600 text-sm mb-4 line-clamp-2" > { property . description } < / p >
2026-02-15 01:53:37 +03:00
< div className = "flex gap-3" >
< Link
href = { ` /property/ ${ property . id } ` }
className = "flex-1 bg-gray-800 text-white py-3 rounded-xl font-medium hover:bg-gray-900 transition-colors text-center"
>
عرض التفاصيل
< / L i n k >
< button className = "px-4 bg-gray-100 text-gray-700 py-3 rounded-xl font-medium hover:bg-gray-200 transition-colors flex items-center gap-2" >
< Phone className = "w-4 h-4" / >
< / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
< / m o t i o n . d i v >
) ;
}
return (
< motion . div
initial = { { opacity : 0 , y : 20 } }
animate = { { opacity : 1 , y : 0 } }
className = "bg-white rounded-2xl shadow-sm hover:shadow-md transition-all duration-300 overflow-hidden border border-gray-100"
>
< div className = "relative h-56 bg-gray-100" >
< Image
src = { property . images [ currentImage ] || '/property-placeholder.jpg' }
alt = { property . title }
fill
className = "object-cover"
/ >
< div className = "absolute top-2 right-2 flex gap-2" >
< button
onClick = { ( ) => setIsFavorite ( ! isFavorite ) }
className = "w-8 h-8 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center hover:bg-white transition-colors shadow-sm"
>
< Heart className = { ` w-4 h-4 ${ isFavorite ? 'fill-red-500 text-red-500' : 'text-gray-600' } ` } / >
< / b u t t o n >
< / d i v >
< / d i v >
< div className = "p-5" >
< div className = "flex justify-between items-start mb-3" >
< div >
< div className = "flex items-center gap-2 mb-2" >
< span className = "px-2 py-1 bg-gray-100 text-gray-700 rounded-lg text-xs font-medium flex items-center gap-1" >
{ getPropertyTypeIcon ( property . type ) }
{ getPropertyTypeLabel ( property . type ) }
< / s p a n >
{ property . status === 'available' && (
2026-03-26 22:20:33 +00:00
< span className = "px-2 py-1 bg-gray-800 text-white rounded-lg text-xs font-medium" > متاح < / s p a n >
2026-02-15 01:53:37 +03:00
) }
< / d i v >
< h3 className = "font-bold text-gray-900 mb-1 line-clamp-1" > { property . title } < / h 3 >
< div className = "flex items-center gap-1 text-gray-500 text-xs mb-2" >
< MapPin className = "w-3 h-3" / >
< span className = "line-clamp-1" > { property . location . city } ، { property . location . district } < / s p a n >
< / d i v >
< / d i v >
< div className = "text-left" >
< div className = "text-xl font-bold text-gray-900" > { formatCurrency ( property . price ) } < / d i v >
< div className = "text-xs text-gray-500" > / { p r o p e r t y . p r i c e U n i t = = = ' d a i l y ' ? ' ي و م ' : ' ش ه ر ' } < / d i v >
< / d i v >
< / d i v >
< div className = "flex justify-between items-center mb-4" >
< div className = "flex items-center gap-3 text-gray-600 text-sm" >
< div className = "flex items-center gap-1" >
< Bed className = "w-4 h-4" / >
< span > { property . bedrooms } < / s p a n >
< / d i v >
< div className = "flex items-center gap-1" >
< Bath className = "w-4 h-4" / >
< span > { property . bathrooms } < / s p a n >
< / d i v >
< div className = "flex items-center gap-1" >
< Square className = "w-4 h-4" / >
< span > { property . area } م² < / s p a n >
< / d i v >
< / d i v >
< div className = "flex items-center gap-1" >
< Star className = "w-4 h-4 fill-gray-400 text-gray-400" / >
< span className = "text-sm font-medium text-gray-700" > { property . rating || 4.5 } < / s p a n >
< / d i v >
< / d i v >
< Link
href = { ` /property/ ${ property . id } ` }
className = "block w-full bg-gray-800 text-white py-3 rounded-xl font-medium hover:bg-gray-900 transition-colors text-center"
>
عرض التفاصيل
< / L i n k >
< / d i v >
< / m o t i o n . d i v >
) ;
} ;
const FilterBar = ( { filters , onFilterChange } ) => {
const [ showFilters , setShowFilters ] = useState ( false ) ;
const propertyTypes = [
{ id : 'all' , label : 'الكل' } ,
{ id : 'apartment' , label : 'شقة' , icon : Building2 } ,
{ id : 'villa' , label : 'فيلا' , icon : Home } ,
{ id : 'house' , label : 'بيت' , icon : Home } ,
] ;
const priceRanges = [
{ id : 'all' , label : 'جميع الأسعار' } ,
{ id : '0-500000' , label : 'أقل من 500,000' } ,
{ id : '500000-1000000' , label : '500,000 - 1,000,000' } ,
{ id : '1000000-2000000' , label : '1,000,000 - 2,000,000' } ,
{ id : '2000000-5000000' , label : '2,000,000 - 5,000,000' } ,
{ id : '5000000+' , label : 'أكثر من 5,000,000' }
] ;
const cities = [
{ id : 'all' , label : 'جميع المدن' } ,
2026-03-07 07:34:31 +03:00
{ id : 'دمشق' , label : 'دمشق' } ,
{ id : 'حلب' , label : 'حلب' } ,
{ id : 'حمص' , label : 'حمص' } ,
{ id : 'اللاذقية' , label : 'اللاذقية' } ,
{ id : 'درعا' , label : 'درعا' }
2026-02-15 01:53:37 +03:00
] ;
return (
< div className = "bg-white rounded-2xl shadow-sm border border-gray-100 p-4" >
< div className = "flex flex-col md:flex-row gap-3 mb-4" >
< div className = "flex-1 relative" >
< Search className = "absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" / >
< input
type = "text"
placeholder = "ابحث عن عقار..."
className = "w-full pr-12 px-4 py-3 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300 transition-all"
value = { filters . search }
onChange = { ( e ) => onFilterChange ( { ... filters , search : e . target . value } ) }
/ >
< / d i v >
< button
onClick = { ( ) => setShowFilters ( ! showFilters ) }
className = "px-6 py-3 bg-gray-100 rounded-xl font-medium hover:bg-gray-200 transition-colors flex items-center gap-2 text-gray-700"
>
< Filter className = "w-5 h-5" / >
فلاتر متقدمة
< ChevronDown className = { ` w-4 h-4 transition-transform ${ showFilters ? 'rotate-180' : '' } ` } / >
< / b u t t o n >
< / d i v >
< AnimatePresence >
{ showFilters && (
< motion . div
initial = { { height : 0 , opacity : 0 } }
animate = { { height : 'auto' , opacity : 1 } }
exit = { { height : 0 , opacity : 0 } }
className = "overflow-hidden"
>
< div className = "grid grid-cols-1 md:grid-cols-3 gap-4 pt-4 border-t border-gray-100" >
< div >
< label className = "block text-sm font-medium text-gray-700 mb-2" > نوع العقار < / l a b e l >
< div className = "flex flex-wrap gap-2" >
{ propertyTypes . map ( ( type ) => {
const Icon = type . icon ;
return (
< button
key = { type . id }
onClick = { ( ) => onFilterChange ( { ... filters , propertyType : type . id } ) }
2026-03-26 22:20:33 +00:00
className = { ` px-3 py-2 rounded-xl text-sm font-medium transition-all flex items-center gap-1 ${ filters . propertyType === type . id ? 'bg-gray-800 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' } ` }
2026-02-15 01:53:37 +03:00
>
{ Icon && < Icon className = "w-4 h-4" / > }
{ type . label }
< / b u t t o n >
) ;
} ) }
< / d i v >
< / d i v >
< div >
< label className = "block text-sm font-medium text-gray-700 mb-2" > المدينة < / l a b e l >
< select
value = { filters . city }
onChange = { ( e ) => onFilterChange ( { ... filters , city : e . target . value } ) }
className = "w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300"
>
{ cities . map ( ( city ) => (
< option key = { city . id } value = { city . id } > { city . label } < / o p t i o n >
) ) }
< / s e l e c t >
< / d i v >
< div >
< label className = "block text-sm font-medium text-gray-700 mb-2" > نطاق السعر < / l a b e l >
< select
value = { filters . priceRange }
onChange = { ( e ) => onFilterChange ( { ... filters , priceRange : e . target . value } ) }
className = "w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300"
>
{ priceRanges . map ( ( range ) => (
< option key = { range . id } value = { range . id } > { range . label } < / o p t i o n >
) ) }
< / s e l e c t >
< / d i v >
< div >
< label className = "block text-sm font-medium text-gray-700 mb-2" > غرف النوم < / l a b e l >
< select
value = { filters . bedrooms }
onChange = { ( e ) => onFilterChange ( { ... filters , bedrooms : e . target . value } ) }
className = "w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300"
>
< option value = "all" > جميع الأعداد < / o p t i o n >
< option value = "1" > 1 + < / o p t i o n >
< option value = "2" > 2 + < / o p t i o n >
< option value = "3" > 3 + < / o p t i o n >
< option value = "4" > 4 + < / o p t i o n >
< option value = "5" > 5 + < / o p t i o n >
< / s e l e c t >
< / d i v >
< div >
< label className = "block text-sm font-medium text-gray-700 mb-2" > المساحة ( م² ) < / l a b e l >
< div className = "flex gap-2" >
< input
type = "number"
placeholder = "من"
className = "w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300"
value = { filters . minArea }
onChange = { ( e ) => onFilterChange ( { ... filters , minArea : e . target . value } ) }
/ >
< input
type = "number"
placeholder = "إلى"
className = "w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300"
value = { filters . maxArea }
onChange = { ( e ) => onFilterChange ( { ... filters , maxArea : e . target . value } ) }
/ >
< / d i v >
< / d i v >
< / d i v >
< div className = "flex gap-3 mt-4 pt-4 border-t border-gray-100" >
< button
onClick = { ( ) => onFilterChange ( {
search : '' ,
propertyType : 'all' ,
city : 'all' ,
priceRange : 'all' ,
bedrooms : 'all' ,
minArea : '' ,
maxArea : '' ,
features : [ ]
} ) }
className = "px-6 py-2 bg-gray-100 rounded-xl font-medium hover:bg-gray-200 transition-colors text-gray-700"
>
إعادة تعيين
< / b u t t o n >
< button
onClick = { ( ) => setShowFilters ( false ) }
className = "px-6 py-2 bg-gray-800 text-white rounded-xl font-medium hover:bg-gray-900 transition-colors"
>
تطبيق الفلاتر
< / b u t t o n >
< / d i v >
< / m o t i o n . d i v >
) }
< / A n i m a t e P r e s e n c e >
< / d i v >
) ;
} ;
export default function PropertiesPage ( ) {
2026-03-26 22:20:33 +00:00
const [ viewMode , setViewMode ] = useState ( 'grid' ) ;
2026-02-15 01:53:37 +03:00
const [ sortBy , setSortBy ] = useState ( 'newest' ) ;
2026-03-26 22:20:33 +00:00
const [ properties , setProperties ] = useState ( FALLBACK _PROPERTIES ) ;
const [ loading , setLoading ] = useState ( true ) ;
2026-02-15 01:53:37 +03:00
const [ filters , setFilters ] = useState ( {
search : '' ,
propertyType : 'all' ,
city : 'all' ,
priceRange : 'all' ,
bedrooms : 'all' ,
minArea : '' ,
maxArea : '' ,
features : [ ]
} ) ;
2026-03-26 22:20:33 +00:00
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 ) {
setProperties ( mapped ) ;
}
} catch ( err ) {
console . warn ( 'Failed to fetch properties:' , err ) ;
} finally {
setLoading ( false ) ;
}
2026-02-15 01:53:37 +03:00
}
2026-03-26 22:20:33 +00:00
fetchProperties ( ) ;
} , [ ] ) ;
2026-02-15 01:53:37 +03:00
const filteredProperties = properties
. filter ( property => {
if ( filters . search && ! property . title . includes ( filters . search ) && ! property . description . includes ( filters . search ) ) {
return false ;
}
if ( filters . propertyType !== 'all' && property . type !== filters . propertyType ) {
return false ;
}
if ( filters . city !== 'all' && property . location . city !== filters . city ) {
return false ;
}
if ( filters . priceRange !== 'all' ) {
const [ min , max ] = filters . priceRange . split ( '-' ) ;
if ( max ) {
if ( property . price < parseInt ( min ) || property . price > parseInt ( max ) ) return false ;
} else if ( filters . priceRange . endsWith ( '+' ) ) {
2026-03-26 22:20:33 +00:00
const minVal = parseInt ( filters . priceRange . replace ( '+' , '' ) ) ;
if ( property . price < minVal ) return false ;
2026-02-15 01:53:37 +03:00
}
}
if ( filters . bedrooms !== 'all' && property . bedrooms < parseInt ( filters . bedrooms ) ) {
return false ;
}
if ( filters . minArea && property . area < parseInt ( filters . minArea ) ) return false ;
if ( filters . maxArea && property . area > parseInt ( filters . maxArea ) ) return false ;
return true ;
} )
. sort ( ( a , b ) => {
2026-03-26 22:20:33 +00:00
switch ( sortBy ) {
2026-02-15 01:53:37 +03:00
case 'price_asc' : return a . price - b . price ;
case 'price_desc' : return b . price - a . price ;
case 'rating' : return b . rating - a . rating ;
2026-03-26 22:20:33 +00:00
default : return 0 ;
2026-02-15 01:53:37 +03:00
}
} ) ;
return (
< div className = "min-h-screen bg-gray-50 py-8" >
< div className = "container mx-auto px-4" >
< motion . div
initial = { { opacity : 0 , y : - 20 } }
animate = { { opacity : 1 , y : 0 } }
className = "text-center mb-8"
>
< h1 className = "text-4xl font-bold text-gray-900 mb-2" > عقارات للإيجار < / h 1 >
< p className = "text-gray-500" > أفضل العقارات في سوريا < / p >
2026-03-26 22:20:33 +00:00
{ loading && (
< div className = "mt-4" >
< div className = "inline-block w-6 h-6 border-2 border-gray-200 border-t-gray-800 rounded-full animate-spin" > < / d i v >
< / d i v >
) }
2026-02-15 01:53:37 +03:00
< / m o t i o n . d i v >
< FilterBar filters = { filters } onFilterChange = { setFilters } / >
< div className = "flex justify-between items-center my-6" >
< div className = "text-gray-600" >
< span className = "font-bold text-gray-900" > { filteredProperties . length } < / s p a n > ع ق ا ر م ت ا ح
< / d i v >
< div className = "flex gap-3" >
< select
value = { sortBy }
onChange = { ( e ) => setSortBy ( e . target . value ) }
className = "px-4 py-2 border border-gray-200 rounded-xl focus:ring-2 focus:ring-gray-300 focus:border-gray-300 text-gray-700"
>
< option value = "newest" > الأحدث < / o p t i o n >
< option value = "price_asc" > السعر : من الأقل < / o p t i o n >
< option value = "price_desc" > السعر : من الأعلى < / o p t i o n >
< option value = "rating" > التقييم < / o p t i o n >
< / s e l e c t >
< div className = "flex gap-2" >
< button
onClick = { ( ) => setViewMode ( 'grid' ) }
2026-03-26 22:20:33 +00:00
className = { ` p-2 rounded-xl transition-colors ${ viewMode === 'grid' ? 'bg-gray-800 text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200' } ` }
2026-02-15 01:53:37 +03:00
>
< Grid3x3 className = "w-5 h-5" / >
< / b u t t o n >
< button
onClick = { ( ) => setViewMode ( 'list' ) }
2026-03-26 22:20:33 +00:00
className = { ` p-2 rounded-xl transition-colors ${ viewMode === 'list' ? 'bg-gray-800 text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200' } ` }
2026-02-15 01:53:37 +03:00
>
< List className = "w-5 h-5" / >
< / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
2026-03-26 22:20:33 +00:00
< div className = { viewMode === 'grid'
2026-02-15 01:53:37 +03:00
? 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6'
: 'space-y-4'
} >
{ filteredProperties . map ( ( property ) => (
< PropertyCard key = { property . id } property = { property } viewMode = { viewMode } / >
) ) }
< / d i v >
{ filteredProperties . length === 0 && (
< motion . div
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
className = "text-center py-16"
>
< div className = "w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4" >
< Home className = "w-12 h-12 text-gray-400" / >
< / d i v >
< h3 className = "text-xl font-bold text-gray-700 mb-2" > لا توجد عقارات < / h 3 >
< p className = "text-gray-500" > جرب تغيير معايير البحث < / p >
< / m o t i o n . d i v >
) }
< / d i v >
< / d i v >
) ;
2026-03-26 22:20:33 +00:00
}