diff --git a/app/reservations/page.js b/app/reservations/page.js
index 6307b8d..5bdf549 100644
--- a/app/reservations/page.js
+++ b/app/reservations/page.js
@@ -390,17 +390,37 @@
-
-
-
'use client';
import { useState, useEffect, useCallback } from 'react';
+import Link from 'next/link';
import { motion } from 'framer-motion';
import { useRouter } from 'next/navigation';
import {
- Calendar, Clock, CheckCircle, XCircle, Eye, Loader2, Search,
- MapPin, DollarSign, Home, ArrowLeft, CreditCard, Timer, Star, Flag,
+ Calendar,
+ Clock,
+ CheckCircle,
+ XCircle,
+ Eye,
+ Loader2,
+ Search,
+ MapPin,
+ DollarSign,
+ Home,
+ ArrowLeft,
+ CreditCard,
+ Timer,
+ Star,
+ Flag,
+ Banknote,
+ Building,
+ ArrowLeftRight,
+ Check,
+ X,
+ Info,
+ Landmark,
+ Phone,
+ Wallet,
} from 'lucide-react';
import toast, { Toaster } from 'react-hot-toast';
import AuthService from '../services/AuthService';
@@ -420,10 +440,52 @@ const STATUS_UI = {
cancelled: { label: 'ملغي', color: 'bg-gray-100 text-gray-800', icon: XCircle },
};
+const PAYMENT_METHODS = [
+ {
+ id: 'cash',
+ label: 'الدفع النقدي',
+ desc: 'ادفع الآن عبر شام كاش مع تأكيد تلقائي للحجز',
+ icon: Banknote,
+ active: true,
+ },
+ {
+ id: 'office',
+ label: 'نقداً',
+ desc: 'ادفع في مكتب المنصة. يتم التأكيد لاحقاً',
+ icon: Building,
+ active: true,
+ },
+ {
+ id: 'transfer',
+ label: 'تحويل داخلي',
+ desc: 'حول من حساب داخلي ثم أرسل المرجع',
+ icon: ArrowLeftRight,
+ active: false,
+ },
+ {
+ id: 'electronic',
+ label: 'دفع إلكتروني',
+ desc: 'سيتم تفعيل الدفع الإلكتروني والتحويل لاحقاً',
+ icon: CreditCard,
+ active: false,
+ },
+];
+
function statusLabel(code) { return STATUS_UI[STATUS_MAP[code]]?.label ?? String(code); }
function statusColor(code) { return STATUS_UI[STATUS_MAP[code]]?.color ?? 'bg-gray-100 text-gray-700'; }
function statusIcon(code) { return STATUS_UI[STATUS_MAP[code]]?.icon ?? Clock; }
+function formatCurrency(v, sign = 'ل.س') {
+ return `${sign} ${Number(v ?? 0).toLocaleString()}`;
+}
+
+function formatDate(date) {
+ if (!date) return '';
+ const d = new Date(date);
+ if (Number.isNaN(d.getTime())) return '';
+ return d.toLocaleDateString('en-GB');
+}
+
function StatusBadge({ code }) {
const Icon = statusIcon(code);
return (
@@ -594,6 +656,247 @@ function CountdownTimer({ deadline }) {
return {pad(h)}:{pad(m)}:{pad(s)};
}
+function PaymentDialog({
+ isOpen,
+ reservation,
+ onClose,
+ selectedPayment,
+ onSelectPayment,
+ onConfirmPay,
+ payingId,
+}) {
+ const [showCashDialog, setShowCashDialog] = useState(false);
+
+ useEffect(() => {
+ if (isOpen) setShowCashDialog(false);
+ }, [isOpen, reservation?.id]);
+
+ if (!isOpen || !reservation) return null;
+
+ const amount = reservation.depositAmount || reservation.totalPrice || 0;
+ const currencySign = reservation.currencySign || 'ل.س';
+
+ return (
+ <>
+
+
e.stopPropagation()}
+ >
+
+
+
+
+
+
+
+ {reservation.propertyName}
+
+ {(reservation.propertyAddress || reservation.propertyCity) && (
+
+
+ {[reservation.propertyCity, reservation.propertyAddress].filter(Boolean).join(' - ')}
+
+ )}
+
+
+
+
+
+
+ {formatDate(reservation.startDate)} - {formatDate(reservation.endDate)}
+
+
+
+ #{reservation.reservationId || reservation.id}
+
+
+
+
+
+
+
مبلغ التأمين (الرعبون)
+
+ {formatCurrency(amount, currencySign)}
+
+
+ يتم دفع التأمين إلى المنصة وليس إلى المالك
+
+
+
+
+
+
+
+
+ الدفع النقدي فقط هو المتاح. سيتم تفعيل الدفع الإلكتروني والتحويل لاحقاً.
+
+
+
+
+
+
طريقة الدفع
+
+ {PAYMENT_METHODS.map((method) => {
+ const isSelected = selectedPayment === method.id;
+ const Icon = method.icon;
+
+ return (
+
+ );
+ })}
+
+
+
+
+ onConfirmPay(reservation)}
+ disabled={payingId === reservation.id}
+ whileHover={{ scale: 1.01 }}
+ whileTap={{ scale: 0.99 }}
+ className="w-full bg-amber-500 hover:bg-amber-600 disabled:bg-amber-300 text-white font-bold py-4 px-6 rounded-2xl text-lg transition-all shadow-lg hover:shadow-xl flex items-center justify-center gap-3"
+ >
+ {payingId === reservation.id ? (
+ <>
+
+ جاري الدفع...
+ >
+ ) : (
+ <>
+
+ دفع التأمين ({formatCurrency(amount, currencySign)})
+ >
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
موقع الدفع النقدي
+
+ مكتب المنصة: أبو رمانة، شارع المالكي، دمشق
+
+
+
+ +963567823411
+
+
+
+
+
+
+
+
+
+
+
+ {showCashDialog && (
+
+
+
+
+
+ الدفع النقدي قيد الانتظار
+
+ اذهب إلى موقع المنصة وادفع العربون.
+
+ ستقوم المنصة بتأكيد الدفع بعد استلام المبلغ.
+
+
+
موقع المنصة
+
مكتب المنصة: أبو رمانة، شارع المالكي، دمشق
+
+
+ +963567823411
+
+
+
+
+
+ حجوزاتي
+
+
+
+
+ )}
+ >
+ );
+}
+
function ReportDialog({ isOpen, reservation, onClose, onSubmit, submitting }) {
const [message, setMessage] = useState('');
@@ -865,6 +1168,8 @@ export default function UserReservationsPage() {
const [payingId, setPayingId] = useState(null);
const [reportDialog, setReportDialog] = useState({ open: false, reservation: null });
const [reportingId, setReportingId] = useState(null);
+ const [selectedPayment, setSelectedPayment] = useState('cash');
+ const [paymentDialog, setPaymentDialog] = useState({ open: false, reservation: null });
useEffect(() => { if (!AuthService.getUser()) { router.push('/login'); return; } loadReservations(); }, [router]);
@@ -911,7 +1216,15 @@ export default function UserReservationsPage() {
const allStatuses = [...new Set(reservations.map(r => STATUS_MAP[r.status]))];
const counts = { all: reservations.length, ...Object.fromEntries(allStatuses.map(s => [s, reservations.filter(r => STATUS_MAP[r.status] === s).length])) };
- const handlePay = async (r) => {
+ const openPaymentDialog = (r) => {
+ setPaymentDialog({ open: true, reservation: r });
+ };
+
+ const closePaymentDialog = () => {
+ setPaymentDialog({ open: false, reservation: null });
+ };
+
+ const handleConfirmPay = async (r) => {
setPayingId(r.id);
try {
await payDeposit({
@@ -921,6 +1234,7 @@ export default function UserReservationsPage() {
comment: null,
});
toast.success('تم دفع السلفة بنجاح!');
+ closePaymentDialog();
loadReservations();
} catch (err) {
toast.error(err?.message || 'فشل عملية الدفع');
@@ -961,7 +1275,7 @@ export default function UserReservationsPage() {
r={selected}
isOpen={!!selected}
onClose={() => setSelected(null)}
- onPay={handlePay}
+ onPay={openPaymentDialog}
onReport={openReportDialog}
payingId={payingId}
reportingId={reportingId}
@@ -973,6 +1287,15 @@ export default function UserReservationsPage() {
onSubmit={handleSubmitReport}
submitting={!!reportingId}
/>
+
@@ -1007,7 +1330,7 @@ export default function UserReservationsPage() {
key={r.id}
r={r}
onViewDetails={setSelected}
- onPay={handlePay}
+ onPay={openPaymentDialog}
onReport={openReportDialog}
payingId={payingId}
reportingId={reportingId}