Files
SweetHome/app/property/[id]/PropertyDetail.js

546 lines
26 KiB
JavaScript
Raw Normal View History

'use client';
import { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import toast, { Toaster } from 'react-hot-toast';
import Link from 'next/link';
2026-05-25 21:27:39 +03:00
import { useParams, useRouter } from 'next/navigation';
import {
2026-05-25 21:27:39 +03:00
MapPin, Bed, Bath, Square, DollarSign, Heart, Share2,
Phone, Mail, MessageCircle, Calendar, Shield, Star,
ChevronLeft, ChevronRight, Check, X, Wifi, Car, Wind,
Camera, Home, Building2, Users, Clock, FileText,
LogIn, Loader2, ArrowLeft, ImageIcon, ChevronDown
} from 'lucide-react';
2026-05-25 21:27:39 +03:00
import { getRentProperty, getSaleProperty, getSalePropertyById, bookReservation, getAvailableDateRanges, getOwnerContactInformation } from '../../utils/api';
import AuthService from '../../services/AuthService';
import { useFavorites } from '@/app/contexts/FavoritesContext';
import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from '../../enums';
2026-04-26 13:46:30 +03:00
import PropertyRatingList from '@/app/components/ratings/PropertyRatingList';
import PropertyRatingForm from '@/app/components/ratings/PropertyRatingForm';
2026-05-25 21:27:39 +03:00
import StarRating from '@/app/components/ratings/StarRating';
import { getPropertyAverageRating } from '../../utils/ratings';
import dynamic from 'next/dynamic';
import 'leaflet/dist/leaflet.css';
const MapContainer = dynamic(() => import('react-leaflet').then(m => m.MapContainer), { ssr: false });
const TileLayer = dynamic(() => import('react-leaflet').then(m => m.TileLayer), { ssr: false });
const Marker = dynamic(() => import('react-leaflet').then(m => m.Marker), { ssr: false });
const Popup = dynamic(() => import('react-leaflet').then(m => m.Popup), { ssr: false });
2026-04-26 13:46:30 +03:00
function formatCurrency(amount) {
2026-05-25 21:27:39 +03:00
if (!amount || isNaN(amount)) return '0';
return Number(amount).toLocaleString('ar-SA');
}
2026-05-25 21:27:39 +03:00
function buildImageUrl(img) {
if (!img) return '';
const apiBase = typeof window !== 'undefined'
? (process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api')
: '';
if (img.startsWith('http')) return img;
return `${apiBase}${img.startsWith('/') ? '' : '/Pictures/'}${img}`;
}
function mapApiDetail(item) {
if (!item) return null;
const info = item.propertyInformation || {};
2026-05-25 21:27:39 +03:00
const details = (() => { try { return JSON.parse(info.detailsJSON || '{}'); } catch { return {}; } })();
2026-05-25 21:27:39 +03:00
const isRent = item.dailyRent != null || item.monthlyRent != null;
const dailyPrice = item.dailyRent || 0;
const monthlyPrice = item.monthlyRent || 0;
const salePrice = item.price || 0;
const price = isRent ? (monthlyPrice || dailyPrice) : salePrice;
const priceUnit = isRent ? (monthlyPrice ? 'monthly' : 'daily') : 'sale';
2026-05-25 21:27:39 +03:00
const propType = BuildingTypeKeys[info.buildingType] ?? BuildingTypeKeys[item.type] ?? 'apartment';
const typeLabel = { apartment: 'شقة', villa: 'فيلا', house: 'بيت', sweet: 'سويت', studio: 'استوديو', office: 'مكتب', shop: 'متجر', warehouse: 'مستودع', farms: 'مزرعة', room: 'غرفة' }[propType] || 'عقار';
const status = PropertyStatusKeys[info.status] ?? PropertyStatusKeys[item.status] ?? 'available';
const statusLabel = { available: 'متاح', booked: 'محجوز', maintenance: 'صيانة', not_available: 'غير متاح' }[status] || 'متاح';
2026-05-25 21:27:39 +03:00
const rawImages = Array.isArray(info.images) ? info.images : [];
const images = rawImages.length > 0 ? rawImages.map(buildImageUrl) : [];
2026-05-25 21:27:39 +03:00
const services = details.services || {};
const terms = details.terms || {};
return {
id: item.id,
title: info.address || `عقار #${item.id}`,
2026-04-26 13:46:30 +03:00
description: info.description || '',
type: propType,
2026-05-25 21:27:39 +03:00
typeLabel,
price,
2026-04-26 13:46:30 +03:00
priceUnit,
2026-05-25 21:27:39 +03:00
priceDisplay: { daily: dailyPrice, monthly: monthlyPrice, sale: salePrice },
isRent,
location: {
city: extractCity(info.address) || 'دمشق',
address: info.address || '',
2026-05-25 21:27:39 +03:00
lat: parseFloat(info.cordsX) || 0,
lng: parseFloat(info.cordsY) || 0,
},
bedrooms: info.numberOfBedRooms || 0,
bathrooms: info.numberOfBathRooms || 0,
area: info.space || 0,
images,
status,
2026-05-25 21:27:39 +03:00
statusLabel,
services,
terms,
details,
2026-04-26 13:46:30 +03:00
deposit: item.deposit || 0,
2026-05-25 21:27:39 +03:00
currencyId: item.currencyId,
isSmokeAllow: item.isSmokeAllow,
isVisitorAllow: item.isVisitorAllow,
specializedFor: item.specializedFor,
_raw: item,
};
}
export default function PropertyDetailsPage() {
const params = useParams();
2026-05-25 21:27:39 +03:00
const router = useRouter();
const { isFavorite, addFavorite, removeFavorite } = useFavorites();
2026-04-26 13:46:30 +03:00
const [property, setProperty] = useState(null);
const [loading, setLoading] = useState(true);
const [currentImage, setCurrentImage] = useState(0);
2026-04-26 13:46:30 +03:00
const [showLoginDialog, setShowLoginDialog] = useState(false);
const [bookingDates, setBookingDates] = useState({ start: '', end: '' });
2026-05-25 21:27:39 +03:00
const [bookingLoading, setBookingLoading] = useState(false);
const [bookingError, setBookingError] = useState(null);
const [bookingSuccess, setBookingSuccess] = useState(false);
const [availableRanges, setAvailableRanges] = useState([]);
2026-05-25 21:27:39 +03:00
const [favLoading, setFavLoading] = useState(false);
const [avgRating, setAvgRating] = useState(null);
2026-04-12 20:44:04 +00:00
const [showRatingForm, setShowRatingForm] = useState(false);
2026-05-25 21:27:39 +03:00
const [showContact, setShowContact] = useState(false);
const [contactInfo, setContactInfo] = useState(null);
const [ownerData, setOwnerData] = useState(null);
useEffect(() => {
2026-05-25 21:27:39 +03:00
const id = params.id;
if (!id) return;
setLoading(true);
2026-05-25 21:27:39 +03:00
async function fetchProperty() {
try {
let data = null;
2026-05-25 21:27:39 +03:00
try { data = await getRentProperty(id); } catch {}
if (!data) { try { data = await getSalePropertyById(id) || await getSaleProperty(id); } catch {} }
if (!data) { try { data = await getSaleProperty(id); } catch {} }
if (data) {
2026-05-25 21:27:39 +03:00
const mapped = mapApiDetail(data);
setProperty(mapped);
if (mapped) fetchAvgRating(mapped.id);
}
} catch (err) {
2026-05-25 21:27:39 +03:00
console.error('[PropertyDetail] Failed:', err);
} finally {
setLoading(false);
}
}
2026-05-25 21:27:39 +03:00
fetchProperty();
}, [params.id]);
2026-05-25 21:27:39 +03:00
const fetchAvgRating = async (propId) => {
try {
const avg = await getPropertyAverageRating(propId);
setAvgRating(avg);
} catch {}
};
2026-05-25 21:27:39 +03:00
const fetchContactInfo = async () => {
if (!property) return;
try {
const info = await getOwnerContactInformation(property._raw?.propertyInformationId || property.id);
setContactInfo(info);
setShowContact(true);
} catch (err) {
toast.error('فشل تحميل معلومات الاتصال');
}
};
2026-05-25 21:27:39 +03:00
const handleFavorite = async () => {
if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; }
if (!property) return;
setFavLoading(true);
try {
if (isFavorite(property.id)) {
await removeFavorite(property.id);
} else {
2026-05-25 21:27:39 +03:00
await addFavorite(property.id);
}
2026-05-25 21:27:39 +03:00
} catch (err) {
toast.error('حدث خطأ');
} finally {
setFavLoading(false);
}
};
2026-05-25 21:27:39 +03:00
const handleBookNow = async () => {
if (!AuthService.isAuthenticated()) { setShowLoginDialog(true); return; }
if (!bookingDates.start || !bookingDates.end) {
2026-05-25 21:27:39 +03:00
setBookingError('يرجى تحديد تاريخ البداية والنهاية');
return;
}
2026-05-25 21:27:39 +03:00
setBookingLoading(true);
setBookingError(null);
try {
2026-05-25 21:27:39 +03:00
await bookReservation(property._raw?.propertyInformationId || property.id, bookingDates.start, bookingDates.end);
setBookingSuccess(true);
2026-04-26 13:46:30 +03:00
toast.success('تم إرسال طلب الحجز بنجاح');
} catch (err) {
2026-04-26 13:46:30 +03:00
setBookingError(err.message || 'فشل الحجز');
} finally {
setBookingLoading(false);
}
};
2026-05-25 21:27:39 +03:00
const handleRatingSuccess = () => {
setShowRatingForm(false);
if (property) fetchAvgRating(property.id);
};
if (loading) {
return (
2026-05-25 21:27:39 +03:00
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<Loader2 className="w-12 h-12 text-amber-500 animate-spin mx-auto mb-4" />
<p className="text-gray-600">جاري تحميل العقار...</p>
</div>
</div>
);
}
if (!property) {
return (
2026-05-25 21:27:39 +03:00
<div className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
<div className="text-center max-w-md">
<div className="w-24 h-24 bg-amber-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Home className="w-12 h-12 text-amber-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900 mb-2">العقار غير موجود</h2>
<p className="text-gray-600 mb-6">لم يتم العثور على العقار المطلوب</p>
<Link href="/properties" className="inline-flex items-center gap-2 bg-amber-500 text-white px-6 py-3 rounded-xl font-medium hover:bg-amber-600">
<ArrowLeft className="w-5 h-5" />
العودة إلى العقارات
</Link>
</div>
</div>
);
}
2026-05-25 21:27:39 +03:00
const isFav = isFavorite(property.id);
return (
2026-05-25 21:27:39 +03:00
<div className="min-h-screen bg-gray-50" dir="rtl">
<Toaster position="top-center" reverseOrder={false} />
<div className="container mx-auto px-4 py-6">
<motion.div initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }} className="mb-6">
<Link href="/properties" className="inline-flex items-center gap-2 text-gray-600 hover:text-amber-600 transition-colors">
<ArrowLeft className="w-5 h-5" />
العودة إلى العقارات
</Link>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 space-y-6">
{/* 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 aspect-video bg-gray-100">
{property.images.length > 0 ? (
<img src={property.images[currentImage]} alt={property.title} className="w-full h-full object-cover" />
) : (
<div className="w-full h-full flex items-center justify-center">
<ImageIcon className="w-16 h-16 text-gray-400" />
</div>
)}
{property.images.length > 1 && (
<>
2026-05-25 21:27:39 +03:00
<button onClick={() => setCurrentImage(prev => (prev - 1 + property.images.length) % property.images.length)}
className="absolute right-4 top-1/2 -translate-y-1/2 bg-black/50 text-white p-2 rounded-full hover:bg-black/70">
<ChevronRight className="w-5 h-5" />
</button>
<button onClick={() => setCurrentImage(prev => (prev + 1) % property.images.length)}
className="absolute left-4 top-1/2 -translate-y-1/2 bg-black/50 text-white p-2 rounded-full hover:bg-black/70">
<ChevronLeft className="w-5 h-5" />
</button>
</>
)}
2026-05-25 21:27:39 +03:00
<div className="absolute bottom-4 right-4">
<span className="bg-black/60 text-white px-3 py-1 rounded-full text-sm">{property.statusLabel}</span>
</div>
</div>
2026-05-25 21:27:39 +03:00
{property.images.length > 1 && (
<div className="flex gap-2 p-4 overflow-x-auto">
{property.images.map((img, idx) => (
<button key={idx} onClick={() => setCurrentImage(idx)}
className={`flex-shrink-0 w-20 h-16 rounded-lg overflow-hidden border-2 transition-colors ${idx === currentImage ? 'border-amber-500' : 'border-transparent opacity-60 hover:opacity-100'}`}>
<img src={img} alt="" className="w-full h-full object-cover" />
</button>
))}
</div>
2026-05-25 21:27:39 +03:00
)}
</motion.div>
2026-05-25 21:27:39 +03:00
{/* 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">
<div>
2026-05-25 21:27:39 +03:00
<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>
<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" />
<span>{property.location.address || property.location.city}</span>
</div>
</div>
2026-05-25 21:27:39 +03:00
<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>
2026-05-25 21:27:39 +03:00
</div>
2026-05-25 21:27:39 +03:00
{/* Price */}
<div className="bg-amber-50 rounded-xl p-4 mb-6">
{property.isRent ? (
<div className="flex gap-6">
{property.priceDisplay.monthly > 0 && (
<div>
<span className="text-2xl font-bold text-amber-600">{formatCurrency(property.priceDisplay.monthly)}</span>
<span className="text-gray-500 mr-1">ل.س / شهرياً</span>
</div>
)}
{property.priceDisplay.daily > 0 && (
<div>
<span className="text-2xl font-bold text-amber-600">{formatCurrency(property.priceDisplay.daily)}</span>
<span className="text-gray-500 mr-1">ل.س / يومياً</span>
</div>
)}
{property.deposit > 0 && (
<div className="text-sm text-gray-500 mt-1">تأمين: {formatCurrency(property.deposit)} ل.س</div>
)}
</div>
) : (
<div>
2026-05-25 21:27:39 +03:00
<span className="text-2xl font-bold text-blue-600">{formatCurrency(property.price)}</span>
<span className="text-gray-500 mr-1">ل.س</span>
<span className="text-sm text-gray-400 mr-2">للبيع</span>
</div>
2026-05-25 21:27:39 +03:00
)}
</div>
2026-05-25 21:27:39 +03:00
{/* Stats */}
<div className="flex gap-6 mb-6">
{property.bedrooms > 0 && (
<div className="text-center">
<Bed className="w-6 h-6 text-amber-500 mx-auto mb-1" />
<div className="font-bold">{property.bedrooms}</div>
<div className="text-xs text-gray-500">غرف نوم</div>
</div>
)}
{property.bathrooms > 0 && (
<div className="text-center">
<Bath className="w-6 h-6 text-amber-500 mx-auto mb-1" />
<div className="font-bold">{property.bathrooms}</div>
<div className="text-xs text-gray-500">حمامات</div>
</div>
2026-05-25 21:27:39 +03:00
)}
{property.area > 0 && (
<div className="text-center">
<Square className="w-6 h-6 text-amber-500 mx-auto mb-1" />
<div className="font-bold">{property.area}</div>
<div className="text-xs text-gray-500">م²</div>
</div>
)}
{avgRating !== null && avgRating > 0 && (
<div className="text-center">
<Star className="w-6 h-6 text-amber-500 mx-auto mb-1 fill-amber-500" />
<div className="font-bold">{avgRating.toFixed(1)}</div>
<div className="text-xs text-gray-500">التقييم</div>
</div>
)}
</div>
2026-05-25 21:27:39 +03:00
{/* 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>
)}
2026-05-25 21:27:39 +03:00
{/* Features */}
<div className="flex flex-wrap gap-2 mb-6">
{property.isSmokeAllow && <span className="px-3 py-1 bg-gray-100 rounded-full text-sm">يسمح بالتدخين</span>}
{property.isVisitorAllow && <span className="px-3 py-1 bg-gray-100 rounded-full text-sm">يسمح بالزوار</span>}
{property.specializedFor && <span className="px-3 py-1 bg-gray-100 rounded-full text-sm">متخصص</span>}
2026-04-26 13:46:30 +03:00
</div>
2026-05-25 21:27:39 +03:00
{/* Services */}
{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">
{Object.entries(property.services).map(([key, val]) => {
if (!val) return null;
const labels = { Electricity: 'كهرباء', Internet: 'إنترنت', Heating: 'تدفئة', Water: 'ماء', Pool: 'مسبح', PrivateGarden: 'حديقة خاصة', Parking: 'موقف سيارات', Security247: 'حراسة 24 س', CentralHeating: 'تدفئة مركزية', CentralAirConditioning: 'تكييف مركزي', EquippedKitchen: 'مطبخ مجهز', MaidsRoom: 'غرفة خادمة', Elevator: 'مصعد' };
return <span key={key} className="px-3 py-1 bg-green-50 text-green-700 rounded-full text-sm border border-green-200">{labels[key] || key}</span>;
})}
</div>
</div>
)}
{/* Terms */}
{Object.keys(property.terms).length > 0 && (
<div className="mb-6">
<h3 className="font-bold text-gray-900 mb-3">الشروط</h3>
<div className="flex flex-wrap gap-2">
{Object.entries(property.terms).map(([key, val]) => {
if (!val) return null;
const labels = { NoSmoking: 'ممنوع التدخين', NoAnimals: 'ممنوع الحيوانات', NoParties: 'ممنوع الحفلات' };
return <span key={key} className="px-3 py-1 bg-amber-50 text-amber-700 rounded-full text-sm border border-amber-200">{labels[key] || key}</span>;
})}
</div>
</div>
)}
</motion.div>
{/* Map */}
{property.location.lat && property.location.lng && (
<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 h-64">
<MapContainer center={[property.location.lat, property.location.lng]} zoom={14} className="h-full w-full" scrollWheelZoom={false}>
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<Marker position={[property.location.lat, property.location.lng]}>
<Popup>{property.title}</Popup>
</Marker>
</MapContainer>
</motion.div>
)}
{/* Ratings Section */}
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }}>
<PropertyRatingList propertyId={property._raw?.propertyInformationId || property.id} />
</motion.div>
{AuthService.isAuthenticated() && !showRatingForm && (
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }}
className="bg-amber-50 border-2 border-dashed border-amber-200 rounded-2xl p-6 text-center cursor-pointer hover:bg-amber-100 transition-colors"
onClick={() => setShowRatingForm(true)}>
<Star className="w-10 h-10 text-amber-500 mx-auto mb-2" />
<h3 className="font-bold text-amber-800 text-lg mb-1">قيّم هذا العقار</h3>
<p className="text-amber-600 text-sm">شارك تجربتك مع المستأجرين الآخرين</p>
</motion.div>
)}
2026-04-12 20:44:04 +00:00
2026-05-25 21:27:39 +03:00
{showRatingForm && (
2026-04-26 13:46:30 +03:00
<PropertyRatingForm
2026-05-25 21:27:39 +03:00
reservationId={property._raw?.propertyInformationId || property.id}
onSuccess={handleRatingSuccess}
2026-04-26 13:46:30 +03:00
onCancel={() => setShowRatingForm(false)}
2026-04-12 20:44:04 +00:00
/>
2026-04-26 13:46:30 +03:00
)}
</div>
2026-05-25 21:27:39 +03:00
{/* Sidebar */}
<div className="space-y-6">
2026-05-25 21:27:39 +03:00
{/* 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">
<h3 className="text-lg font-bold text-gray-900 mb-4">حجز العقار</h3>
{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>
<h4 className="font-bold text-green-700 mb-1">تم إرسال طلب الحجز</h4>
<p className="text-sm text-gray-500">سيتم مراجعة طلبك من قبل المالك</p>
</div>
2026-05-25 21:27:39 +03:00
) : (
<>
<div className="space-y-3 mb-4">
<div>
<label className="block text-sm 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" />
</div>
<div>
<label className="block text-sm 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" />
</div>
</div>
2026-05-25 21:27:39 +03:00
{bookingError && (
<div className="bg-red-50 text-red-600 p-3 rounded-xl text-sm mb-4">{bookingError}</div>
)}
2026-05-25 21:27:39 +03:00
<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" />}
{bookingLoading ? 'جاري الحجز...' : 'حجز الآن'}
</button>
</>
)}
</motion.div>
2026-05-25 21:27:39 +03:00
)}
2026-05-25 21:27:39 +03:00
{/* 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">
<h3 className="text-lg font-bold text-gray-900 mb-4">معلومات المالك</h3>
2026-05-25 21:27:39 +03:00
{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" />
<span className="font-medium text-gray-900" dir="ltr">{contactInfo.phone || contactInfo.phoneNumber || '—'}</span>
</div>
2026-05-25 21:27:39 +03:00
{contactInfo.whatsAppNumber && (
<div className="flex items-center gap-3 p-3 bg-gray-50 rounded-xl">
<MessageCircle className="w-5 h-5 text-green-600" />
<span className="font-medium text-gray-900" dir="ltr">{contactInfo.whatsAppNumber}</span>
</div>
2026-05-25 21:27:39 +03:00
)}
</div>
2026-05-25 21:27:39 +03:00
) : (
<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" />
عرض معلومات الاتصال
</button>
2026-05-25 21:27:39 +03:00
)}
</motion.div>
</div>
</div>
</div>
2026-05-25 21:27:39 +03:00
{/* Login Dialog */}
{showLoginDialog && (
2026-05-25 21:27:39 +03:00
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowLoginDialog(false)}>
<div className="bg-white rounded-2xl p-6 max-w-sm text-center mx-4" onClick={e => e.stopPropagation()}>
<div className="w-16 h-16 bg-amber-100 rounded-full flex items-center justify-center mx-auto mb-4">
<LogIn className="w-8 h-8 text-amber-600" />
</div>
2026-05-25 21:27:39 +03:00
<h3 className="text-xl font-bold mb-2">تسجيل الدخول مطلوب</h3>
<p className="text-gray-500 mb-4">للحجز أو إضافة المفضلة، سجل دخولك.</p>
<Link href="/login" className="block w-full bg-amber-500 text-white py-3 rounded-xl font-medium mb-2 hover:bg-amber-600">تسجيل الدخول</Link>
<Link href="/auth/choose-role" className="block w-full bg-gray-100 py-3 rounded-xl font-medium hover:bg-gray-200">إنشاء حساب</Link>
<button onClick={() => setShowLoginDialog(false)} className="mt-3 text-gray-400 hover:text-gray-600">إلغاء</button>
2026-04-26 13:46:30 +03:00
</div>
</div>
)}
</div>
);
2026-05-25 21:27:39 +03:00
}