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"; import { setAccessToken } from "@/lib/tokenStore"; import { useProvince } from "@/context/ProvinceProvider"; function SubmitData({ setStep, data, prevData, setErrors, doctor, isForAnother, selectedSlot, selectedDate, setAppointmentId, setAppointmentExpiresAt }) { const [loading, setLoading] = useState(false); const { cityId } = useProvince(); const newStep = () => setStep((prev) => prev + 1); const refreshAccessToken = async () => { try { const res = await fetch("/api/auth/refresh", { method: "POST" }); if (!res.ok) return false; const response = await res.json(); if (response?.access_token) { setAccessToken(response.access_token); return true; } return false; } catch { return false; } }; // پاسخ خطای backend: { success:false, errors:[{ code, field, message }] } // به نگاشت field→message تبدیل می‌شود تا inline در فرم نمایش داده شود. const fieldErrorsFromResponse = (error) => { const list = error?.response?.data?.errors; if (!Array.isArray(list)) return {}; return list.reduce((acc, e) => { if (e?.field && e?.message) acc[e.field] = e.message; return acc; }, {}); }; const isNationalCodeTaken = (error) => error?.response?.data?.errors?.some((e) => e?.code === "ERR_PROFILE_001"); const validate = () => { const errs = {}; const nationalCode = (data?.national_code?.value || "").trim(); if (!data?.name?.value?.trim()) errs.name = "نام الزامی است"; if (!data?.family?.value?.trim()) errs.family = "نام خانوادگی الزامی است"; if (!nationalCode) errs.national_code = "کد ملی الزامی است"; else if (!/^\d{10}$/.test(nationalCode)) errs.national_code = "کد ملی باید ۱۰ رقم باشد"; if (!data?.gender?.value) errs.gender = "جنسیت الزامی است"; if (!data?.basic_insurance?.value?.id) errs.basic_insurance = "نوع بیمه الزامی است"; return errs; }; const handleSubmit = async () => { const errs = validate(); if (Object.keys(errs).length > 0) { setErrors(errs); return; } 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) { // 409 با کد ERR_PROFILE_001 یعنی کد ملی تکراری، نه «پروفایل موجود» → باید throw شود تا inline نمایش یابد // پروفایل از قبل ساخته شده (lazy-create در سمت backend) → به‌جای ساخت، ویرایش if (err?.response?.status === 409 && userUuid && !isNationalCodeTaken(err)) { 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 || "", // کد ملی و جنسیت در هر دو حالت (خودِ بیمار / شخص دیگر) الزامی است. patient_national_code: data?.national_code?.value || "", patient_gender: data?.gender?.value?.id || data?.gender?.value || "", // شناسه‌ی شهرِ دامنه‌ی جاری؛ backend برای گاردِ پورسانت نماینده استفاده می‌کند. city_id: cityId ?? null, ...(isForAnother ? { patient_name: [data?.name?.value, data?.family?.value].filter(Boolean).join(" ").trim(), patient_mobile: data?.phone?.value, patient_reason: data?.patient_reason?.value || "", } : {}), }; const res = await request.postAppointment(appointmentPayload); const appointment = res?.data?.data; const appointmentUuid = appointment?.uuid; if (appointmentUuid) { setAppointmentId(appointmentUuid); setAppointmentExpiresAt?.(appointment?.expires_at ?? null); } } setLoading(false); newStep(); } catch (error) { setLoading(false); const fieldErrors = fieldErrorsFromResponse(error); if (Object.keys(fieldErrors).length > 0) { setErrors(fieldErrors); return; } if (error?.response?.status === 409) { setStep(0); return; } } }; return ( ); } export default SubmitData;