diff --git a/app/owner/reservations/page.js b/app/owner/reservations/page.js
new file mode 100644
index 0000000..d879743
--- /dev/null
+++ b/app/owner/reservations/page.js
@@ -0,0 +1,415 @@
+'use client';
+
+import { useState, useEffect, useCallback } from 'react';
+import { motion } from 'framer-motion';
+import { useRouter } from 'next/navigation';
+import {
+ Calendar,
+ Clock,
+ CheckCircle,
+ XCircle,
+ Eye,
+ Loader2,
+ Search,
+ MapPin,
+ DollarSign,
+ Home,
+ ArrowLeft,
+ User,
+ RefreshCw,
+ Mail,
+ Phone
+} from 'lucide-react';
+import toast, { Toaster } from 'react-hot-toast';
+import AuthService from '../../services/AuthService';
+
+const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api';
+
+const statusConfig = {
+ pending: { label: 'قيد الانتظار', color: 'bg-yellow-100 text-yellow-800', icon: Clock },
+ ownerConfirmed: { label: 'مؤكد', color: 'bg-green-100 text-green-800', icon: CheckCircle },
+ depositPaid: { label: 'تم دفع السلفة', color: 'bg-indigo-100 text-indigo-800', icon: DollarSign },
+ depositConfirmed: { label: 'مؤكد نهائياً', color: 'bg-green-100 text-green-800', icon: CheckCircle },
+ rejected: { label: 'مرفوض', color: 'bg-red-100 text-red-800', icon: XCircle },
+ cancelled: { label: 'ملغي', color: 'bg-gray-100 text-gray-800', icon: XCircle },
+ completed: { label: 'منتهي', color: 'bg-blue-100 text-blue-800', icon: CheckCircle },
+};
+
+function StatusBadge({ status }) {
+ const config = statusConfig[status] || { label: status, color: 'bg-gray-100 text-gray-700', icon: Clock };
+ const Icon = config.icon;
+ return (
+
+
+ {config.label}
+
+ );
+}
+
+function OwnerReservationCard({ reservation, onViewDetails, onConfirm, onReject }) {
+ const property = reservation.property || reservation.propertyInformation;
+ const user = reservation.user;
+ const isPending = reservation.status === 'pending';
+
+ return (
+
+
+
+
+
+ {property && (
+
+
+ {property.address || 'عقار'}
+
+ )}
+
+
+
+ {reservation.totalPrice?.toLocaleString() || '—'}
+
+
السعر الإجمالي
+
+
+
+ {user && (
+
+
+
+
+
+
+
{user.name || user.email || 'مستخدم'}
+
+ {user.phoneNumber && <>
{user.phoneNumber}>}
+ {user.email && <>
{user.email}>}
+
+
+
+
+ )}
+
+
+
+
+
من
+
+ {new Date(reservation.startDate).toLocaleDateString('ar')}
+
+
+
+
+
إلى
+
+ {new Date(reservation.endDate).toLocaleDateString('ar')}
+
+
+
+
+
+
+
+ {isPending && (
+ <>
+
+
+ >
+ )}
+
+
+
+ );
+}
+
+function DetailsModal({ reservation, isOpen, onClose }) {
+ if (!isOpen || !reservation) return null;
+ const property = reservation.property || reservation.propertyInformation;
+ const user = reservation.user;
+
+ return (
+
+ e.stopPropagation()}
+ >
+
+
+
طلب حجز #{reservation.id}
+
+
+
+
+
+ {user && (
+
+
+ معلومات المستأجر
+
+
الاسم: {user.name || '—'}
+
البريد: {user.email || '—'}
+ {user.phoneNumber &&
الهاتف: {user.phoneNumber}
}
+
+ )}
+
+ {property && (
+
+
+ معلومات العقار
+
+
العنوان: {property.address || '—'}
+ {property.numberOfBedRooms && (
+
+ {property.numberOfBedRooms} غرف
+ {property.numberOfBathRooms} حمامات
+
+ )}
+
+ )}
+
+
+
+ تفاصيل الحجز
+
+
+
+
تاريخ البداية
+
{new Date(reservation.startDate).toLocaleDateString('ar')}
+
+
+
تاريخ النهاية
+
{new Date(reservation.endDate).toLocaleDateString('ar')}
+
+
+
+
تاريخ الإنشاء
+
{new Date(reservation.createdAt).toLocaleDateString('ar')}
+
+
+
+
+
+
+ المعلومات المالية
+
+
+ الإجمالي
+ {reservation.totalPrice?.toLocaleString() || '—'}
+
+
+
+
+
+ );
+}
+
+export default function OwnerReservationRequestsPage() {
+ const router = useRouter();
+ const [reservations, setReservations] = useState([]);
+ const [filtered, setFiltered] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [selected, setSelected] = useState(null);
+ const [filterStatus, setFilterStatus] = useState('all');
+ const [searchTerm, setSearchTerm] = useState('');
+
+ useEffect(() => {
+ const user = AuthService.getUser();
+ if (!user || !AuthService.isOwner()) {
+ router.push('/auth/choose-role');
+ return;
+ }
+ loadReservations();
+ }, [router]);
+
+ const loadReservations = async () => {
+ try {
+ const token = AuthService.getToken();
+ const res = await fetch(`${API_BASE}/Reservations/GetOwnerReservationRequests`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
+ const json = await res.json();
+
+ const list = json.data || json || [];
+ setReservations(Array.isArray(list) ? list : []);
+ setFiltered(Array.isArray(list) ? list : []);
+ } catch (err) {
+ console.error('Failed to load owner reservations:', err);
+ toast.error('فشل تحميل طلبات الحجز');
+ }
+ setLoading(false);
+ };
+
+ useEffect(() => {
+ let result = reservations;
+ if (filterStatus !== 'all') result = result.filter(r => r.status === filterStatus);
+ if (searchTerm) {
+ const q = searchTerm.toLowerCase();
+ result = result.filter(r => {
+ const addr = (r.property?.address || '').toLowerCase();
+ const userName = ((r.user?.name) || (r.user?.email) || '').toLowerCase();
+ const sid = String(r.id).toLowerCase();
+ return addr.includes(q) || userName.includes(q) || sid.includes(q);
+ });
+ }
+ setFiltered(result);
+ }, [reservations, filterStatus, searchTerm]);
+
+ const handleConfirm = async (reservation) => {
+ try {
+ const token = AuthService.getToken();
+ const id = typeof reservation.id === 'number' ? reservation.id : parseInt(reservation.id);
+ const res = await fetch(`${API_BASE}/Reservations/owner-confirm/${id}`, {
+ method: 'PUT',
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
+
+ toast.success('تم قبول الحجز بنجاح');
+ await loadReservations();
+ } catch (err) {
+ console.error('Failed to confirm:', err);
+ toast.error('فشل قبول الحجز');
+ }
+ };
+
+ const handleReject = async (reservation) => {
+ if (!confirm('هل أنت متأكد من رفض هذا الحجز؟')) return;
+ try {
+ const token = AuthService.getToken();
+ const id = typeof reservation.id === 'number' ? reservation.id : parseInt(reservation.id);
+ const res = await fetch(`${API_BASE}/Reservations/reject/${id}`, {
+ method: 'PUT',
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
+
+ toast.success('تم رفض الحجز');
+ await loadReservations();
+ } catch (err) {
+ console.error('Failed to reject:', err);
+ toast.error('فشل رفض الحجز');
+ }
+ };
+
+ const statuses = ['all', ...new Set(reservations.map(r => r.status))];
+ const statusCounts = {
+ all: reservations.length,
+ ...Object.fromEntries(
+ [...new Set(reservations.map(r => r.status))].map(s => [s, reservations.filter(r => r.status === s).length])
+ ),
+ };
+
+ if (loading) return
;
+
+ return (
+
+
+
setSelected(null)} />
+
+
+
+
+
+
+
طلبات الحجز
+
لديك {reservations.length} طلب
+
+
+
+
+
+
+ {Object.entries(statusCounts).map(([status, count]) => (
+
setFilterStatus(status)}
+ >
+ {count}
+ {status === 'all' ? 'الكل' : (statusConfig[status]?.label || status)}
+
+ ))}
+
+
+
+
+ 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"
+ />
+
+
+ {filtered.length === 0 ? (
+
+
+
لا توجد طلبات
+
لم يتم استلام أي طلبات حجز حتى الآن
+
+ ) : (
+
+ {filtered.map((r) => (
+
+ ))}
+
+ )}
+
+
+ );
+}
diff --git a/app/reservations/page.js b/app/reservations/page.js
new file mode 100644
index 0000000..07d996a
--- /dev/null
+++ b/app/reservations/page.js
@@ -0,0 +1,321 @@
+'use client';
+
+import { useState, useEffect, useCallback } from 'react';
+import { motion } from 'framer-motion';
+import { useRouter } from 'next/navigation';
+import {
+ Calendar,
+ Clock,
+ CheckCircle,
+ XCircle,
+ Eye,
+ Loader2,
+ Search,
+ MapPin,
+ DollarSign,
+ Home,
+ ArrowLeft,
+ Building2
+} from 'lucide-react';
+import toast, { Toaster } from 'react-hot-toast';
+import AuthService from '../services/AuthService';
+
+const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api';
+
+const statusConfig = {
+ pending: { label: 'قيد الانتظار', color: 'bg-yellow-100 text-yellow-800', icon: Clock },
+ ownerConfirmed: { label: 'مؤكد من المالك', color: 'bg-blue-100 text-blue-800', icon: CheckCircle },
+ depositPaid: { label: 'تم دفع السلفة', color: 'bg-indigo-100 text-indigo-800', icon: DollarSign },
+ depositConfirmed: { label: 'مؤكد', color: 'bg-green-100 text-green-800', icon: CheckCircle },
+ rejected: { label: 'مرفوض', color: 'bg-red-100 text-red-800', icon: XCircle },
+ cancelled: { label: 'ملغي', color: 'bg-gray-100 text-gray-800', icon: XCircle },
+ completed: { label: 'منتهي', color: 'bg-green-100 text-green-800', icon: CheckCircle },
+};
+
+function StatusBadge({ status }) {
+ const config = statusConfig[status] || { label: status, color: 'bg-gray-100 text-gray-700', icon: Clock };
+ const Icon = config.icon;
+ return (
+
+
+ {config.label}
+
+ );
+}
+
+function ReservationCard({ reservation, onViewDetails }) {
+ const property = reservation.property || reservation.propertyInformation;
+
+ return (
+
+
+
+
+
+
+
+ {property && (
+
+
+ {property.address || 'عقار'}
+
+ )}
+
+
+
+ {reservation.totalPrice?.toLocaleString() || '—'}
+
+
السعر الإجمالي
+
+
+
+ {property?.images?.length > 0 && (
+
+

+
+ )}
+
+
+
+
+
من
+
+ {new Date(reservation.startDate).toLocaleDateString('ar')}
+
+
+
+
+
إلى
+
+ {new Date(reservation.endDate).toLocaleDateString('ar')}
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function DetailsModal({ reservation, isOpen, onClose }) {
+ if (!isOpen || !reservation) return null;
+ const property = reservation.property || reservation.propertyInformation;
+
+ return (
+
+ e.stopPropagation()}
+ >
+
+
+
تفاصيل الحجز
+
+
+
رقم الحجز: #{reservation.id}
+
+
+
+ {property && (
+
+
+ معلومات العقار
+
+
العنوان: {property.address || '—'}
+ {property.numberOfBedRooms && (
+
+ {property.numberOfBedRooms} غرف
+ {property.numberOfBathRooms} حمامات
+
+ )}
+
+ )}
+
+
+
+ تفاصيل الحجز
+
+
+
+
تاريخ البداية
+
{new Date(reservation.startDate).toLocaleDateString('ar')}
+
+
+
تاريخ النهاية
+
{new Date(reservation.endDate).toLocaleDateString('ar')}
+
+
+
+
تاريخ الإنشاء
+
{new Date(reservation.createdAt).toLocaleDateString('ar')}
+
+
+
+
+
+
+ المعلومات المالية
+
+
+ الإجمالي
+ {reservation.totalPrice?.toLocaleString() || '—'}
+
+
+
+
+
+ );
+}
+
+export default function UserReservationsPage() {
+ const router = useRouter();
+ const [reservations, setReservations] = useState([]);
+ const [filtered, setFiltered] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [selected, setSelected] = useState(null);
+ const [filterStatus, setFilterStatus] = useState('all');
+ const [searchTerm, setSearchTerm] = useState('');
+
+ useEffect(() => {
+ const user = AuthService.getUser();
+ if (!user) {
+ router.push('/login');
+ return;
+ }
+ loadReservations();
+ }, [router]);
+
+ const loadReservations = async () => {
+ try {
+ const token = AuthService.getToken();
+ const res = await fetch(`${API_BASE}/Reservations/GetUserReservations`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
+ const json = await res.json();
+
+ const list = json.data || json || [];
+ setReservations(Array.isArray(list) ? list : []);
+ setFiltered(Array.isArray(list) ? list : []);
+ } catch (err) {
+ console.error('Failed to load reservations:', err);
+ toast.error('فشل تحميل الحجوزات');
+ setReservations([]);
+ setFiltered([]);
+ }
+ setLoading(false);
+ };
+
+ useEffect(() => {
+ let result = reservations;
+ if (filterStatus !== 'all') result = result.filter(r => r.status === filterStatus);
+ if (searchTerm) {
+ const q = searchTerm.toLowerCase();
+ result = result.filter(r => {
+ const addr = (r.property?.address || '').toLowerCase();
+ const sid = String(r.id).toLowerCase();
+ return addr.includes(q) || sid.includes(q);
+ });
+ }
+ setFiltered(result);
+ }, [reservations, filterStatus, searchTerm]);
+
+ const statuses = ['all', ...new Set(reservations.map(r => r.status))];
+ const statusCounts = {
+ all: reservations.length,
+ ...Object.fromEntries(
+ [...new Set(reservations.map(r => r.status))].map(s => [s, reservations.filter(r => r.status === s).length])
+ ),
+ };
+
+ if (loading) return
;
+
+ return (
+
+
+
setSelected(null)} />
+
+
+
+
+ حجوزاتي
+ لديك {reservations.length} حجز
+
+
+
+ {Object.entries(statusCounts).map(([status, count]) => (
+
setFilterStatus(status)}
+ >
+ {count}
+ {status === 'all' ? 'الكل' : (statusConfig[status]?.label || status)}
+
+ ))}
+
+
+
+
+ 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"
+ />
+
+
+ {filtered.length === 0 ? (
+
+
+
لا توجد حجوزات
+
لم تقم بأي حجز حتى الآن
+
+ ) : (
+
+ {filtered.map((r) => (
+
+ ))}
+
+ )}
+
+
+ );
+}