diff --git a/app/component/fields/EditField.js b/app/component/fields/EditField.js index 9fb17f5..8117689 100644 --- a/app/component/fields/EditField.js +++ b/app/component/fields/EditField.js @@ -2,6 +2,21 @@ import EditGrayA from "@/components/icons/EditGrayA"; import EditOrangeA from "@/components/icons/EditOrangeA"; import { Button, TextField } from "@mui/material"; +// تابع تبدیل اعداد فارسی و عربی به انگلیسی +const convertPersianToEnglish = (str) => { + const persianNumbers = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; + const arabicNumbers = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩']; + + let result = str; + for (let i = 0; i < 10; i++) { + const regex = new RegExp(persianNumbers[i], 'g'); + result = result.replace(regex, i.toString()); + const arabicRegex = new RegExp(arabicNumbers[i], 'g'); + result = result.replace(arabicRegex, i.toString()); + } + return result; +}; + function EditField({ changeData, multiline, @@ -14,7 +29,31 @@ function EditField({ noDisable, type, props, + error, }) { + const handleChange = (e) => { + let inputValue = e.target.value; + + // اگر فیلد کد ملی یا شماره موبایل یا شماره بیمه است، فقط اعداد انگلیسی + if (name === "national_code" || name === "phone" || name === "insurance_id" || type === "tel") { + // ابتدا اعداد فارسی و عربی را به انگلیسی تبدیل کن + inputValue = convertPersianToEnglish(inputValue); + // فقط اعداد انگلیسی را نگه دار + inputValue = inputValue.replace(/[^0-9]/g, ''); + + // محدودیت تعداد ارقام + if (name === "national_code" && inputValue.length > 10) { + inputValue = inputValue.slice(0, 10); + } else if (name === "phone" && inputValue.length > 11) { + inputValue = inputValue.slice(0, 11); + } else if (name === "insurance_id" && inputValue.length > 16) { + inputValue = inputValue.slice(0, 16); + } + } + + changeData(inputValue, "value", name); + }; + return (
{ - changeData(e.target.value, "value", name); - }} + error={!!error} + helperText={error || ""} + className={`!w-full res-field-account dark:!bg-transparent ${isTransparent ? "!bg-transparent lg:!bg-[#FFF]" : "!bg-[#FFF]"} + }`} + onChange={handleChange} sx={{ "& .MuiFormLabel-root": { top: "-4px !important", @@ -43,6 +81,10 @@ function EditField({ padding: "0 !important", borderRadius: "8px !important", }, + "& .MuiFormHelperText-root": { + marginLeft: "0", + marginRight: "14px", + }, ".Mui-focused": { "& .MuiOutlinedInput-notchedOutline": { border: "1px solid #5559CE !important", @@ -50,17 +92,17 @@ function EditField({ }, }, "& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button": - { - display: "none", - }, + { + display: "none", + }, }} /> diff --git a/app/component/selectors/DefaultSelect.js b/app/component/selectors/DefaultSelect.js index 54f2245..99cf046 100644 --- a/app/component/selectors/DefaultSelect.js +++ b/app/component/selectors/DefaultSelect.js @@ -74,8 +74,14 @@ function DefaultSelect({ list, value, updateData, label, error, name }) { ), }} placeholder={label} + error={!!error} + helperText={error || ""} sx={{ borderRadius: "8px", + "& .MuiFormHelperText-root": { + marginLeft: "0", + marginRight: "14px", + }, }} /> )} diff --git a/components/appointment/detail/Form.js b/components/appointment/detail/Form.js index f8ec331..748a17a 100644 --- a/components/appointment/detail/Form.js +++ b/components/appointment/detail/Form.js @@ -2,7 +2,7 @@ import Content from "./Content"; import EditField from "../../../app/component/fields/EditField"; import DefaultSelect from "@/app/component/selectors/DefaultSelect"; -function Form({ changeData, insurance, supplementaryInsurance, data, isForAnother }) { +function Form({ changeData, insurance, supplementaryInsurance, data, isForAnother, errors = {} }) { const findBasicInsuranceVal = () => { return insurance?.find( (g) => @@ -25,20 +25,21 @@ function Form({ changeData, insurance, supplementaryInsurance, data, isForAnothe justify-center gap-x-[24px] gap-y-[12px] md:gap-y-[14px] lg:gap-y-[16px] grid-cols-1 sm:grid-cols-2" > - + - + - + + + + changeData(val, "value", name)} @@ -63,6 +68,7 @@ function Form({ changeData, insurance, supplementaryInsurance, data, isForAnothe name="basic_insurance" list={insurance} value={findBasicInsuranceVal()} + error={errors?.basic_insurance} /> @@ -72,6 +78,7 @@ function Form({ changeData, insurance, supplementaryInsurance, data, isForAnothe name="supplementary_insurance" list={supplementaryInsurance} value={findSupplementaryInsuranceVal()} + error={errors?.supplementary_insurance} />
diff --git a/components/appointment/detail/SubmitData.js b/components/appointment/detail/SubmitData.js index a4346ea..a8cd554 100644 --- a/components/appointment/detail/SubmitData.js +++ b/components/appointment/detail/SubmitData.js @@ -4,35 +4,51 @@ import { Button } from "@mui/material"; import ArrowLeftB from "@/components/icons/ArrowLeftB"; import { request } from "@/services/response"; -function SubmitData({ setStep, data, prevData }) { +function SubmitData({ setStep, data, prevData, setErrors }) { const [loading, setLoading] = useState(false); const newStep = () => setStep((prev) => prev + 1); - const handleSubmit = () => { + const handleSubmit = async () => { const isChanged = JSON.stringify(prevData) !== JSON.stringify(data); + // پاک کردن error های قبلی + setErrors({}); + if (isChanged) { setLoading(true); - let newData = data; - const { basic_insurance, name, national_code, uuid } = newData; + const { basic_insurance, supplementary_insurance, name, family, national_code, gender, insurance_id, uuid } = data; - newData = { - basic_insurance: [basic_insurance.value?.id], - ...(prevData.name?.value === data.name.value ? {} : { name: name }), - ...(prevData.national_code?.value - ? {} - : { national_code: national_code }), + const payload = { + name: name?.value, + family: family?.value, + national_code: national_code?.value, + gender: 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] : [], }; - request - .patchUserProfile(newData, uuid) - .then(() => { - setLoading(false); - newStep(); - }) - .catch(() => { - setLoading(false); - }); + try { + if (uuid) { + // اگر uuid داریم، پروفایل وجود داره و باید PATCH کنیم + console.log('📤 ارسال درخواست PATCH - UUID:', uuid, 'Payload:', payload); + await request.patchUserProfile(payload, uuid); + } else { + // اگر uuid نداریم، پروفایل وجود نداره و باید POST کنیم + console.log('📤 ارسال درخواست POST - Payload:', payload); + await request.postUserProfile(payload); + } + console.log('✅ پروفایل با موفقیت ذخیره شد'); + setLoading(false); + newStep(); + } catch (error) { + console.log('❌ خطا در ذخیره پروفایل:', error?.response?.data || error); + setLoading(false); + // اگر خطای validation بود، error ها را ست می‌کنیم + if (error?.response?.data) { + setErrors(error.response.data); + } + } } else { newStep(); } diff --git a/components/appointment/detail/index.js b/components/appointment/detail/index.js index 9751fad..620356f 100644 --- a/components/appointment/detail/index.js +++ b/components/appointment/detail/index.js @@ -18,6 +18,8 @@ function Detail({ }) { const [insurance, setInsurance] = useState(); const [supplementaryInsurance, setSupplementaryInsurance] = useState(); + const [errors, setErrors] = useState({}); + const changeData = (value, type, name) => setData({ ...data, @@ -68,6 +70,7 @@ function Detail({ supplementaryInsurance={supplementaryInsurance} changeData={changeData} isForAnother={isForAnother} + errors={errors} /> {!isForAnother && ( )} - + ); diff --git a/components/appointment/index.js b/components/appointment/index.js index 0dc5df0..4d9ae90 100644 --- a/components/appointment/index.js +++ b/components/appointment/index.js @@ -11,6 +11,7 @@ const defaultData = { name: { value: "", isEdit: true }, family: { value: "", isEdit: true }, gender: { value: "", isEdit: true }, + insurance_id: { value: "", isEdit: true }, basic_insurance: { value: "", isEdit: true }, }; @@ -50,6 +51,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) { // سپس اگر uuid داریم، بقیه اطلاعات را از API می‌گیریم if (userInfo && parsedData) { try { + console.log('📤 درخواست دریافت پروفایل کاربر - UUID:', parsedData.uuid); const res = await request.getUserProfile(parsedData.uuid); if (res) { @@ -63,6 +65,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) { name: { value: res.name || "", isEdit: true }, family: { value: res.family || "", isEdit: true }, gender: { value: res.gender || "", isEdit: true }, + insurance_id: { value: res.insurance_id || "", isEdit: true }, basic_insurance: { value: res.basic_insurance, isEdit: true, @@ -80,6 +83,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) { name: { value: "", isEdit: true }, family: { value: "", isEdit: true }, gender: { value: "", isEdit: true }, + insurance_id: { value: "", isEdit: true }, basic_insurance: { value: "", isEdit: true }, })); } @@ -104,6 +108,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) { if (userInfo && parsedData && !data.uuid) { try { + console.log('📤 درخواست مجدد دریافت پروفایل (step 3) - UUID:', parsedData.uuid); const res = await request.getUserProfile(parsedData.uuid); if (res) { @@ -117,6 +122,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) { name: { value: res.name || "", isEdit: true }, family: { value: res.family || "", isEdit: true }, gender: { value: res.gender || "", isEdit: true }, + insurance_id: { value: res.insurance_id || "", isEdit: true }, basic_insurance: { value: res.basic_insurance, isEdit: true, @@ -134,6 +140,7 @@ function AppointmentPage({ doctor, disabledDates, matchedCity }) { name: { value: "", isEdit: true }, family: { value: "", isEdit: true }, gender: { value: "", isEdit: true }, + insurance_id: { value: "", isEdit: true }, basic_insurance: { value: "", isEdit: true }, })); }