327 lines
11 KiB
TypeScript
327 lines
11 KiB
TypeScript
// InnerPersonalInfoForm.tsx
|
||
"use client";
|
||
|
||
import React from "react";
|
||
import { Box, Button, MenuItem, TextField } from "@mui/material";
|
||
import { Form, type FormikProps } from "formik";
|
||
import { MilitaryStatus, PersonalInfoFormValues } from "./types";
|
||
import {
|
||
EDUCATION_OPTIONS,
|
||
HOUSING_OPTIONS,
|
||
MILITARY_OPTIONS,
|
||
} from "./constants";
|
||
import { PersonalInfoFormProps } from "./PersonalInfoForm";
|
||
import { handleBack } from "@/core/utils";
|
||
|
||
type Props = FormikProps<PersonalInfoFormValues> & PersonalInfoFormProps;
|
||
|
||
export default function InnerPersonalInfoForm(props: Props) {
|
||
const { values, errors, touched, setFieldValue, handleChange } = props;
|
||
|
||
const showSpouseFields = values.maritalStatus === "متاهل";
|
||
const showChildrenCount = ["متاهل", "متارکه", "فوت همسر"].includes(
|
||
values.maritalStatus,
|
||
);
|
||
const isPermanentExempt = values.militaryStatus === "معافیت دائم";
|
||
|
||
const handleMaritalStatusChange = (
|
||
e: React.ChangeEvent<HTMLInputElement>,
|
||
) => {
|
||
const status = e.target.value;
|
||
|
||
setFieldValue("maritalStatus", status);
|
||
|
||
// پاکسازی شرطیها
|
||
const isMarried = status === "متاهل";
|
||
const hasChildren = ["متاهل", "متارکه", "فوت همسر"].includes(status);
|
||
|
||
if (!isMarried) {
|
||
setFieldValue("spouseName", "");
|
||
setFieldValue("spouseEducation", "");
|
||
setFieldValue("spouseJob", "");
|
||
setFieldValue("spouseWorkplace", "");
|
||
}
|
||
if (!hasChildren) {
|
||
setFieldValue("childrenCount", "");
|
||
}
|
||
};
|
||
|
||
const handleMilitaryStatusChange = (
|
||
e: React.ChangeEvent<HTMLInputElement>,
|
||
) => {
|
||
const ms = e.target.value as MilitaryStatus;
|
||
setFieldValue("militaryStatus", ms);
|
||
|
||
if (ms !== "معافیت دائم") {
|
||
setFieldValue("permanentExemptionReason", "");
|
||
}
|
||
};
|
||
|
||
const tf = <K extends keyof PersonalInfoFormValues>(name: K) => ({
|
||
name: String(name),
|
||
value: values[name] as any,
|
||
onChange: handleChange,
|
||
fullWidth: true,
|
||
error: !!(touched as any)[name] && !!(errors as any)[name],
|
||
helperText: (touched as any)[name] ? ((errors as any)[name] as string) : "",
|
||
});
|
||
|
||
return (
|
||
<Form>
|
||
<Box
|
||
sx={{
|
||
display: "grid",
|
||
gridTemplateColumns: { xs: "1fr", md: "repeat(2, 1fr)" },
|
||
gap: 2,
|
||
}}
|
||
>
|
||
{/* وضعیت تاهل */}
|
||
<TextField
|
||
select
|
||
label="وضعیت تاهل"
|
||
name="maritalStatus"
|
||
value={values.maritalStatus}
|
||
onChange={handleMaritalStatusChange}
|
||
fullWidth
|
||
error={!!touched.maritalStatus && !!errors.maritalStatus}
|
||
helperText={
|
||
touched.maritalStatus ? (errors.maritalStatus as string) : ""
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب کنید</MenuItem>
|
||
<MenuItem value="مجرد">مجرد</MenuItem>
|
||
<MenuItem value="متاهل">متاهل</MenuItem>
|
||
<MenuItem value="متارکه">متارکه</MenuItem>
|
||
<MenuItem value="فوت همسر">فوت همسر</MenuItem>
|
||
</TextField>
|
||
{/* همسر (شرطی) */}
|
||
{showSpouseFields && (
|
||
<>
|
||
<TextField label="نام و نام خانوادگی همسر" {...tf("spouseName")} />
|
||
<TextField label="تحصیلات همسر" {...tf("spouseEducation")} />
|
||
<TextField label="شغل همسر" {...tf("spouseJob")} />
|
||
<TextField label="محل کار همسر" {...tf("spouseWorkplace")} />
|
||
</>
|
||
)}
|
||
{/* تعداد فرزند (شرطی) */}
|
||
{showChildrenCount && (
|
||
<TextField
|
||
label="تعداد فرزند"
|
||
name="childrenCount"
|
||
type="number"
|
||
value={values.childrenCount}
|
||
onChange={(e) =>
|
||
setFieldValue(
|
||
"childrenCount",
|
||
e.target.value === "" ? "" : Number(e.target.value),
|
||
)
|
||
}
|
||
fullWidth
|
||
error={!!touched.childrenCount && !!errors.childrenCount}
|
||
helperText={
|
||
touched.childrenCount ? (errors.childrenCount as string) : ""
|
||
}
|
||
/>
|
||
)}
|
||
{/* وضعیت نظام وظیفه */}
|
||
<TextField
|
||
select
|
||
label="وضعیت نظام وظیفه"
|
||
name="militaryStatus"
|
||
value={values.militaryStatus}
|
||
onChange={handleMilitaryStatusChange}
|
||
fullWidth
|
||
error={!!touched.militaryStatus && !!errors.militaryStatus}
|
||
helperText={
|
||
touched.militaryStatus ? (errors.militaryStatus as string) : ""
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب کنید</MenuItem>
|
||
{MILITARY_OPTIONS.map((opt) => (
|
||
<MenuItem key={opt} value={opt}>
|
||
{opt}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
{/* علت معافیت دائم */}
|
||
{isPermanentExempt && (
|
||
<TextField
|
||
label="علت معافیت دائم"
|
||
{...tf("permanentExemptionReason")}
|
||
/>
|
||
)}
|
||
{/* تحصیلات پدر/مادر */}
|
||
<TextField
|
||
select
|
||
label="تحصیلات پدر"
|
||
name="fatherEducation"
|
||
value={values.fatherEducation}
|
||
onChange={handleChange}
|
||
fullWidth
|
||
error={!!touched.fatherEducation && !!errors.fatherEducation}
|
||
helperText={
|
||
touched.fatherEducation ? (errors.fatherEducation as string) : ""
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب کنید</MenuItem>
|
||
{EDUCATION_OPTIONS.map((opt) => (
|
||
<MenuItem key={opt} value={opt}>
|
||
{opt}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
<TextField label="شغل پدر" {...tf("fatherJob")} />
|
||
<TextField
|
||
select
|
||
label="تحصیلات مادر"
|
||
name="motherEducation"
|
||
value={values.motherEducation}
|
||
onChange={handleChange}
|
||
fullWidth
|
||
error={!!touched.motherEducation && !!errors.motherEducation}
|
||
helperText={
|
||
touched.motherEducation ? (errors.motherEducation as string) : ""
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب کنید</MenuItem>
|
||
{EDUCATION_OPTIONS.map((opt) => (
|
||
<MenuItem key={opt} value={opt}>
|
||
{opt}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
<TextField label="شغل مادر" {...tf("motherJob")} />
|
||
{/* وضعیت مسکن / شهر / آدرس */}
|
||
<TextField
|
||
select
|
||
label="وضعیت مسکن"
|
||
name="housingStatus"
|
||
value={values.housingStatus}
|
||
onChange={handleChange}
|
||
fullWidth
|
||
error={!!touched.housingStatus && !!errors.housingStatus}
|
||
helperText={
|
||
touched.housingStatus ? (errors.housingStatus as string) : ""
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب کنید</MenuItem>
|
||
{HOUSING_OPTIONS.map((opt) => (
|
||
<MenuItem key={opt} value={opt}>
|
||
{opt}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>{" "}
|
||
<TextField label="شهر" {...tf("city")} />
|
||
<Box sx={{ gridColumn: { md: "span 2" } }}>
|
||
<TextField label="آدرس" {...tf("address")} multiline minRows={2} />
|
||
</Box>
|
||
{/* تلفنها */}
|
||
<TextField label="تلفن منزل" {...tf("homePhone")} />
|
||
<TextField label="تلفن همراه" {...tf("mobilePhone")} />
|
||
<TextField label="تلفن ضروری" {...tf("emergencyPhone")} />
|
||
<TextField label="ایمیل" {...tf("email")} />
|
||
{/* مدت سکونت */}
|
||
<TextField
|
||
label="مدت سکونت (سال)"
|
||
name="residenceDuration"
|
||
type="number"
|
||
value={values.residenceDuration}
|
||
onChange={(e) =>
|
||
setFieldValue(
|
||
"residenceDuration",
|
||
e.target.value === "" ? "" : Number(e.target.value),
|
||
)
|
||
}
|
||
fullWidth
|
||
error={!!touched.residenceDuration && !!errors.residenceDuration}
|
||
helperText={
|
||
touched.residenceDuration
|
||
? (errors.residenceDuration as string)
|
||
: ""
|
||
}
|
||
/>
|
||
{/* ایثارگر */}
|
||
<TextField
|
||
select
|
||
label="ایثارگر"
|
||
name="isVeteran"
|
||
value={String(values.isVeteran)}
|
||
onChange={(e) =>
|
||
setFieldValue("isVeteran", e.target.value === "true")
|
||
}
|
||
fullWidth
|
||
error={!!touched.isVeteran && !!errors.isVeteran}
|
||
helperText={touched.isVeteran ? (errors.isVeteran as string) : ""}
|
||
>
|
||
<MenuItem value="false">خیر</MenuItem>
|
||
<MenuItem value="true">بله</MenuItem>
|
||
</TextField>
|
||
{/* سوءپیشینه */}
|
||
<TextField
|
||
select
|
||
label="سابقه کیفری"
|
||
name="hasCriminalRecord"
|
||
value={String(values.hasCriminalRecord)}
|
||
onChange={(e) => {
|
||
const next = e.target.value === "true";
|
||
setFieldValue("hasCriminalRecord", next);
|
||
if (!next) setFieldValue("criminalDescription", "");
|
||
}}
|
||
fullWidth
|
||
error={!!touched.hasCriminalRecord && !!errors.hasCriminalRecord}
|
||
helperText={
|
||
touched.hasCriminalRecord
|
||
? (errors.hasCriminalRecord as string)
|
||
: ""
|
||
}
|
||
>
|
||
<MenuItem value="false">خیر</MenuItem>
|
||
<MenuItem value="true">بله</MenuItem>
|
||
</TextField>
|
||
{values.hasCriminalRecord && (
|
||
<TextField
|
||
label="توضیحات سوء پیشینه"
|
||
{...tf("criminalDescription")}
|
||
/>
|
||
)}
|
||
|
||
</Box>
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
justifyContent: "space-between",
|
||
mt: 5,
|
||
width: "100%",
|
||
}}
|
||
>
|
||
<Button
|
||
disabled={props.step === 1}
|
||
type="button"
|
||
onClick={() => handleBack(props, "personalInfo")}
|
||
sx={{
|
||
borderRadius: "12px",
|
||
color: "#64748b",
|
||
fontWeight: 700,
|
||
}}
|
||
>
|
||
بازگشت
|
||
</Button>
|
||
<Button
|
||
variant="contained"
|
||
type="submit"
|
||
sx={{
|
||
borderRadius: "12px",
|
||
px: 4,
|
||
py: 1.5,
|
||
bgcolor: `${props.step === 12 ? "green" : "#2563eb"}`,
|
||
fontWeight: 700,
|
||
}}
|
||
>
|
||
{props.step === 12 ? "اتمام و ثبت نهايي" : "گام بعدی"}
|
||
</Button>
|
||
</Box>
|
||
|
||
</Form>
|
||
);
|
||
}
|