fixed my propries page and fixed the sidebar again mouaz is the best in the west
All checks were successful
Build frontend / build (push) Successful in 44s

This commit is contained in:
mouazkh
2026-05-25 22:42:53 +03:00
parent 7b333f9b53
commit 427dc74e7f
3 changed files with 190 additions and 253 deletions

View File

@ -3,7 +3,7 @@
import { useState } from 'react';
import { motion } from 'framer-motion';
import Link from 'next/link';
import { Heart, Bell, CreditCard, Shield, UserPlus, Settings, CalendarDays, Star, FileText } from 'lucide-react';
import { Heart, Bell, CreditCard, Shield, UserPlus, Settings } from 'lucide-react';
import { useFavorites } from '@/app/contexts/FavoritesContext';
import { useNotifications } from '@/app/contexts/NotificationsContext';
import AuthService from '@/app/services/AuthService';
@ -177,57 +177,6 @@ export default function FloatingSidebar({ isRTL, isAdmin }) {
</Link>
{renderTooltip('payments', 'المدفوعات')}
</motion.div>
<motion.div
className="relative group"
variants={buttonVariants}
initial="rest"
whileHover="hover"
whileTap="tap"
onMouseEnter={() => showTooltip('booked')}
onMouseLeave={hideTooltip}
>
<Link
href="/booked-properties"
className="flex items-center justify-center w-14 h-14 rounded-xl transition-colors"
>
<CalendarDays className="w-7 h-7 text-gray-600 transition-colors group-hover:text-amber-600" />
</Link>
{renderTooltip('booked', 'حجوزاتي')}
</motion.div>
<motion.div
className="relative group"
variants={buttonVariants}
initial="rest"
whileHover="hover"
whileTap="tap"
onMouseEnter={() => showTooltip('myRates')}
onMouseLeave={hideTooltip}
>
<Link
href="/my-rates"
className="flex items-center justify-center w-14 h-14 rounded-xl transition-colors"
>
<Star className="w-7 h-7 text-gray-600 transition-colors group-hover:text-amber-600" />
</Link>
{renderTooltip('myRates', 'تقييماتي')}
</motion.div>
<motion.div
className="relative group"
variants={buttonVariants}
initial="rest"
whileHover="hover"
whileTap="tap"
onMouseEnter={() => showTooltip('reports')}
onMouseLeave={hideTooltip}
>
<Link
href="/reports"
className="flex items-center justify-center w-14 h-14 rounded-xl transition-colors"
>
<FileText className="w-7 h-7 text-gray-600 transition-colors group-hover:text-amber-600" />
</Link>
{renderTooltip('reports', 'البلاغات')}
</motion.div>
<motion.div
className="relative group"
variants={buttonVariants}

View File

@ -1076,12 +1076,12 @@ export default function OwnerPropertiesPage() {
transition={{ delay: index * 0.1 }}
className="bg-white rounded-2xl shadow-sm hover:shadow-md transition-all overflow-hidden border border-gray-200"
>
<div className="relative h-48 bg-gray-100">
<div className="relative aspect-[16/10] bg-gray-100 overflow-hidden">
{property.images && property.images.length > 0 ? (
<img
src={property.images[0]}
alt={property.title}
className="w-full h-full object-cover"
className="w-full h-full object-cover hover:scale-105 transition-transform duration-300"
/>
) : (
<div className="w-full h-full flex items-center justify-center">
@ -1089,133 +1089,123 @@ export default function OwnerPropertiesPage() {
</div>
)}
<div className="absolute top-2 right-2 flex gap-1">
<span className={`px-2 py-1 rounded-lg text-xs font-medium shadow-sm ${
<span className={`px-2 py-0.5 rounded-md text-xs font-medium shadow-sm backdrop-blur-sm ${
property.status === 'available'
? 'bg-green-100 text-green-800'
: 'bg-yellow-100 text-yellow-800'
? 'bg-white/90 text-green-700'
: 'bg-white/90 text-yellow-700'
}`}>
{property.status === 'available' ? 'متاح' : 'مؤجر'}
</span>
{property.purpose === 'rent' && property.furnished && (
<span className="px-2 py-1 rounded-lg text-xs font-medium bg-amber-100 text-amber-800 shadow-sm">
مفروش
</span>
)}
{property.purpose === 'rent' && !property.furnished && property.furnished !== undefined && (
<span className="px-2 py-1 rounded-lg text-xs font-medium bg-gray-100 text-gray-600 shadow-sm">
غير مفروش
{property.purpose === 'rent' && property.furnished !== undefined && (
<span className={`px-2 py-0.5 rounded-md text-xs font-medium shadow-sm backdrop-blur-sm ${
property.furnished ? 'bg-white/90 text-amber-700' : 'bg-white/90 text-gray-600'
}`}>
{property.furnished ? 'مفروش' : 'غير مفروش'}
</span>
)}
</div>
<div className="absolute top-2 left-2">
<span className="px-2 py-0.5 rounded-md text-xs font-medium bg-white/90 text-amber-700 shadow-sm backdrop-blur-sm">
{property.propertyTypeLabel || (property.propertyType === 'apartment' ? 'شقة' : property.propertyType === 'villa' ? 'فيلا' : property.propertyType === 'sweet' ? 'سويت' : property.propertyType === 'room' ? 'غرفة' : property.propertyType === 'studio' ? 'استوديو' : property.propertyType === 'office' ? 'مكتب' : property.propertyType === 'farms' ? 'مزرعة' : property.propertyType === 'shop' ? 'متجر' : property.propertyType === 'warehouse' ? 'مستودع' : 'عقار')}
</span>
</div>
</div>
<div className="p-4">
<div className="flex items-center gap-2 mb-1">
<span className="text-xs px-2 py-0.5 bg-amber-50 text-amber-700 rounded-full">{property.propertyTypeLabel || (property.propertyType === 'apartment' ? 'شقة' : property.propertyType === 'villa' ? 'فيلا' : property.propertyType === 'sweet' ? 'سويت' : property.propertyType === 'room' ? 'غرفة' : property.propertyType === 'studio' ? 'استوديو' : property.propertyType === 'office' ? 'مكتب' : property.propertyType === 'farms' ? 'مزرعة' : property.propertyType === 'shop' ? 'متجر' : property.propertyType === 'warehouse' ? 'مستودع' : 'عقار')}</span>
</div>
<h3 className="font-bold text-gray-900 mb-2">{property.title}</h3>
<div className="flex items-center gap-1 text-gray-500 text-sm mb-3">
<MapPin className="w-4 h-4" />
{property.address || property.location || 'موقع غير محدد'}
<div className="p-3">
<div className="flex items-start justify-between mb-1">
<h3 className="font-bold text-gray-900 truncate flex-1 ml-2">{property.title}</h3>
{property.rating > 0 && (
<div className="flex items-center gap-0.5 text-amber-600 shrink-0">
<Star className="w-3 h-3 fill-amber-500" />
<span className="text-xs font-medium">{Number(property.rating).toFixed(1)}</span>
</div>
)}
</div>
<div className="flex flex-wrap items-center gap-3 text-sm text-gray-600 mb-3">
<div className="flex items-center gap-1">
<Bed className="w-4 h-4" />
<span>{property.bedrooms}</span>
</div>
<div className="flex items-center gap-1">
<Bath className="w-4 h-4" />
<span>{property.bathrooms}</span>
</div>
<div className="flex items-center gap-1">
<Square className="w-4 h-4" />
<span>{property.area}م²</span>
</div>
<div className="flex items-center gap-1 text-gray-500 text-xs mb-2">
<MapPin className="w-3 h-3" />
<span className="truncate">{property.address || property.location || 'موقع غير محدد'}</span>
</div>
<div className="flex flex-wrap items-center gap-2 text-xs text-gray-600 mb-2">
{property.bedrooms > 0 && (
<div className="flex items-center gap-0.5 bg-gray-50 px-2 py-0.5 rounded-md">
<Bed className="w-3 h-3" />
<span>{property.bedrooms}</span>
</div>
)}
{property.bathrooms > 0 && (
<div className="flex items-center gap-0.5 bg-gray-50 px-2 py-0.5 rounded-md">
<Bath className="w-3 h-3" />
<span>{property.bathrooms}</span>
</div>
)}
{property.area > 0 && (
<div className="flex items-center gap-0.5 bg-gray-50 px-2 py-0.5 rounded-md">
<Square className="w-3 h-3" />
<span>{property.area}م²</span>
</div>
)}
{property.floor > 0 && (
<div className="flex items-center gap-1">
<Layers className="w-4 h-4" />
<div className="flex items-center gap-0.5 bg-gray-50 px-2 py-0.5 rounded-md">
<Layers className="w-3 h-3" />
<span>ط {property.floor}</span>
</div>
)}
{property.salons > 0 && (
<div className="flex items-center gap-1">
<Sofa className="w-4 h-4" />
<div className="flex items-center gap-0.5 bg-gray-50 px-2 py-0.5 rounded-md">
<Sofa className="w-3 h-3" />
<span>{property.salons}</span>
</div>
)}
{property.balconies > 0 && (
<div className="flex items-center gap-1">
<DoorOpen className="w-4 h-4" />
<div className="flex items-center gap-0.5 bg-gray-50 px-2 py-0.5 rounded-md">
<DoorOpen className="w-3 h-3" />
<span>{property.balconies}</span>
</div>
)}
{property.rating > 0 && (
<div className="flex items-center gap-1 text-amber-600">
<Star className="w-3 h-3 fill-amber-500" />
<span>{Number(property.rating).toFixed(1)}</span>
</div>
)}
</div>
<div className="flex justify-between items-center pt-3 border-t border-gray-100">
<div className="flex justify-between items-center pt-2 border-t border-gray-100">
<div>
{property.purpose === 'rent' ? (
<div className="flex flex-wrap items-center gap-x-3">
{property.rentType === 'monthly' && property.monthlyPrice > 0 && (
<span>
<span className="text-lg font-bold text-amber-600">{Number(property.monthlyPrice).toLocaleString()}</span>
<span className="text-xs text-gray-500 mr-1">ل.س /شهر</span>
<div>
{property.monthlyPrice > 0 && (
<span className="text-base font-bold text-amber-600">
{Number(property.monthlyPrice).toLocaleString()}
<span className="text-xs text-gray-500 font-normal mr-1">ل.س /شهر</span>
</span>
)}
{property.rentType === 'daily' && property.dailyPrice > 0 && (
<span>
<span className="text-lg font-bold text-amber-600">{Number(property.dailyPrice).toLocaleString()}</span>
<span className="text-xs text-gray-500 mr-1">ل.س /يوم</span>
</span>
)}
{property.rentType === 'daily' && property.monthlyPrice > 0 && (
<span>
<span className="text-lg font-bold text-amber-600">{Number(property.monthlyPrice).toLocaleString()}</span>
<span className="text-xs text-gray-500 mr-1">ل.س /شهر</span>
{property.dailyPrice > 0 && !property.monthlyPrice && (
<span className="text-base font-bold text-amber-600">
{Number(property.dailyPrice).toLocaleString()}
<span className="text-xs text-gray-500 font-normal mr-1">ل.س /يوم</span>
</span>
)}
{property.deposit > 0 && (
<span className="text-xs text-gray-400">تأمين: {Number(property.deposit).toLocaleString()}</span>
<div className="text-[10px] text-gray-400">تأمين: {Number(property.deposit).toLocaleString()} ل.س</div>
)}
</div>
) : (
<div>
<span className="text-lg font-bold text-blue-600">
{Number(property.salePrice).toLocaleString()} ل.س
</span>
<span className="text-xs text-gray-500 mr-1">للبيع</span>
</div>
<span className="text-base font-bold text-blue-600">
{Number(property.salePrice).toLocaleString()} ل.س
</span>
)}
</div>
<div className="flex gap-2">
<button
onClick={() => setViewModal({ isOpen: true, property })}
className="p-2 hover:bg-blue-50 rounded-lg transition-colors group"
title="عرض التفاصيل"
>
<Eye className="w-4 h-4 text-gray-600 group-hover:text-blue-600" />
<div className="flex gap-1">
<button onClick={() => setViewModal({ isOpen: true, property })}
className="p-1.5 hover:bg-blue-50 rounded-lg transition-colors group" title="عرض التفاصيل">
<Eye className="w-3.5 h-3.5 text-gray-400 group-hover:text-blue-600" />
</button>
<button
onClick={() => setEditModal({ isOpen: true, property })}
className="p-2 hover:bg-amber-50 rounded-lg transition-colors group"
title="تعديل العقار"
>
<Edit className="w-4 h-4 text-gray-600 group-hover:text-amber-600" />
<button onClick={() => setEditModal({ isOpen: true, property })}
className="p-1.5 hover:bg-amber-50 rounded-lg transition-colors group" title="تعديل العقار">
<Edit className="w-3.5 h-3.5 text-gray-400 group-hover:text-amber-600" />
</button>
<button
onClick={() => setDeleteModal({ isOpen: true, property })}
className="p-2 hover:bg-red-50 rounded-lg transition-colors group"
title="حذف العقار"
>
<Trash2 className="w-4 h-4 text-gray-600 group-hover:text-red-600" />
<button onClick={() => setDeleteModal({ isOpen: true, property })}
className="p-1.5 hover:bg-red-50 rounded-lg transition-colors group" title="حذف العقار">
<Trash2 className="w-3.5 h-3.5 text-gray-400 group-hover:text-red-600" />
</button>
</div>
</div>

View File

@ -302,15 +302,15 @@ export default function PropertyDetailsPage() {
</Link>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 space-y-6">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-5">
{/* Image Gallery */}
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="bg-white rounded-2xl overflow-hidden shadow-sm border border-gray-200">
<div className="relative bg-gray-900" style={{ minHeight: '420px', maxHeight: '520px' }}>
<div className="relative bg-gray-900" style={{ minHeight: '380px', maxHeight: '460px' }}>
{property.images.length > 0 ? (
<img src={property.images[currentImage]} alt={property.title}
className="w-full h-full object-contain mx-auto"
style={{ minHeight: '420px', maxHeight: '520px' }} />
style={{ minHeight: '380px', maxHeight: '460px' }} />
) : (
<div className="w-full h-full flex items-center justify-center" style={{ minHeight: '420px' }}>
<div className="text-center">
@ -363,29 +363,27 @@ export default function PropertyDetailsPage() {
</motion.div>
{/* Property Info */}
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="bg-white rounded-2xl p-6 shadow-sm border border-gray-200">
<div className="flex justify-between items-start mb-4">
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="bg-white rounded-2xl p-5 shadow-sm border border-gray-200">
<div className="flex justify-between items-start mb-3">
<div>
<div className="flex items-center gap-2 mb-2">
<span className="px-3 py-1 bg-amber-100 text-amber-800 rounded-full text-sm">{property.typeLabel}</span>
<span className={`px-3 py-1 rounded-full text-sm ${property.status === 'available' ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'}`}>{property.statusLabel}</span>
<div className="flex items-center gap-2 mb-1">
<span className="px-2 py-0.5 bg-amber-100 text-amber-800 rounded-full text-xs">{property.typeLabel}</span>
<span className={`px-2 py-0.5 rounded-full text-xs ${property.status === 'available' ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'}`}>{property.statusLabel}</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">{property.title}</h1>
<div className="flex items-center gap-1 text-gray-500 mt-1">
<MapPin className="w-4 h-4" />
<h1 className="text-xl font-bold text-gray-900">{property.title}</h1>
<div className="flex items-center gap-1 text-gray-500 text-xs mt-0.5">
<MapPin className="w-3 h-3" />
<span>{property.location.address || property.location.city}</span>
</div>
</div>
<div className="flex gap-2">
<button onClick={handleFavorite} disabled={favLoading}
className="p-2 rounded-full hover:bg-gray-100 transition-colors">
<Heart className={`w-6 h-6 ${isFav ? 'fill-red-500 text-red-500' : 'text-gray-400'}`} />
</button>
</div>
<button onClick={handleFavorite} disabled={favLoading}
className="p-1.5 rounded-full hover:bg-gray-100 transition-colors">
<Heart className={`w-5 h-5 ${isFav ? 'fill-red-500 text-red-500' : 'text-gray-400'}`} />
</button>
</div>
{/* Price */}
<div className="bg-amber-50 rounded-xl p-4 mb-6">
<div className="bg-amber-50 rounded-xl p-3 mb-4">
{property.isRent ? (
<div className="flex flex-wrap gap-6 items-end">
{property.priceDisplay.monthly > 0 && (
@ -416,79 +414,79 @@ export default function PropertyDetailsPage() {
</div>
{/* Specs Tiles */}
<div className="grid grid-cols-3 md:grid-cols-6 gap-2 mb-6">
<div className="grid grid-cols-3 md:grid-cols-6 gap-1.5 mb-4">
{property.bedrooms > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<Bed className="w-5 h-5 text-amber-500 mx-auto mb-1" />
<div className="font-bold text-gray-900">{property.bedrooms}</div>
<div className="text-xs text-gray-500">غرف نوم</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<Bed className="w-4 h-4 text-amber-500 mx-auto mb-0.5" />
<div className="font-bold text-gray-900 text-sm">{property.bedrooms}</div>
<div className="text-[10px] text-gray-500">غرف نوم</div>
</div>
)}
{property.bathrooms > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<Bath className="w-5 h-5 text-amber-500 mx-auto mb-1" />
<div className="font-bold text-gray-900">{property.bathrooms}</div>
<div className="text-xs text-gray-500">حمامات</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<Bath className="w-4 h-4 text-amber-500 mx-auto mb-0.5" />
<div className="font-bold text-gray-900 text-sm">{property.bathrooms}</div>
<div className="text-[10px] text-gray-500">حمامات</div>
</div>
)}
{property.area > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<Square className="w-5 h-5 text-amber-500 mx-auto mb-1" />
<div className="font-bold text-gray-900">{property.area}</div>
<div className="text-xs text-gray-500">م²</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<Square className="w-4 h-4 text-amber-500 mx-auto mb-0.5" />
<div className="font-bold text-gray-900 text-sm">{property.area}</div>
<div className="text-[10px] text-gray-500">م²</div>
</div>
)}
{property.floor > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<Layers className="w-5 h-5 text-amber-500 mx-auto mb-1" />
<div className="font-bold text-gray-900">{property.floor}</div>
<div className="text-xs text-gray-500">طابق</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<Layers className="w-4 h-4 text-amber-500 mx-auto mb-0.5" />
<div className="font-bold text-gray-900 text-sm">{property.floor}</div>
<div className="text-[10px] text-gray-500">طابق</div>
</div>
)}
{property.salons > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<Sofa className="w-5 h-5 text-amber-500 mx-auto mb-1" />
<div className="font-bold text-gray-900">{property.salons}</div>
<div className="text-xs text-gray-500">صالونات</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<Sofa className="w-4 h-4 text-amber-500 mx-auto mb-0.5" />
<div className="font-bold text-gray-900 text-sm">{property.salons}</div>
<div className="text-[10px] text-gray-500">صالونات</div>
</div>
)}
{property.balconies > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<DoorOpen className="w-5 h-5 text-amber-500 mx-auto mb-1" />
<div className="font-bold text-gray-900">{property.balconies}</div>
<div className="text-xs text-gray-500">بلكونات</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<DoorOpen className="w-4 h-4 text-amber-500 mx-auto mb-0.5" />
<div className="font-bold text-gray-900 text-sm">{property.balconies}</div>
<div className="text-[10px] text-gray-500">بلكونات</div>
</div>
)}
{avgRating !== null && avgRating > 0 && (
<div className="bg-gray-50 rounded-xl p-3 text-center">
<Star className="w-5 h-5 text-amber-500 mx-auto mb-1 fill-amber-500" />
<div className="font-bold text-gray-900">{avgRating.toFixed(1)}</div>
<div className="text-xs text-gray-500">التقييم</div>
<div className="bg-gray-50 rounded-lg p-2 text-center">
<Star className="w-4 h-4 text-amber-500 mx-auto mb-0.5 fill-amber-500" />
<div className="font-bold text-gray-900 text-sm">{avgRating.toFixed(1)}</div>
<div className="text-[10px] text-gray-500">التقييم</div>
</div>
)}
</div>
{/* Description */}
{property.description && (
<div className="mb-6">
<h3 className="font-bold text-gray-900 mb-2">الوصف</h3>
<p className="text-gray-600 leading-relaxed">{property.description}</p>
<div className="mb-4">
<h3 className="font-bold text-gray-900 mb-1 text-sm">الوصف</h3>
<p className="text-gray-600 text-sm leading-relaxed">{property.description}</p>
</div>
)}
{/* Features */}
<div className="flex flex-wrap gap-2 mb-6">
{property.isSmokeAllow && <span className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm border flex items-center gap-1"><Wind className="w-3 h-3" /> يسمح بالتدخين</span>}
{!property.isSmokeAllow && <span className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm border flex items-center gap-1"><Ban className="w-3 h-3" /> ممنوع التدخين</span>}
{property.isVisitorAllow && <span className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm border flex items-center gap-1"><Users className="w-3 h-3" /> يسمح بالزوار</span>}
{property.specializedFor && <span className="px-3 py-1 bg-amber-50 text-amber-700 rounded-full text-sm border border-amber-200 flex items-center gap-1"><Users className="w-3 h-3" /> {property.specializedFor}</span>}
<div className="flex flex-wrap gap-1.5 mb-4">
{property.isSmokeAllow && <span className="px-2 py-0.5 bg-gray-100 text-gray-700 rounded-full text-xs border flex items-center gap-1"><Wind className="w-3 h-3" /> يسمح بالتدخين</span>}
{!property.isSmokeAllow && <span className="px-2 py-0.5 bg-gray-100 text-gray-700 rounded-full text-xs border flex items-center gap-1"><Ban className="w-3 h-3" /> ممنوع التدخين</span>}
{property.isVisitorAllow && <span className="px-2 py-0.5 bg-gray-100 text-gray-700 rounded-full text-xs border flex items-center gap-1"><Users className="w-3 h-3" /> يسمح بالزوار</span>}
{property.specializedFor && <span className="px-2 py-0.5 bg-amber-50 text-amber-700 rounded-full text-xs border border-amber-200 flex items-center gap-1"><Users className="w-3 h-3" /> {property.specializedFor}</span>}
</div>
{/* Services with detail text */}
{Object.keys(property.services).length > 0 && (
<div className="mb-6">
<h3 className="font-bold text-gray-900 mb-3">الخدمات</h3>
<div className="flex flex-wrap gap-2">
<div className="mb-4">
<h3 className="font-bold text-gray-900 mb-2 text-sm">الخدمات</h3>
<div className="flex flex-wrap gap-1.5">
{Object.entries(property.services).map(([key, val]) => {
if (!val) return null;
const detail = typeof val === 'object' && val.detail ? val.detail : null;
@ -505,12 +503,12 @@ export default function PropertyDetailsPage() {
{/* Room Details (only for room type) */}
{isRoomType && Object.keys(property.roomDetails).length > 0 && (
<div className="mb-6 bg-blue-50 rounded-xl p-4">
<h3 className="font-bold text-gray-900 mb-3 flex items-center gap-2">
<Info className="w-5 h-5 text-blue-500" />
<div className="mb-4 bg-blue-50 rounded-xl p-3">
<h3 className="font-bold text-gray-900 mb-2 text-sm flex items-center gap-2">
<Info className="w-4 h-4 text-blue-500" />
تفاصيل الغرفة
</h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
<div className="grid grid-cols-2 md:grid-cols-3 gap-2">
{(() => {
const rd = property.roomDetails;
const items = [];
@ -542,24 +540,24 @@ export default function PropertyDetailsPage() {
{/* Proximity */}
{Object.keys(property.proximity).length > 0 && (
<div className="mb-6">
<h3 className="font-bold text-gray-900 mb-3">القرب من الخدمات</h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-2">
<div className="mb-4">
<h3 className="font-bold text-gray-900 mb-2 text-sm">القرب من الخدمات</h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-1.5">
{Object.entries(property.proximity).map(([key, val]) => {
if (!val) return null;
const dist = typeof val === 'object' ? val.distance : val;
return (
<div key={key} className="bg-gray-50 rounded-lg p-3 flex items-center gap-2">
{key === 'School' && <School className="w-4 h-4 text-amber-500 flex-shrink-0" />}
{key === 'Hospital' && <Hospital className="w-4 h-4 text-amber-500 flex-shrink-0" />}
{key === 'Restaurant' && <Store className="w-4 h-4 text-amber-500 flex-shrink-0" />}
{key === 'University' && <GraduationCap className="w-4 h-4 text-amber-500 flex-shrink-0" />}
{key === 'Park' && <TreePine className="w-4 h-4 text-amber-500 flex-shrink-0" />}
{key === 'Mall' && <Building className="w-4 h-4 text-amber-500 flex-shrink-0" />}
{!['School','Hospital','Restaurant','University','Park','Mall'].includes(key) && <MapPin className="w-4 h-4 text-amber-500 flex-shrink-0" />}
<div key={key} className="bg-gray-50 rounded-lg p-2 flex items-center gap-1.5">
{key === 'School' && <School className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
{key === 'Hospital' && <Hospital className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
{key === 'Restaurant' && <Store className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
{key === 'University' && <GraduationCap className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
{key === 'Park' && <TreePine className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
{key === 'Mall' && <Building className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
{!['School','Hospital','Restaurant','University','Park','Mall'].includes(key) && <MapPin className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />}
<div>
<div className="text-sm font-medium text-gray-900">{proximityLabels[key] || key}</div>
<div className="text-xs text-gray-500">{dist} {typeof dist === 'number' ? 'كم' : ''}</div>
<div className="text-xs font-medium text-gray-900">{proximityLabels[key] || key}</div>
<div className="text-[10px] text-gray-500">{dist} {typeof dist === 'number' ? 'كم' : ''}</div>
</div>
</div>
);
@ -570,19 +568,19 @@ export default function PropertyDetailsPage() {
{/* Terms as checklist */}
{Object.keys(property.terms).length > 0 && (
<div className="mb-6">
<h3 className="font-bold text-gray-900 mb-3">الشروط</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
<div className="mb-4">
<h3 className="font-bold text-gray-900 mb-2 text-sm">الشروط</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-1.5">
{Object.entries(property.terms).map(([key, val]) => {
if (!val) return null;
return (
<div key={key} className="flex items-center gap-2 p-2 bg-gray-50 rounded-lg">
<div key={key} className="flex items-center gap-1.5 p-1.5 bg-gray-50 rounded-lg">
{key.startsWith('No') || key.startsWith('Only') ? (
<Ban className="w-4 h-4 text-red-500 flex-shrink-0" />
<Ban className="w-3.5 h-3.5 text-red-500 flex-shrink-0" />
) : (
<Check className="w-4 h-4 text-green-500 flex-shrink-0" />
<Check className="w-3.5 h-3.5 text-green-500 flex-shrink-0" />
)}
<span className="text-sm text-gray-700">{termLabels[key] || key}</span>
<span className="text-xs text-gray-700">{termLabels[key] || key}</span>
</div>
);
})}
@ -641,45 +639,45 @@ export default function PropertyDetailsPage() {
</div>
{/* Sidebar */}
<div className="space-y-6">
<div className="space-y-4">
{/* Booking Card */}
{property.isRent && (
<motion.div initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} className="bg-white rounded-2xl p-6 shadow-sm border border-gray-200 sticky top-6">
<div className="flex items-center gap-2 mb-4">
<Calendar className="w-5 h-5 text-amber-500" />
<h3 className="text-lg font-bold text-gray-900">حجز العقار</h3>
<motion.div initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} className="bg-white rounded-2xl p-5 shadow-sm border border-gray-200 sticky top-6">
<div className="flex items-center gap-2 mb-3">
<Calendar className="w-4 h-4 text-amber-500" />
<h3 className="font-bold text-gray-900">حجز العقار</h3>
</div>
{bookingSuccess ? (
<div className="text-center py-4">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-3">
<Check className="w-8 h-8 text-green-600" />
<div className="text-center py-3">
<div className="w-14 h-14 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-2">
<Check className="w-7 h-7 text-green-600" />
</div>
<h4 className="font-bold text-green-700 mb-1">تم إرسال طلب الحجز</h4>
<p className="text-sm text-gray-500">سيتم مراجعة طلبك من قبل المالك</p>
<h4 className="font-bold text-green-700 text-sm mb-1">تم إرسال طلب الحجز</h4>
<p className="text-xs text-gray-500">سيتم مراجعة طلبك من قبل المالك</p>
</div>
) : (
<>
<div className="space-y-3 mb-4">
<div className="space-y-2 mb-3">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">من تاريخ</label>
<label className="block text-xs font-medium text-gray-700 mb-1">من تاريخ</label>
<input type="date" value={bookingDates.start} onChange={e => setBookingDates(prev => ({ ...prev, start: e.target.value }))}
className="w-full px-3 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-amber-500" />
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-xl focus:ring-2 focus:ring-amber-500" />
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">إلى تاريخ</label>
<label className="block text-xs font-medium text-gray-700 mb-1">إلى تاريخ</label>
<input type="date" value={bookingDates.end} onChange={e => setBookingDates(prev => ({ ...prev, end: e.target.value }))}
className="w-full px-3 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-amber-500" />
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-xl focus:ring-2 focus:ring-amber-500" />
</div>
</div>
{bookingError && (
<div className="bg-red-50 text-red-600 p-3 rounded-xl text-sm mb-4">{bookingError}</div>
<div className="bg-red-50 text-red-600 p-2.5 rounded-xl text-xs mb-3">{bookingError}</div>
)}
<button onClick={handleBookNow} disabled={bookingLoading}
className="w-full bg-amber-500 hover:bg-amber-600 text-white py-3 rounded-xl font-bold transition-all disabled:opacity-50 flex items-center justify-center gap-2">
{bookingLoading ? <Loader2 className="w-5 h-5 animate-spin" /> : <Calendar className="w-5 h-5" />}
className="w-full bg-amber-500 hover:bg-amber-600 text-white py-2.5 rounded-xl font-bold text-sm transition-all disabled:opacity-50 flex items-center justify-center gap-2">
{bookingLoading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Calendar className="w-4 h-4" />}
{bookingLoading ? 'جاري الحجز...' : 'حجز الآن'}
</button>
</>
@ -688,30 +686,30 @@ export default function PropertyDetailsPage() {
)}
{/* Contact Card */}
<motion.div initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} className="bg-white rounded-2xl p-6 shadow-sm border border-gray-200">
<div className="flex items-center gap-2 mb-4">
<Phone className="w-5 h-5 text-amber-500" />
<h3 className="text-lg font-bold text-gray-900">معلومات المالك</h3>
<motion.div initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} className="bg-white rounded-2xl p-5 shadow-sm border border-gray-200">
<div className="flex items-center gap-2 mb-3">
<Phone className="w-4 h-4 text-amber-500" />
<h3 className="font-bold text-gray-900">معلومات المالك</h3>
</div>
{showContact && contactInfo ? (
<div className="space-y-3">
<div className="flex items-center gap-3 p-3 bg-gray-50 rounded-xl">
<Phone className="w-5 h-5 text-gray-600 flex-shrink-0" />
<span className="font-medium text-gray-900" dir="ltr">{contactInfo.phone || contactInfo.phoneNumber || '—'}</span>
<div className="space-y-2">
<div className="flex items-center gap-2.5 p-2.5 bg-gray-50 rounded-xl">
<Phone className="w-4 h-4 text-gray-600 flex-shrink-0" />
<span className="font-medium text-gray-900 text-sm" dir="ltr">{contactInfo.phone || contactInfo.phoneNumber || '—'}</span>
</div>
{contactInfo.whatsAppNumber && (
<a href={`https://wa.me/${contactInfo.whatsAppNumber.replace(/[^0-9]/g, '')}`} target="_blank" rel="noopener noreferrer"
className="flex items-center gap-3 p-3 bg-green-50 rounded-xl hover:bg-green-100 transition-colors">
<MessageCircle className="w-5 h-5 text-green-600 flex-shrink-0" />
<span className="font-medium text-gray-900" dir="ltr">{contactInfo.whatsAppNumber}</span>
className="flex items-center gap-2.5 p-2.5 bg-green-50 rounded-xl hover:bg-green-100 transition-colors">
<MessageCircle className="w-4 h-4 text-green-600 flex-shrink-0" />
<span className="font-medium text-gray-900 text-sm" dir="ltr">{contactInfo.whatsAppNumber}</span>
</a>
)}
</div>
) : (
<button onClick={fetchContactInfo}
className="w-full bg-gray-800 hover:bg-gray-900 text-white py-3 rounded-xl font-medium transition-colors flex items-center justify-center gap-2">
<Phone className="w-5 h-5" />
className="w-full bg-gray-800 hover:bg-gray-900 text-white py-2.5 rounded-xl font-medium text-sm transition-colors flex items-center justify-center gap-2">
<Phone className="w-4 h-4" />
عرض معلومات الاتصال
</button>
)}