refactor: enhance appointment handling by adding appointmentId state and updating payment process

This commit is contained in:
hamed
2025-11-18 17:09:37 +03:30
parent 5a9f21e88d
commit df54983fa3
6 changed files with 126 additions and 21 deletions
+4 -1
View File
@@ -34,6 +34,8 @@ function Container({
setSelectedSlot,
selectedDate,
setSelectedDate,
appointmentId,
setAppointmentId,
}) {
const elements = [
<Date
@@ -70,8 +72,9 @@ function Container({
doctor={doctor}
selectedSlot={selectedSlot}
selectedDate={selectedDate}
setAppointmentId={setAppointmentId}
/>,
<Paying setStep={setStep} />,
<Paying setStep={setStep} appointmentId={appointmentId} />,
<SuccessPay setStep={setStep} />,
<FailedPay setStep={setStep} />,
];
+5 -2
View File
@@ -5,7 +5,7 @@ import ArrowLeftB from "@/components/icons/ArrowLeftB";
import { request } from "@/services/response";
import Cookies from "js-cookie";
function SubmitData({ setStep, data, prevData, setErrors, doctor, selectedSlot, selectedDate }) {
function SubmitData({ setStep, data, prevData, setErrors, doctor, selectedSlot, selectedDate, setAppointmentId }) {
const [loading, setLoading] = useState(false);
const newStep = () => setStep((prev) => prev + 1);
@@ -113,7 +113,10 @@ function SubmitData({ setStep, data, prevData, setErrors, doctor, selectedSlot,
info: ""
};
await request.postAppointment(appointmentPayload);
const appointmentResponse = await request.postAppointment(appointmentPayload);
if (appointmentResponse?.id) {
setAppointmentId(appointmentResponse.id);
}
}
setLoading(false);
+6 -4
View File
@@ -18,6 +18,7 @@ function Detail({
doctor,
selectedSlot,
selectedDate,
setAppointmentId,
}) {
const [insurance, setInsurance] = useState();
const [supplementaryInsurance, setSupplementaryInsurance] = useState();
@@ -93,14 +94,15 @@ function Detail({
</p>
</Button>
)}
<SubmitData
setStep={setStep}
data={data}
prevData={prevData}
<SubmitData
setStep={setStep}
data={data}
prevData={prevData}
setErrors={setErrors}
doctor={doctor}
selectedSlot={selectedSlot}
selectedDate={selectedDate}
setAppointmentId={setAppointmentId}
/>
</div>
</div>
+3
View File
@@ -32,6 +32,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) {
// Appointment slot states
const [selectedSlot, setSelectedSlot] = useState(null);
const [selectedDate, setSelectedDate] = useState(null);
const [appointmentId, setAppointmentId] = useState(null);
useEffect(() => {
const fetchUserData = async () => {
@@ -201,6 +202,8 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) {
setSelectedSlot={setSelectedSlot}
selectedDate={selectedDate}
setSelectedDate={setSelectedDate}
appointmentId={appointmentId}
setAppointmentId={setAppointmentId}
/>
);
}
+107 -14
View File
@@ -1,8 +1,70 @@
import { useState, useEffect } from "react";
import ArrowLeftB from "@/components/icons/ArrowLeftB";
import { Button } from "@mui/material";
import { Button, MenuItem, Select, FormControl, InputLabel } from "@mui/material";
import ButtonFixed from "./ButtonFixed";
import { request } from "@/services/response";
function Paying({ setStep, appointmentId }) {
const [selectedBank, setSelectedBank] = useState("");
const [loading, setLoading] = useState(false);
const [timeLeft, setTimeLeft] = useState(600); // 10 minutes in seconds
const banks = [
{ id: "mellat", title: "بانک ملت" },
{ id: "saman", title: "سامان کیش" }
];
useEffect(() => {
if (timeLeft === 0) return;
const timer = setInterval(() => {
setTimeLeft((prev) => prev - 1);
}, 1000);
return () => clearInterval(timer);
}, [timeLeft]);
const formatTime = (seconds) => {
const minutes = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${minutes}:${secs.toString().padStart(2, '0')}`;
};
const handlePayment = async () => {
if (!selectedBank) {
alert("لطفا بانک خود را انتخاب کنید");
return;
}
if (!appointmentId) {
alert("شناسه نوبت یافت نشد");
return;
}
setLoading(true);
try {
const paymentPayload = {
payment_method: selectedBank,
bundle: "appointment",
entity_reference_id: appointmentId
};
const response = await request.postPayment(paymentPayload);
// Redirect to payment gateway
if (response?.uuid) {
const paymentUrl = `${process.env.NEXT_PUBLIC_API_URL}/payment/${response.uuid}`;
window.location.href = paymentUrl;
} else {
setStep((prev) => prev + 1);
}
} catch (error) {
console.error("Payment error:", error);
alert("خطا در پرداخت");
setLoading(false);
}
};
function Paying({ setTypePay, fadeElement, setStep }) {
return (
<div className="w-full lg:w-[59%]">
<div
@@ -12,29 +74,60 @@ function Paying({ setTypePay, fadeElement, setStep }) {
<p className="text-[#3B3B3B] text-[14px] sm:text-[16px] md:text-[18px] lg:text-[20px] font-bold">
اطلاعات پرداخت
</p>
<div className="flex justify-between items-center mt-[12px] sm:mt-[18px] md:mt-[24px] lg:mt-[30px]">
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium">
مبلغ پیش پرداخت (بیعانه) :{" "}
</p>
<p className="text-[#525252] text-[14px] md:text-[16px] font-bold">
20،000 تومان
</p>
<div className="mt-[12px] sm:mt-[18px] md:mt-[24px] lg:mt-[30px]">
<div className="flex justify-between items-center mb-4">
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium">
زمان باقیمانده:
</p>
<p className={`text-[14px] md:text-[16px] font-bold ${timeLeft < 60 ? 'text-red-500' : 'text-[#525252]'}`}>
{formatTime(timeLeft)}
</p>
</div>
<FormControl fullWidth className="!mb-4">
<InputLabel id="bank-select-label">انتخاب بانک</InputLabel>
<Select
labelId="bank-select-label"
value={selectedBank}
label="انتخاب بانک"
onChange={(e) => setSelectedBank(e.target.value)}
>
{banks.map((bank) => (
<MenuItem key={bank.id} value={bank.id}>
{bank.title}
</MenuItem>
))}
</Select>
</FormControl>
{/* <div className="flex justify-between items-center">
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium">
مبلغ پیش پرداخت (بیعانه) :
</p>
<p className="text-[#525252] text-[14px] md:text-[16px] font-bold">
10،000 تومان
</p>
</div> */}
</div>
<span className="bg-[#D7D7D7] hidden md:block h-px w-full mt-[32px] mb-[25px]"></span>
<ButtonFixed>
<div className="flex items-center justify-between gap-2">
<p className="text-[#616161] md:text-[#3B3B3B] text-[14px] md:text-[16px] font-bold">
مبلغ قابل پرداخت : 20،000 تومان
مبلغ قابل پرداخت : 10،000 تومان
</p>
<Button
className="!gap-[4px] !mr-auto !flex !px-[12px] !p-[7px] md:!py-[9px] !min-w-[157px]"
onClick={() => setStep((prev) => prev + 1)}
onClick={handlePayment}
variant="contained"
disabled={loading || !selectedBank || timeLeft === 0}
>
<p className="text-[#EFEFEF] text-[16px] font-medium">
پرداخت نهایی
<p className={`${loading && "opacity-0"} text-[#EFEFEF] text-[16px] font-medium`}>
{timeLeft === 0 ? "زمان پرداخت تمام شد" : "پرداخت نهایی"}
</p>
<ArrowLeftB />
{timeLeft > 0 && <ArrowLeftB />}
</Button>
</div>
</ButtonFixed>
+1
View File
@@ -67,6 +67,7 @@ export const request = {
removeTokenHead
),
postAppointment: (data) => api.post(`api/v1/appointment`, data, { requireAuth: true }),
postPayment: (data) => api.post(`api/v1/payment`, data, { requireAuth: true }),
postDoctor: (data) => api.post("api/v1/doctor", data),
postImageUpload: (data) =>
api.post("file/upload/clinic_pro/doctor/field_image", data, {