Files
hounam-submit-form-frontend/ui/forms/physicalInfo/InnerPhysicalInfoForm.tsx
2026-06-02 17:08:52 +03:30

298 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// InnerPhysicalInfoForm.tsx
"use client";
import React, { useEffect, useMemo } from "react";
import { Box, Button, MenuItem, TextField } from "@mui/material";
import { Form, type FormikProps } from "formik";
import { PhysicalInfoFormValues } from "./types";
import { PhysicalInfoFormProps } from "./PhysicalInfoForm";
import { BLOOD_TYPE_OPTIONS } from "./constants";
import { handleBack } from "@/core/utils";
type Props = FormikProps<PhysicalInfoFormValues> & PhysicalInfoFormProps;
function round1(n: number) {
return Math.round(n * 10) / 10;
}
export default function InnerPhysicalInfoForm(props: Props) {
const { values, errors, touched, setFieldValue, handleChange } = props;
const computedBmi = useMemo(() => {
if (values.height === "" || values.weight === "") return "";
const hMeters = Number(values.height) / 100;
if (!hMeters || hMeters <= 0) return "";
const bmi = Number(values.weight) / (hMeters * hMeters);
return Number.isFinite(bmi) ? round1(bmi) : "";
}, [values.height, values.weight]);
useEffect(() => {
if (values.bmi !== computedBmi) {
setFieldValue("bmi", computedBmi, false);
}
}, [computedBmi, setFieldValue, values.bmi]);
const tf = <K extends keyof PhysicalInfoFormValues>(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) : "",
});
console.log(props.errors)
return (
<Form>
<Box
sx={{
display: "grid",
gridTemplateColumns: { xs: "1fr", md: "repeat(2, 1fr)" },
gap: 2,
width: "100%",
}}
>
{/* bloodType */}
<TextField
select
label="گروه خونی"
name="bloodType"
value={values.bloodType}
onChange={handleChange}
fullWidth
error={!!touched.bloodType && !!errors.bloodType}
helperText={touched.bloodType ? (errors.bloodType as string) : ""}
>
<MenuItem value="">انتخاب کنید</MenuItem>
{BLOOD_TYPE_OPTIONS.map((bt) => (
<MenuItem key={bt} value={bt}>
{bt}
</MenuItem>
))}
</TextField>
{/* height */}
<TextField
label="قد (سانتی‌متر)"
name="height"
type="number"
value={values.height}
onChange={(e) =>
setFieldValue(
"height",
e.target.value === "" ? "" : Number(e.target.value),
)
}
fullWidth
error={!!touched.height && !!errors.height}
helperText={touched.height ? (errors.height as string) : ""}
/>
{/* weight */}
<TextField
label="وزن (کیلوگرم)"
name="weight"
type="number"
value={values.weight}
onChange={(e) =>
setFieldValue(
"weight",
e.target.value === "" ? "" : Number(e.target.value),
)
}
fullWidth
error={!!touched.weight && !!errors.weight}
helperText={touched.weight ? (errors.weight as string) : ""}
/>
{/* bmi */}
<TextField
label="BMI"
name="bmi"
type="number"
value={values.bmi}
fullWidth
disabled
error={!!touched.bmi && !!errors.bmi}
helperText={
touched.bmi && errors.bmi
? (errors.bmi as string)
: values.height !== "" && values.weight !== ""
? "به‌صورت خودکار از قد و وزن محاسبه می‌شود"
: "برای محاسبه BMI، قد و وزن را وارد کنید"
}
/>
{/* specialMark */}
<TextField label="علامت مشخصه" {...tf("specialMark")} />
{/* hasDisability */}
<TextField
select
label="معلولیت دارد؟"
name="hasDisability"
value={String(values.hasDisability)}
onChange={(e) => {
const next = e.target.value === "true";
setFieldValue("hasDisability", next);
if (!next) {
setFieldValue("disabilityDescription", "");
}
}}
fullWidth
error={!!touched.hasDisability && !!errors.hasDisability}
helperText={
touched.hasDisability ? (errors.hasDisability as string) : ""
}
>
<MenuItem value="false">خیر</MenuItem>
<MenuItem value="true">بله</MenuItem>
</TextField>
{/* hasChronicDisease */}
<TextField
select
label="بیماری مزمن دارد؟"
name="hasChronicDisease"
value={String(values.hasChronicDisease)}
onChange={(e) => {
const next = e.target.value === "true";
setFieldValue("hasChronicDisease", next);
if (!next) {
setFieldValue("chronicDiseaseDescription", "");
}
}}
fullWidth
error={!!touched.hasChronicDisease && !!errors.hasChronicDisease}
helperText={
touched.hasChronicDisease
? (errors.hasChronicDisease as string)
: ""
}
>
<MenuItem value="false">خیر</MenuItem>
<MenuItem value="true">بله</MenuItem>
</TextField>
{/* disabilityDescription */}
{values.hasDisability && (
<Box sx={{ gridColumn: { xs: "1", md: "1 / -1" } }}>
<TextField
label="توضیحات معلولیت"
name="disabilityDescription"
value={values.disabilityDescription}
onChange={handleChange}
fullWidth
multiline
minRows={2}
error={
!!touched.disabilityDescription &&
!!errors.disabilityDescription
}
helperText={
touched.disabilityDescription
? (errors.disabilityDescription as string)
: ""
}
/>
</Box>
)}
{/* chronicDiseaseDescription */}
{values.hasChronicDisease && (
<Box sx={{ gridColumn: { xs: "1", md: "1 / -1" } }}>
<TextField
label="توضیحات بیماری مزمن"
name="chronicDiseaseDescription"
value={values.chronicDiseaseDescription}
onChange={handleChange}
fullWidth
multiline
minRows={2}
error={
!!touched.chronicDiseaseDescription &&
!!errors.chronicDiseaseDescription
}
helperText={
touched.chronicDiseaseDescription
? (errors.chronicDiseaseDescription as string)
: ""
}
/>
</Box>
)}
{/* surgeryHistory */}
<Box sx={{ gridColumn: { xs: "1", md: "1 / -1" } }}>
<TextField
label="سابقه جراحی"
name="surgeryHistory"
value={values.surgeryHistory}
onChange={handleChange}
fullWidth
multiline
minRows={2}
error={!!touched.surgeryHistory && !!errors.surgeryHistory}
helperText={
touched.surgeryHistory ? (errors.surgeryHistory as string) : ""
}
/>
</Box>
{/* medications */}
<Box sx={{ gridColumn: { xs: "1", md: "1 / -1" } }}>
<TextField
label="داروهای مصرفی"
name="medications"
value={values.medications}
onChange={handleChange}
fullWidth
multiline
minRows={2}
error={!!touched.medications && !!errors.medications}
helperText={
touched.medications ? (errors.medications as string) : ""
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
mt: 5,
width: "100%",
}}
>
<Button
disabled={props.step === 1}
type="button"
onClick={() => handleBack(props,"physicalInfo")}
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>
);
}