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}