'use client'; import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { useTranslation } from 'react-i18next'; import { Calendar, Home, User, Mail, Phone, DollarSign, CheckCircle, XCircle, Clock, MapPin, Bed, Bath, Square, CalendarDays, ChevronLeft, ChevronRight, Eye, MessageCircle, ArrowLeft, Loader2, Filter, Search, Download, TrendingUp, Users, Building } from 'lucide-react'; import toast, { Toaster } from 'react-hot-toast'; import AuthService from '../../services/AuthService'; import Image from 'next/image'; const OwnerBookingCalendar = ({ property, onDateSelect, selectedDates }) => { const { t } = useTranslation(); const [currentMonth, setCurrentMonth] = useState(new Date()); const [hoverDate, setHoverDate] = useState(null); const daysInMonth = new Date( currentMonth.getFullYear(), currentMonth.getMonth() + 1, 0 ).getDate(); const firstDayOfMonth = new Date( currentMonth.getFullYear(), currentMonth.getMonth(), 1 ).getDay(); const monthNames = [ t('january'), t('february'), t('march'), t('april'), t('may'), t('june'), t('july'), t('august'), t('september'), t('october'), t('november'), t('december') ]; const dayNames = [ t('dayFull.sunday'), t('dayFull.monday'), t('dayFull.tuesday'), t('dayFull.wednesday'), t('dayFull.thursday'), t('dayFull.friday'), t('dayFull.saturday') ]; const isDateBooked = (date) => { if (!property?.bookings) return false; const dateStr = date.toISOString().split('T')[0]; return property.bookings.some(booking => { const start = new Date(booking.startDate); const end = new Date(booking.endDate); const current = new Date(date); return current >= start && current <= end; }); }; const isDateSelected = (date) => { if (!selectedDates) return false; const dateStr = date.toISOString().split('T')[0]; return dateStr === selectedDates.start || dateStr === selectedDates.end; }; const isInRange = (date) => { if (!selectedDates?.start || !selectedDates?.end) return false; const dateStr = date.toISOString().split('T')[0]; return dateStr > selectedDates.start && dateStr < selectedDates.end; }; const handleDateClick = (date) => { if (isDateBooked(date)) return; onDateSelect?.(date); }; const renderDays = () => { const days = []; const totalDays = daysInMonth + firstDayOfMonth; for (let i = 0; i < totalDays; i++) { if (i < firstDayOfMonth) { days.push(
); } else { const dayNumber = i - firstDayOfMonth + 1; const date = new Date( currentMonth.getFullYear(), currentMonth.getMonth(), dayNumber ); const isBooked = isDateBooked(date); const isSelected = isDateSelected(date); const inRange = isInRange(date); const isToday = date.toDateString() === new Date().toDateString(); days.push( ); } } return days; }; return (

{monthNames[currentMonth.getMonth()]} {currentMonth.getFullYear()}

{dayNames.map((name, i) => (
{name}
))}
{renderDays()}
{t('booked')}
{t('selected')}
{t('inRange')}
{t('today')}
); }; const BookingCard = ({ booking, onViewDetails, onContact }) => { const { t } = useTranslation(); const formatCurrency = (amount) => { return amount?.toLocaleString() + ' ' + t('syp'); }; const getStatusBadge = (status) => { const statusConfig = { pending: { label: t('pending'), color: 'bg-yellow-100 text-yellow-800', icon: Clock }, confirmed: { label: t('confirmed'), color: 'bg-green-100 text-green-800', icon: CheckCircle }, cancelled: { label: t('cancelled'), color: 'bg-red-100 text-red-800', icon: XCircle }, completed: { label: t('completed'), color: 'bg-gray-100 text-gray-800', icon: CheckCircle } }; const config = statusConfig[status] || statusConfig.pending; const Icon = config.icon; return ( {config.label} ); }; return (

{booking.propertyTitle}

{getStatusBadge(booking.status)}
{booking.location}
{formatCurrency(booking.totalAmount)}
{t('totalAmount')}

{booking.tenantName}

{booking.tenantPhone} {booking.tenantEmail}
{t('from')}
{booking.startDate}
{t('to')}
{booking.endDate}
{t('duration')}
{booking.days} {t('days')}
); }; const BookingDetailsModal = ({ booking, isOpen, onClose }) => { const { t } = useTranslation(); if (!isOpen || !booking) return null; const formatCurrency = (amount) => { return amount?.toLocaleString() + ' ' + t('syp'); }; return ( e.stopPropagation()} >

{t('bookingDetails')}

{t('bookingId', { id: booking.id })}

{t('propertyInfo')}

{t('property')}: {booking.propertyTitle}

{t('location')}: {booking.location}

{booking.propertyDetails && (
{booking.propertyDetails.bedrooms} {t('rooms')} {booking.propertyDetails.bathrooms} {t('bathrooms')} {booking.propertyDetails.area} {t('sqm')}
)}

{t('tenantInfo')}

{t('name')} {booking.tenantName}

{t('email')} {booking.tenantEmail}

{t('phone')} {booking.tenantPhone}

{t('bookingDetails')}

{t('startDate')}

{booking.startDate}

{t('endDate')}

{booking.endDate}

{t('durationDays', { days: booking.days })}

{booking.days} {t('days')}

{t('bookingStatus')}

{booking.status === 'pending' ? t('pending') : booking.status === 'confirmed' ? t('confirmed') : booking.status === 'cancelled' ? t('cancelled') : t('completed')}

{t('financialInfo')}

{t('dailyPrice')} {formatCurrency(booking.dailyPrice)}
{t('durationDays', { days: booking.days })} {formatCurrency(booking.dailyPrice * booking.days)}
{t('securityDeposit')} {formatCurrency(booking.securityDeposit || 0)}
{t('total')} {formatCurrency(booking.totalAmount)}
{booking.notes && (

{t('notes')}

{booking.notes}

)}
); }; export default function OwnerBookingsPage() { const { t, i18n } = useTranslation(); const router = useRouter(); const [user, setUser] = useState(null); const [bookings, setBookings] = useState([]); const [filteredBookings, setFilteredBookings] = useState([]); const [isLoading, setIsLoading] = useState(true); const [selectedBooking, setSelectedBooking] = useState(null); const [filterStatus, setFilterStatus] = useState('all'); const [searchTerm, setSearchTerm] = useState(''); const [dateRange, setDateRange] = useState({ start: '', end: '' }); const [showCalendar, setShowCalendar] = useState(false); useEffect(() => { const authUser = AuthService.getUser(); if (authUser && AuthService.isOwner()) { setUser({ name: authUser.name || authUser.email, email: authUser.email, role: 'owner', }); loadBookings(); } else { router.push('/auth/choose-role'); } }, [router]); const loadBookings = () => { const storedBookings = localStorage.getItem('ownerBookings'); if (storedBookings) { setBookings(JSON.parse(storedBookings)); setFilteredBookings(JSON.parse(storedBookings)); } else { const mockBookings = [ { id: 'BK001', propertyId: 1, propertyTitle: t('ownerBookings.mockB1Title'), location: t('ownerBookings.mockB1Location'), propertyDetails: { bedrooms: 5, bathrooms: 4, area: 450 }, tenantName: t('ownerBookings.mockB1Tenant'), tenantEmail: 'ahmed@example.com', tenantPhone: '0933111222', startDate: '2024-03-10', endDate: '2024-03-15', days: 5, dailyPrice: 500000, totalAmount: 2500000, securityDeposit: 500000, status: 'confirmed', createdAt: '2024-02-25', notes: t('ownerBookings.mockB1Notes') }, { id: 'BK002', propertyId: 2, propertyTitle: t('ownerBookings.mockB2Title'), location: t('ownerBookings.mockB2Location'), propertyDetails: { bedrooms: 3, bathrooms: 2, area: 180 }, tenantName: t('ownerBookings.mockB2Tenant'), tenantEmail: 'sara@example.com', tenantPhone: '0945123789', startDate: '2024-03-05', endDate: '2024-03-08', days: 3, dailyPrice: 250000, totalAmount: 750000, securityDeposit: 250000, status: 'pending', createdAt: '2024-02-24', notes: t('ownerBookings.mockB2Notes') }, { id: 'BK003', propertyId: 3, propertyTitle: t('ownerBookings.mockB3Title'), location: t('ownerBookings.mockB3Location'), propertyDetails: { bedrooms: 4, bathrooms: 3, area: 300 }, tenantName: t('ownerBookings.mockB3Tenant'), tenantEmail: 'mohammed@example.com', tenantPhone: '0956123456', startDate: '2024-02-20', endDate: '2024-03-20', days: 30, dailyPrice: 350000, totalAmount: 10500000, securityDeposit: 500000, status: 'completed', createdAt: '2024-02-15', notes: t('ownerBookings.mockB3Notes') } ]; setBookings(mockBookings); setFilteredBookings(mockBookings); localStorage.setItem('ownerBookings', JSON.stringify(mockBookings)); } setIsLoading(false); }; const handleViewDetails = (booking) => { setSelectedBooking(booking); }; const handleContact = (booking) => { toast.success(t('openingChat', { name: booking.tenantName }), { icon: '💬', style: { background: '#dcfce7', color: '#166534' } }); }; const handleStatusChange = (bookingId, newStatus) => { const updatedBookings = bookings.map(b => b.id === bookingId ? { ...b, status: newStatus } : b ); setBookings(updatedBookings); setFilteredBookings(updatedBookings); localStorage.setItem('ownerBookings', JSON.stringify(updatedBookings)); toast.success(t('statusUpdated')); }; const statusCounts = { all: bookings.length, pending: bookings.filter(b => b.status === 'pending').length, confirmed: bookings.filter(b => b.status === 'confirmed').length, completed: bookings.filter(b => b.status === 'completed').length, cancelled: bookings.filter(b => b.status === 'cancelled').length }; if (isLoading) { return (

{t('loading')}

); } return (
setSelectedBooking(null)} />

{t('myBookings')}

{t('welcomeBookings', { name: user?.name, count: bookings.length })}

setFilterStatus('all')} >
{statusCounts.all}
{t('allBookings')}
setFilterStatus('pending')} >
{statusCounts.pending}
{t('pending')}
setFilterStatus('confirmed')} >
{statusCounts.confirmed}
{t('confirmed')}
setFilterStatus('completed')} >
{statusCounts.completed}
{t('completed')}
setFilterStatus('cancelled')} >
{statusCounts.cancelled}
{t('cancelled')}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500" />
setDateRange({...dateRange, start: e.target.value})} className="px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500" placeholder={t('filterDateFrom')} /> setDateRange({...dateRange, end: e.target.value})} className="px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500" placeholder={t('filterDateTo')} /> {(dateRange.start || dateRange.end) && ( )}
{showCalendar && ( )} {filteredBookings.length === 0 ? (

{t('noBookings')}

{filterStatus !== 'all' ? t('noBookingsInCategory') : t('noBookingsReceived')}

{filterStatus !== 'all' && ( )}
) : (
{filteredBookings.map((booking) => ( ))}
)}
); }