// '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,
// RefreshCw,
// } from 'lucide-react';
// import toast, { Toaster } from 'react-hot-toast';
// import AuthService from '../../services/AuthService';
// import { getRentProperty } from '../../utils/api';
// const API_BASE =
// process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api';
// const STATUS_MAP = [
// 'pending',
// 'ownerConfirmed',
// 'depositPaid',
// 'depositConfirmed',
// 'completed',
// 'cancelled',
// ];
// const STATUS_UI = {
// 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,
// },
// completed: {
// label: 'منتهي',
// color: 'bg-blue-100 text-blue-800',
// icon: CheckCircle,
// },
// cancelled: {
// label: 'ملغي',
// color: 'bg-gray-100 text-gray-800',
// icon: XCircle,
// },
// };
// const getStatusKey = (code) => STATUS_MAP[Number(code)] || 'pending';
// const sLabel = (code) => STATUS_UI[getStatusKey(code)]?.label ?? String(code);
// const sColor = (code) =>
// STATUS_UI[getStatusKey(code)]?.color ?? 'bg-gray-100 text-gray-700';
// const sIcon = (code) => STATUS_UI[getStatusKey(code)]?.icon ?? Clock;
// function StatusBadge({ code }) {
// const Icon = sIcon(code);
// return (
//
// {sLabel(code)}
//
// );
// }
// async function enrich(r) {
// if (!r?.propertyId) return r;
// try {
// const prop = await getRentProperty(r.propertyId);
// return {
// ...r,
// _prop: prop?.propertyInformation ?? prop ?? null,
// };
// } catch {
// return {
// ...r,
// _prop: null,
// };
// }
// }
// const pAddr = (p) => p?.address ?? '';
// const pImgs = (p) => (Array.isArray(p?.images) ? p.images : []);
// const pBeds = (p) => p?.numberOfBedRooms ?? 0;
// const pBaths = (p) => p?.numberOfBathRooms ?? 0;
// const API = (token, method, path, body) => {
// return fetch(`${API_BASE}${path}`, {
// method: method || 'GET',
// headers: {
// 'Content-Type': 'application/json',
// ...(token && { Authorization: `Bearer ${token}` }),
// },
// ...(body && { body: JSON.stringify(body) }),
// });
// };
// function buildImageUrl(path) {
// if (!path) return null;
// if (path.startsWith('http://') || path.startsWith('https://')) {
// return path;
// }
// return `${API_BASE}${path}`;
// }
// function OwnerCard({
// r,
// onViewDetails,
// onConfirm,
// onReject,
// actionLoadingId,
// }) {
// const p = r._prop;
// const imgs = pImgs(p);
// const img = imgs.length > 0 ? buildImageUrl(imgs[0]) : null;
// const addr = pAddr(p);
// const isPending = Number(r.status) === 0;
// const isActionLoading = actionLoadingId === r.id;
// return (
//
//
// {img && (
//
//

