"use client"; import { useState, useEffect, useMemo } from "react"; import { motion } from "framer-motion"; import { useRouter } from "next/navigation"; import { useTranslation } from "react-i18next"; import { Calendar, User, Mail, Phone, CheckCircle, XCircle, Clock, MapPin, Bed, Bath, Square, CalendarDays, ChevronLeft, ChevronRight, Eye, Loader2, Search } from "lucide-react"; import toast, { Toaster } from "react-hot-toast"; import { getMyRentListings, getOwnerReservationRequests } from "@/app/utils/api"; import useAuth from "@/app/hooks/useAuth"; 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 || !Array.isArray(property.bookings)) return false; return property.bookings.some((booking) => { const start = new Date(booking.startDate); const end = new Date(booking.endDate); return date >= start && date <= 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 }) => { const { t } = useTranslation(); const formatCurrency = (amount) => { return (amount || 0).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.dailyRent)}
{t("dailyRent")}
{booking.propertyDetails?.bedrooms} {t("rooms")}
{booking.propertyDetails?.bathrooms} {t("baths")}
{booking.propertyDetails?.area} {t("sqm")}
{booking.tenantName && (

{booking.tenantName}

{booking.tenantPhone && ( {booking.tenantPhone} )} {booking.tenantEmail && ( {booking.tenantEmail} )}
)}
{t("monthlyRent")}
{formatCurrency(booking.monthlyRent)}
{t("deposit")}
{formatCurrency(booking.deposit)}
); }; const BookingDetailsModal = ({ booking, isOpen, onClose }) => { const { t } = useTranslation(); if (!isOpen || !booking) return null; const formatCurrency = (amount) => { return (amount || 0).toLocaleString() + " " + t("syp"); }; return ( e.stopPropagation()} >

{t("bookingDetails")}

# {booking.id}

{booking.images && booking.images.length > 0 && (
{booking.images.map((img, idx) => ( {`property-${idx}`} ))}
)}

{t("propertyInfo")}

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

{t("description")}: {booking.parsedDetails?.description || "-"}

{booking.propertyDetails?.bedrooms} {t("rooms")} {booking.propertyDetails?.bathrooms} {t("bathrooms")} {booking.propertyDetails?.salons} {t("salons")} {booking.propertyDetails?.area} {t("sqm")}

{t("financialInfo")}

{t("dailyRent")} {formatCurrency(booking.dailyRent)}
{t("monthlyRent")} {formatCurrency(booking.monthlyRent)}
{t("deposit")} {formatCurrency(booking.deposit)}
{booking.parsedDetails?.services && (

{t("services")}

{booking.parsedDetails.services.map((srv, i) => ( {srv} ))}
)}
); }; export default function OwnerBookingsPage() { const { t, i18n } = useTranslation(); const router = useRouter(); const { name, isOwner } = useAuth(); const [bookings, setBookings] = 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); const isRtl = i18n.language === "ar"; useEffect(() => { if (isOwner) { fetchData(); } else { router.push("/auth/choose-role"); } }, [isOwner, router]); const fetchData = async () => { try { const response = await getOwnerReservationRequests(); let rawData = response; if (response && response.data) { rawData = response.data; } // تحويل البيانات إلى مصفوفة وتصفية العناصر الفارغة (null أو undefined) const rawList = Array.isArray(rawData) ? rawData : rawData ? [rawData] : []; const list = rawList.filter(Boolean); const mappedBookings = list.map((item) => { let parsedDetails = {}; try { if (item?.propertyInformation?.detailsJSON) { parsedDetails = JSON.parse(item.propertyInformation.detailsJSON); } } catch (e) { console.error("Error parsing detailsJSON", e); } const statusMap = { 0: "pending", 1: "confirmed", 2: "completed", 3: "cancelled", }; const statusKey = statusMap[item?.propertyInformation?.status] || "pending"; return { id: item?.id, dailyRent: item?.dailyRent, monthlyRent: item?.monthlyRent, deposit: item?.deposit, createdAt: item?.createdAt, startDate: item?.createdAt?.split("T")[0], status: statusKey, propertyTitle: parsedDetails.description || `${t("property")} #${item?.id}`, location: item?.propertyInformation?.address || "", images: item?.propertyInformation?.images || [], propertyDetails: { bedrooms: item?.propertyInformation?.numberOfBedRooms || 0, bathrooms: item?.propertyInformation?.numberOfBathRooms || 0, salons: item?.propertyInformation?.numberOfSalons || 0, area: item?.propertyInformation?.space || 0, }, parsedDetails, tenantName: item?.tenantName || null, tenantPhone: item?.tenantPhone || null, tenantEmail: item?.tenantEmail || null, }; }); setBookings(mappedBookings); } catch (error) { console.error("Error loading listings:", error); setBookings([]); } finally { setIsLoading(false); } }; const filteredBookings = useMemo(() => { return bookings.filter((booking) => { const matchesStatus = filterStatus === "all" || booking.status === filterStatus; const matchesSearch = !searchTerm || booking.tenantName?.toLowerCase().includes(searchTerm.toLowerCase()) || booking.propertyTitle?.toLowerCase().includes(searchTerm.toLowerCase()) || booking.location?.toLowerCase().includes(searchTerm.toLowerCase()) || String(booking.id).includes(searchTerm); const bookingDate = new Date(booking.startDate || booking.createdAt); const matchesStart = !dateRange.start || bookingDate >= new Date(dateRange.start); const matchesEnd = !dateRange.end || bookingDate <= new Date(dateRange.end); return matchesStatus && matchesSearch && matchesStart && matchesEnd; }); }, [bookings, filterStatus, searchTerm, dateRange]); const statusCounts = useMemo(() => { return { 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, }; }, [bookings]); if (isLoading) { return (

{t("loading")}

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

{t("myBookings")}

{t("welcomeBookings", { name: name, count: bookings.length })}

{[ { id: "all", label: "allBookings", count: statusCounts.all, color: "text-gray-900", active: "border-gray-900 bg-gray-50" }, { id: "pending", label: "pending", count: statusCounts.pending, color: "text-yellow-600", active: "border-yellow-500 bg-yellow-50" }, { id: "confirmed", label: "confirmed", count: statusCounts.confirmed, color: "text-green-600", active: "border-green-500 bg-green-50" }, { id: "completed", label: "completed", count: statusCounts.completed, color: "text-gray-600", active: "border-gray-500 bg-gray-50" }, { id: "cancelled", label: "cancelled", count: statusCounts.cancelled, color: "text-red-600", active: "border-red-500 bg-red-50" }, ].map((item, index) => ( setFilterStatus(item.id)} >
{item.count}
{t(item.label)}
))}
setSearchTerm(e.target.value)} className={`w-full py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${isRtl ? "pr-10 pl-4" : "pl-10 pr-4"}`} />
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" /> 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" /> {(dateRange.start || dateRange.end) && ( )}
{showCalendar && ( )} {filteredBookings.length === 0 ? (

{t("noBookings")}

{filterStatus !== "all" || searchTerm || dateRange.start || dateRange.end ? t("noBookingsInCategory") : t("noBookingsReceived")}

{(filterStatus !== "all" || searchTerm || dateRange.start || dateRange.end) && ( )}
) : (
{filteredBookings.map((booking) => ( ))}
)}
); }