From eb3cb6ca1045cdd9e1031b3dfe5a291c759fa2d9 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Mon, 15 Jun 2026 18:09:33 +0330 Subject: [PATCH] feat(appointment): payment timer from real lock + status-driven payment UX Drive the payment countdown from the booking's expires_at (15-min lock) instead of a fake local 10-min timer; when it hits zero, show an expiry notice and an 'choose time again' button back to slot selection. Show the booked time (Jalali) and doctor on the payment step, and replace the fabricated success amount with a confirmation/SMS note. Co-Authored-By: Claude Opus 4.8 --- components/appointment/paying/index.js | 64 ++++++++++++++++------ components/appointment/successPay/index.js | 18 +----- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/components/appointment/paying/index.js b/components/appointment/paying/index.js index b7173f4..069ab04 100644 --- a/components/appointment/paying/index.js +++ b/components/appointment/paying/index.js @@ -1,13 +1,19 @@ import { useState, useEffect } from "react"; +import moment from "moment-jalaali"; import ArrowLeftB from "@/components/icons/ArrowLeftB"; import { Button, MenuItem, Select, FormControl, InputLabel } from "@mui/material"; import ButtonFixed from "./ButtonFixed"; import { request } from "@/services/response"; -function Paying({ setStep, appointmentId }) { +function Paying({ setStep, appointmentId, expiresAt, doctor, selectedSlot, selectedDate }) { const [selectedBank, setSelectedBank] = useState(""); const [loading, setLoading] = useState(false); - const [timeLeft, setTimeLeft] = useState(600); // 10 minutes in seconds + + const computeLeft = () => + expiresAt + ? Math.max(0, Math.floor((expiresAt * 1000 - Date.now()) / 1000)) + : 900; + const [timeLeft, setTimeLeft] = useState(computeLeft); const banks = [ { id: "mellat", title: "بانک ملت" }, @@ -15,14 +21,12 @@ function Paying({ setStep, appointmentId }) { ]; useEffect(() => { - if (timeLeft === 0) return; - const timer = setInterval(() => { - setTimeLeft((prev) => prev - 1); + setTimeLeft(computeLeft()); }, 1000); return () => clearInterval(timer); - }, [timeLeft]); + }, [expiresAt]); const formatTime = (seconds) => { const minutes = Math.floor(seconds / 60); @@ -74,6 +78,16 @@ function Paying({ setStep, appointmentId }) { اطلاعات پرداخت

+ {selectedSlot?.start && ( +
+ زمان نوبت: + + {moment.unix(selectedSlot.start).locale("fa").format("jD jMMMM jYYYY - HH:mm")} + {doctor?.name ? ` با ${doctor.name}` : ""} + +
+ )} +

@@ -112,19 +126,35 @@ function Paying({ setStep, appointmentId }) { + {timeLeft === 0 && ( +

+ مهلت پرداخت تمام شد؛ لطفاً دوباره زمان نوبت را انتخاب کنید. +

+ )} +
- + {timeLeft === 0 ? ( + + ) : ( + + )}
diff --git a/components/appointment/successPay/index.js b/components/appointment/successPay/index.js index 6a7a102..6ebd250 100644 --- a/components/appointment/successPay/index.js +++ b/components/appointment/successPay/index.js @@ -18,24 +18,12 @@ function SuccessPay({ setStep }) {

- برای نمایش نوبت ها به قسمت نوبت های من بروید.{" "} + نوبت شما تأیید شد و پیامک تأیید برای بیمار ارسال می‌شود. برای نمایش نوبت‌ها به قسمت نوبت‌های من بروید.{" "}

-
- -
-

- مقدار پرداخت شده:{" "} -

-

- 20،000 تومان -

-
- -