//
// )}
//
//
//
// {addr && (
//
//
// {addr}
//
// )}
//
//
//
// {r.totalPrice?.toLocaleString() ?? '—'}
//
//
السعر الإجمالي
//
//
// {(pBeds(p) || pBaths(p)) && (
//
// {pBeds(p) > 0 && {pBeds(p)} غرف}
// {pBaths(p) > 0 && {pBaths(p)} حمامات}
//
// )}
//
//
//
//
من
//
// {r.startDate
// ? new Date(r.startDate).toLocaleDateString('ar')
// : '—'}
//
//
//
//
//
إلى
//
// {r.endDate ? new Date(r.endDate).toLocaleDateString('ar') : '—'}
//
//
//
//
//
// {isPending && (
// <>
//
//
// >
// )}
//
//
//
// );
// }
// function DetailsModal({ r, isOpen, onClose }) {
// if (!isOpen || !r) return null;
// const p = r._prop;
// return (
//
// e.stopPropagation()}
// >
//
//
//
طلب حجز #{r.id}
//
//
//
//
// {p && (
//
//
//
// معلومات العقار
//
//
// العنوان:{' '}
// {pAddr(p) || '—'}
//
// {(pBeds(p) || pBaths(p)) && (
//
// {pBeds(p) > 0 && (
//
// {pBeds(p)} غرف
//
// )}
// {pBaths(p) > 0 && (
//
// {pBaths(p)} حمامات
//
// )}
//
// )}
//
// )}
//
//
//
// تفاصيل الحجز
//
//
//
//
تاريخ البداية
//
// {r.startDate
// ? new Date(r.startDate).toLocaleDateString('ar')
// : '—'}
//
//
//
//
تاريخ النهاية
//
// {r.endDate ? new Date(r.endDate).toLocaleDateString('ar') : '—'}
//
//
//
//
//
تاريخ الإنشاء
//
// {r.createdAt
// ? new Date(r.createdAt).toLocaleDateString('ar')
// : '—'}
//
//
//
//
//
//
//
// المعلومات المالية
//
//
// الإجمالي
//
// {r.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('');
// const [actionLoadingId, setActionLoadingId] = useState(null);
// const loadReservations = useCallback(async () => {
// try {
// setLoading(true);
// const token = AuthService.getToken();
// const res = await fetch(
// `${API_BASE}/Reservations/GetOwnerResevationRequests`,
// {
// method: 'GET',
// headers: {
// Authorization: `Bearer ${token}`,
// 'Content-Type': 'application/json',
// },
// }
// );
// if (!res.ok) {
// const errorText = await res.text();
// throw new Error(errorText || `HTTP ${res.status}`);
// }
// const json = await res.json();
// let list = json.data || json || [];
// if (!Array.isArray(list)) list = [];
// const enriched = await Promise.all(list.map(enrich));
// setReservations(enriched);
// setFiltered(enriched);
// } catch (err) {
// console.error(err);
// toast.error('فشل تحميل طلبات الحجز');
// setReservations([]);
// setFiltered([]);
// } finally {
// setLoading(false);
// }
// }, []);
// useEffect(() => {
// if (!AuthService.getUser() || !AuthService.isOwner()) {
// router.push('/auth/choose-role');
// return;
// }
// loadReservations();
// }, [router, loadReservations]);
// useEffect(() => {
// let result = reservations;
// if (filterStatus !== 'all') {
// result = result.filter((x) => getStatusKey(x.status) === filterStatus);
// }
// if (searchTerm.trim()) {
// const q = searchTerm.trim().toLowerCase();
// result = result.filter(
// (x) =>
// pAddr(x._prop).toLowerCase().includes(q) || String(x.id).includes(q)
// );
// }
// setFiltered(result);
// }, [reservations, filterStatus, searchTerm]);
// const handleConfirm = async (r) => {
// try {
// setActionLoadingId(r.id);
// const res = await API(
// AuthService.getToken(),
// 'PUT',
// `/Reservations/OwnerConfirmReservation/owner-confirm/${r.id}`
// );
// if (!res.ok) {
// const errorText = await res.text();
// throw new Error(errorText || `HTTP ${res.status}`);
// }
// toast.success('تم قبول الحجز بنجاح');
// await loadReservations();
// } catch (err) {
// console.error(err);
// toast.error('فشل قبول الحجز');
// } finally {
// setActionLoadingId(null);
// }
// };
// const handleReject = async (r) => {
// if (!confirm('هل أنت متأكد من رفض هذا الحجز؟')) return;
// try {
// setActionLoadingId(r.id);
// const res = await API(
// AuthService.getToken(),
// 'POST',
// `/Reservations/ChangeReservationStatus?id=${r.id}&newStatus=5`
// );
// if (!res.ok) {
// const errorText = await res.text();
// throw new Error(errorText || `HTTP ${res.status}`);
// }
// toast.success('تم رفض الحجز');
// await loadReservations();
// } catch (err) {
// console.error(err);
// toast.error('فشل رفض الحجز');
// } finally {
// setActionLoadingId(null);
// }
// };
// const allStatuses = [
// ...new Set(reservations.map((r) => getStatusKey(r.status)).filter(Boolean)),
// ];
// const counts = {
// all: reservations.length,
// ...Object.fromEntries(
// allStatuses.map((s) => [
// s,
// reservations.filter((r) => getStatusKey(r.status) === s).length,
// ])
// ),
// };
// if (loading) {
// return (
//
//
//
// );
// }
// return (
//
//
//
setSelected(null)}
// />
//
//
//
//
//
//
// طلبات الحجز
//
//
لديك {reservations.length} طلب
//
//
//
//
//
// {Object.entries(counts).map(([s, c]) => (
//
setFilterStatus(s)}
// >
// {c}
//
// {s === 'all' ? 'الكل' : STATUS_UI[s]?.label || s}
//
//
// ))}
//
//
//
// 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) => (
//
// ))}
//
// )}
//
//
// );
// }
'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,
RefreshCw,
Flag,
} from 'lucide-react';
import toast, { Toaster } from 'react-hot-toast';
import AuthService from '../../services/AuthService';
import { getRentProperty } from '../../utils/api';
const API_BASE =
process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api';
const STATUS_MAP = [
'pending',
'ownerConfirmed',
'depositPaid',
'depositConfirmed',
'completed',
'cancelled',
];
const STATUS_UI = {
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,
},
completed: {
label: 'منتهي',
color: 'bg-blue-100 text-blue-800',
icon: CheckCircle,
},
cancelled: {
label: 'ملغي',
color: 'bg-gray-100 text-gray-800',
icon: XCircle,
},
};
const getStatusKey = (code) => STATUS_MAP[Number(code)] || 'pending';
const sLabel = (code) => STATUS_UI[getStatusKey(code)]?.label ?? String(code);
const sColor = (code) =>
STATUS_UI[getStatusKey(code)]?.color ?? 'bg-gray-100 text-gray-700';
const sIcon = (code) => STATUS_UI[getStatusKey(code)]?.icon ?? Clock;
function StatusBadge({ code }) {
const Icon = sIcon(code);
return (
{sLabel(code)}
);
}
async function enrich(r) {
if (!r?.propertyId) return r;
try {
const prop = await getRentProperty(r.propertyId);
return {
...r,
_prop: prop?.propertyInformation ?? prop ?? null,
};
} catch {
return {
...r,
_prop: null,
};
}
}
const pAddr = (p) => p?.address ?? '';
const pImgs = (p) => (Array.isArray(p?.images) ? p.images : []);
const pBeds = (p) => p?.numberOfBedRooms ?? 0;
const pBaths = (p) => p?.numberOfBathRooms ?? 0;
const API = (token, method, path, body) => {
return fetch(`${API_BASE}${path}`, {
method: method || 'GET',
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
},
...(body && { body: JSON.stringify(body) }),
});
};
function buildImageUrl(path) {
if (!path) return null;
if (path.startsWith('http://') || path.startsWith('https://')) {
return path;
}
return `${API_BASE}${path}`;
}
const getAuthToken = () => {
if (typeof window === 'undefined') return '';
return (
AuthService.getToken?.() ||
AuthService.getAccessToken?.() ||
localStorage.getItem('token') ||
localStorage.getItem('accessToken') ||
localStorage.getItem('authToken') ||
''
);
};
const readStoredUser = () => {
if (typeof window === 'undefined') return null;
const keys = ['user', 'currentUser', 'authUser', 'profile'];
for (const key of keys) {
const raw = localStorage.getItem(key);
if (!raw) continue;
try {
return JSON.parse(raw);
} catch {
return raw;
}
}
return null;
};
const extractNumericUserId = (value) => {
if (!value) return null;
if (typeof value === 'number') return Number.isInteger(value) ? value : null;
if (typeof value === 'string') {
const n = Number(value);
return Number.isInteger(n) ? n : null;
}
if (typeof value === 'object') {
const candidates = [
value.id,
value.userId,
value.userID,
value.user?.id,
value.user?.userId,
value.profile?.id,
value.profile?.userId,
value.data?.id,
];
for (const candidate of candidates) {
const id = extractNumericUserId(candidate);
if (id !== null) return id;
}
}
return null;
};
async function reportReservation(reservationId, message) {
const user = AuthService.getUser?.() ?? readStoredUser();
const reporter = extractNumericUserId(user);
const rid = Number(reservationId);
if (!Number.isInteger(rid)) {
throw new Error('رقم الحجز غير صالح');
}
if (!Number.isInteger(reporter)) {
throw new Error('تعذر تحديد المستخدم الحالي');
}
const token = getAuthToken();
const res = await fetch(`${API_BASE}/ReservationReports/ReportReservation`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify({
reservationId: rid,
message: message ?? null,
reporter,
}),
});
if (!res.ok) {
let errorMessage = 'فشل إرسال البلاغ';
try {
const data = await res.json();
errorMessage = data?.message || data?.title || errorMessage;
} catch (_) {
try {
const text = await res.text();
if (text) errorMessage = text;
} catch (_) {}
}
throw new Error(errorMessage);
}
try {
return await res.json();
} catch {
return null;
}
}
function OwnerCard({
r,
onViewDetails,
onConfirm,
onReject,
onReport,
actionLoadingId,
reportingId,
}) {
const p = r._prop;
const imgs = pImgs(p);
const img = imgs.length > 0 ? buildImageUrl(imgs[0]) : null;
const addr = pAddr(p);
const isPending = Number(r.status) === 0;
const isActionLoading = actionLoadingId === r.id;
const isReporting = reportingId === r.id;
return (
{img && (
)}
{r.totalPrice?.toLocaleString() ?? '—'}
السعر الإجمالي
{(pBeds(p) || pBaths(p)) && (
{pBeds(p) > 0 && {pBeds(p)} غرف}
{pBaths(p) > 0 && {pBaths(p)} حمامات}
)}
من
{r.startDate
? new Date(r.startDate).toLocaleDateString('ar')
: '—'}
إلى
{r.endDate ? new Date(r.endDate).toLocaleDateString('ar') : '—'}
{isPending && (
<>
>
)}
);
}
function DetailsModal({ r, isOpen, onClose, onReport, reportingId }) {
if (!isOpen || !r) return null;
const p = r._prop;
const isReporting = reportingId === r.id;
return (
e.stopPropagation()}
>
{p && (
معلومات العقار
العنوان:{' '}
{pAddr(p) || '—'}
{(pBeds(p) || pBaths(p)) && (
{pBeds(p) > 0 && (
{pBeds(p)} غرف
)}
{pBaths(p) > 0 && (
{pBaths(p)} حمامات
)}
)}
)}
تفاصيل الحجز
تاريخ البداية
{r.startDate
? new Date(r.startDate).toLocaleDateString('ar')
: '—'}
تاريخ النهاية
{r.endDate ? new Date(r.endDate).toLocaleDateString('ar') : '—'}
تاريخ الإنشاء
{r.createdAt
? new Date(r.createdAt).toLocaleDateString('ar')
: '—'}
المعلومات المالية
الإجمالي
{r.totalPrice?.toLocaleString() ?? '—'}
);
}
function ReportDialog({ isOpen, reservation, onClose, onSubmit, submitting }) {
const [message, setMessage] = useState('');
useEffect(() => {
if (isOpen) setMessage('');
}, [isOpen, reservation?.id]);
if (!isOpen || !reservation) return null;
return (
e.stopPropagation()}
>
الإبلاغ عن الحجز
رقم الحجز: #{reservation.id}
اخبر فريق الدعم بما حدث التفاصيل الواضحة تساعدنا على مراجعة هذا الحجز بشكل اسرع
);
}
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('');
const [actionLoadingId, setActionLoadingId] = useState(null);
const [reportDialog, setReportDialog] = useState({ open: false, reservation: null });
const [reportingId, setReportingId] = useState(null);
const loadReservations = useCallback(async () => {
try {
setLoading(true);
const token = AuthService.getToken();
const res = await fetch(
`${API_BASE}/Reservations/GetOwnerResevationRequests`,
{
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
}
);
if (!res.ok) {
const errorText = await res.text();
throw new Error(errorText || `HTTP ${res.status}`);
}
const json = await res.json();
let list = json.data || json || [];
if (!Array.isArray(list)) list = [];
const enriched = await Promise.all(list.map(enrich));
setReservations(enriched);
setFiltered(enriched);
} catch (err) {
console.error(err);
toast.error('فشل تحميل طلبات الحجز');
setReservations([]);
setFiltered([]);
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
if (!AuthService.getUser() || !AuthService.isOwner()) {
router.push('/auth/choose-role');
return;
}
loadReservations();
}, [router, loadReservations]);
useEffect(() => {
let result = reservations;
if (filterStatus !== 'all') {
result = result.filter((x) => getStatusKey(x.status) === filterStatus);
}
if (searchTerm.trim()) {
const q = searchTerm.trim().toLowerCase();
result = result.filter(
(x) =>
pAddr(x._prop).toLowerCase().includes(q) || String(x.id).includes(q)
);
}
setFiltered(result);
}, [reservations, filterStatus, searchTerm]);
const handleConfirm = async (r) => {
try {
setActionLoadingId(r.id);
const res = await API(
AuthService.getToken(),
'PUT',
`/Reservations/OwnerConfirmReservation/owner-confirm/${r.id}`
);
if (!res.ok) {
const errorText = await res.text();
throw new Error(errorText || `HTTP ${res.status}`);
}
toast.success('تم قبول الحجز بنجاح');
await loadReservations();
} catch (err) {
console.error(err);
toast.error('فشل قبول الحجز');
} finally {
setActionLoadingId(null);
}
};
const handleReject = async (r) => {
if (!confirm('هل أنت متأكد من رفض هذا الحجز؟')) return;
try {
setActionLoadingId(r.id);
const res = await API(
AuthService.getToken(),
'POST',
`/Reservations/ChangeReservationStatus?id=${r.id}&newStatus=5`
);
if (!res.ok) {
const errorText = await res.text();
throw new Error(errorText || `HTTP ${res.status}`);
}
toast.success('تم رفض الحجز');
await loadReservations();
} catch (err) {
console.error(err);
toast.error('فشل رفض الحجز');
} finally {
setActionLoadingId(null);
}
};
const openReportDialog = (r) => {
setReportDialog({ open: true, reservation: r });
};
const closeReportDialog = () => {
setReportDialog({ open: false, reservation: null });
};
const handleSubmitReport = async (message) => {
if (!reportDialog.reservation) return;
setReportingId(reportDialog.reservation.id);
try {
await reportReservation(reportDialog.reservation.id, message.trim() || null);
toast.success('تم إرسال البلاغ بنجاح');
closeReportDialog();
} catch (err) {
console.error(err);
toast.error(err?.message || 'فشل إرسال البلاغ');
} finally {
setReportingId(null);
}
};
const allStatuses = [
...new Set(reservations.map((r) => getStatusKey(r.status)).filter(Boolean)),
];
const counts = {
all: reservations.length,
...Object.fromEntries(
allStatuses.map((s) => [
s,
reservations.filter((r) => getStatusKey(r.status) === s).length,
])
),
};
if (loading) {
return (
);
}
return (
setSelected(null)}
onReport={openReportDialog}
reportingId={reportingId}
/>
طلبات الحجز
لديك {reservations.length} طلب
{Object.entries(counts).map(([s, c]) => (
setFilterStatus(s)}
>
{c}
{s === 'all' ? 'الكل' : STATUS_UI[s]?.label || s}
))}
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) => (
))}
)}
);
}