With the backend now returning 200 (lazy-created profile) instead of 404, align the consumers: the profile lives at res.data.data (the endpoint double-nests), so the booking detail and dashboard read that instead of res.data / the raw envelope. Drop the obsolete 404 special handling (empty editable form now comes from the 200 payload), seed the dashboard empty state when the profile has no real data yet, and make the profile POST fall back to PATCH on 409 (already lazy-created). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
172 lines
6.0 KiB
JavaScript
172 lines
6.0 KiB
JavaScript
import { useState } from "react";
|
|
import ButtonFixed from "../paying/ButtonFixed";
|
|
import { Button } from "@mui/material";
|
|
import ArrowLeftB from "@/components/icons/ArrowLeftB";
|
|
import { request } from "@/services/response";
|
|
import Cookies from "js-cookie";
|
|
|
|
function SubmitData({ setStep, data, prevData, setErrors, doctor, isForAnother, selectedSlot, selectedDate, setAppointmentId, setAppointmentExpiresAt }) {
|
|
const [loading, setLoading] = useState(false);
|
|
const newStep = () => setStep((prev) => prev + 1);
|
|
|
|
const refreshAccessToken = async () => {
|
|
try {
|
|
const refreshToken = Cookies.get("refresh_token");
|
|
if (!refreshToken) return false;
|
|
|
|
const res = await fetch("/api/auth/refresh", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ refresh_token: refreshToken }),
|
|
});
|
|
const response = await res.json();
|
|
|
|
if (response?.access_token) {
|
|
Cookies.set("access_token", response.access_token, { expires: 7 });
|
|
if (response.refresh_token) {
|
|
Cookies.set("refresh_token", response.refresh_token, { expires: 7 });
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
const isChanged = JSON.stringify(prevData) !== JSON.stringify(data);
|
|
|
|
setErrors({});
|
|
setLoading(true);
|
|
|
|
try {
|
|
if (!isForAnother && isChanged) {
|
|
const { basic_insurance, supplementary_insurance, name, family, national_code, gender, insurance_id, uuid } = data;
|
|
|
|
let payload = {};
|
|
|
|
// برای PATCH فقط فیلدهای تغییر یافته را ارسال میکنیم
|
|
if (uuid) {
|
|
// بررسی تغییرات فیلد به فیلد
|
|
if (JSON.stringify(prevData.name) !== JSON.stringify(name)) {
|
|
payload.name = name?.value;
|
|
}
|
|
if (JSON.stringify(prevData.family) !== JSON.stringify(family)) {
|
|
payload.family = family?.value;
|
|
}
|
|
if (JSON.stringify(prevData.national_code) !== JSON.stringify(national_code)) {
|
|
payload.national_code = national_code?.value;
|
|
}
|
|
if (JSON.stringify(prevData.gender) !== JSON.stringify(gender)) {
|
|
payload.gender = gender?.value?.id || gender?.value;
|
|
}
|
|
if (JSON.stringify(prevData.insurance_id) !== JSON.stringify(insurance_id)) {
|
|
payload.insurance_id = insurance_id?.value;
|
|
}
|
|
if (JSON.stringify(prevData.basic_insurance) !== JSON.stringify(basic_insurance)) {
|
|
payload.basic_insurance = basic_insurance?.value?.id ? [basic_insurance.value.id] : [];
|
|
}
|
|
if (JSON.stringify(prevData.supplementary_insurance) !== JSON.stringify(supplementary_insurance)) {
|
|
payload.supplementary_insurance = supplementary_insurance?.value?.id ? [supplementary_insurance.value.id] : [];
|
|
}
|
|
} else {
|
|
// برای POST همه فیلدها را ارسال میکنیم
|
|
payload = {
|
|
name: name?.value,
|
|
family: family?.value,
|
|
national_code: national_code?.value,
|
|
gender: gender?.value?.id || gender?.value,
|
|
insurance_id: insurance_id?.value,
|
|
basic_insurance: basic_insurance?.value?.id ? [basic_insurance.value.id] : [],
|
|
supplementary_insurance: supplementary_insurance?.value?.id ? [supplementary_insurance.value.id] : [],
|
|
};
|
|
}
|
|
|
|
if (uuid) {
|
|
await request.patchUserProfile(payload, uuid);
|
|
} else {
|
|
const userUuid = data?.uuid || Cookies.get("uuid");
|
|
try {
|
|
await request.postUserProfile(payload);
|
|
} catch (err) {
|
|
// پروفایل از قبل ساخته شده (lazy-create در سمت backend) → بهجای ساخت، ویرایش
|
|
if (err?.response?.status === 409 && userUuid) {
|
|
await request.patchUserProfile(payload, userUuid);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
const refreshed = await refreshAccessToken();
|
|
|
|
if (refreshed) {
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
}
|
|
}
|
|
|
|
if (doctor && selectedSlot) {
|
|
const appointmentPayload = {
|
|
doctor_uuid: doctor.uuid,
|
|
slot_start: selectedSlot.start,
|
|
slot_end: selectedSlot.end,
|
|
for_self: !isForAnother,
|
|
note: data?.patient_reason?.value || "",
|
|
...(isForAnother
|
|
? {
|
|
patient_name: [data?.name?.value, data?.family?.value].filter(Boolean).join(" ").trim(),
|
|
patient_mobile: data?.phone?.value,
|
|
patient_national_code: data?.national_code?.value || "",
|
|
patient_gender: data?.gender?.value?.id || data?.gender?.value || "",
|
|
patient_reason: data?.patient_reason?.value || "",
|
|
}
|
|
: {}),
|
|
};
|
|
|
|
const res = await request.postAppointment(appointmentPayload);
|
|
const appointmentUuid = res?.data?.uuid;
|
|
if (appointmentUuid) {
|
|
setAppointmentId(appointmentUuid);
|
|
setAppointmentExpiresAt?.(res?.data?.expires_at ?? null);
|
|
}
|
|
}
|
|
|
|
setLoading(false);
|
|
newStep();
|
|
} catch (error) {
|
|
setLoading(false);
|
|
if (error?.response?.status === 409) {
|
|
setStep(0);
|
|
return;
|
|
}
|
|
if (error?.response?.data) {
|
|
setErrors(error.response.data);
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<ButtonFixed>
|
|
<Button
|
|
disabled={loading}
|
|
className={`
|
|
!flex !w-full md:!w-fit !mt-0 md:!mt-[32px]
|
|
!gap-[4px] md:!mr-auto !px-[12px] !py-[8px] md:!py-[9px] !min-w-[150px]
|
|
`}
|
|
variant="contained"
|
|
onClick={handleSubmit}
|
|
>
|
|
<p
|
|
className={`${loading && "opacity-0"} text-[#EFEFEF] text-[16px] font-medium`}
|
|
>
|
|
ثبت اطلاعات
|
|
</p>
|
|
<ArrowLeftB />
|
|
</Button>
|
|
</ButtonFixed>
|
|
);
|
|
}
|
|
|
|
export default SubmitData;
|