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

294 lines
9.8 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.
"use client";
import React from "react";
import {
Box,
FormControlLabel,
IconButton,
Paper,
Switch,
TextField,
Typography,
Button,
} from "@mui/material";
import { DeleteOutlineOutlined, Add } from "@mui/icons-material";
import { FieldArray, Form, getIn, type FormikProps } from "formik";
import type {
WorkExperienceFormProps,
WorkExperienceFormValues,
WorkExperienceFormItem,
} from "./types";
import {
WORK_EXPERIENCE_EMPTY_ITEM,
WORK_EXPERIENCE_NO_EXPERIENCE_ITEM,
} from "./constant";
type Props = FormikProps<WorkExperienceFormValues> & WorkExperienceFormProps;
export default function InnerWorkExperienceForm(props: Props) {
const {
values,
errors,
touched,
setFieldValue,
handleChange,
isSubmitting,
} = props;
const workExperiences = values.workExperiences || [];
const hasNoExperienceMode =
workExperiences.length === 1 && workExperiences[0]?.hasNoExperience;
const handleBack = () => {
props.update({
workExperiences: values.workExperiences,
});
props.setStep(props.step - 1);
};
return (
<Form>
<FieldArray name="workExperiences">
{({ push, remove, replace }) => (
<>
{workExperiences.map((item: WorkExperienceFormItem, index: number) => {
const itemErrors = getIn(errors, `workExperiences.${index}`) || {};
const itemTouched = getIn(touched, `workExperiences.${index}`) || {};
const setHasNoExperience = (checked: boolean) => {
if (checked) {
replace(0, {
...WORK_EXPERIENCE_NO_EXPERIENCE_ITEM,
id: Date.now(),
});
for (let i = workExperiences.length - 1; i >= 1; i--) {
remove(i);
}
} else {
setFieldValue(`workExperiences.${index}.hasNoExperience`, false);
}
};
return (
<Paper
key={item.id || index}
elevation={0}
sx={{
p: { xs: 2, md: 3 },
borderRadius: "24px",
border: "1px solid #e2e8f0",
backgroundColor: "#fff",
mb: 3,
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
mb: 2,
}}
>
<Typography sx={{ fontWeight: 700 }}>
سابقه کاری {index + 1}
</Typography>
<IconButton
onClick={() => remove(index)}
disabled={workExperiences.length === 1 || hasNoExperienceMode}
size="small"
color="error"
>
<DeleteOutlineOutlined />
</IconButton>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: {
xs: "1fr",
md: "repeat(2, 1fr)",
},
gap: 2,
}}
>
<FormControlLabel
sx={{ gridColumn: "1 / -1" }}
control={
<Switch
checked={item.hasNoExperience}
onChange={(e) => setHasNoExperience(e.target.checked)}
/>
}
label="فاقد سابقه کاری هستم"
/>
<TextField
label="نام شرکت"
name={`workExperiences.${index}.companyName`}
value={item.companyName}
onChange={handleChange}
fullWidth
disabled={item.hasNoExperience}
error={!!itemTouched.companyName && !!itemErrors.companyName}
helperText={
itemTouched.companyName ? itemErrors.companyName : ""
}
/>
<TextField
label="آخرین سمت"
name={`workExperiences.${index}.lastPosition`}
value={item.lastPosition}
onChange={handleChange}
fullWidth
disabled={item.hasNoExperience}
error={!!itemTouched.lastPosition && !!itemErrors.lastPosition}
helperText={
itemTouched.lastPosition ? itemErrors.lastPosition : ""
}
/>
<TextField
label="سال شروع"
name={`workExperiences.${index}.startYear`}
value={item.startYear}
onChange={(e) => {
const onlyDigits = e.target.value.replace(/[^\d]/g, "");
setFieldValue(
`workExperiences.${index}.startYear`,
onlyDigits,
);
}}
fullWidth
disabled={item.hasNoExperience}
inputMode="numeric"
error={!!itemTouched.startYear && !!itemErrors.startYear}
helperText={itemTouched.startYear ? itemErrors.startYear : ""}
/>
<TextField
label="سال پایان"
name={`workExperiences.${index}.endYear`}
value={item.endYear}
onChange={(e) => {
const onlyDigits = e.target.value.replace(/[^\d]/g, "");
setFieldValue(
`workExperiences.${index}.endYear`,
onlyDigits,
);
}}
fullWidth
disabled={item.hasNoExperience}
inputMode="numeric"
error={!!itemTouched.endYear && !!itemErrors.endYear}
helperText={itemTouched.endYear ? itemErrors.endYear : ""}
/>
<TextField
label="علت ترک کار"
name={`workExperiences.${index}.leavingReason`}
value={item.leavingReason}
onChange={handleChange}
fullWidth
disabled={item.hasNoExperience}
error={!!itemTouched.leavingReason && !!itemErrors.leavingReason}
helperText={
itemTouched.leavingReason ? itemErrors.leavingReason : ""
}
sx={{ gridColumn: { md: "1 / -1" } }}
/>
<TextField
label="توضیحات"
name={`workExperiences.${index}.description`}
value={item.description}
onChange={handleChange}
fullWidth
disabled={item.hasNoExperience}
multiline
minRows={3}
error={!!itemTouched.description && !!itemErrors.description}
helperText={
itemTouched.description ? itemErrors.description : ""
}
sx={{ gridColumn: { md: "1 / -1" } }}
/>
</Box>
</Paper>
);
})}
{!hasNoExperienceMode && (
<Button
type="button"
variant="outlined"
startIcon={<Add />}
onClick={() =>
push({
...WORK_EXPERIENCE_EMPTY_ITEM,
id: Date.now(),
})
}
sx={{
borderRadius: "12px",
mb: 3,
fontWeight: 700,
}}
>
افزودن سابقه کاری
</Button>
)}
{typeof errors.workExperiences === "string" && (
<Typography color="error" sx={{ mb: 2 }}>
{errors.workExperiences}
</Typography>
)}
<Box
sx={{
display: "flex",
justifyContent: "space-between",
mt: 4,
width: "100%",
}}
>
<Button
disabled={props.step === 1 || isSubmitting}
type="button"
onClick={handleBack}
sx={{
borderRadius: "12px",
color: "#64748b",
fontWeight: 700,
}}
>
بازگشت
</Button>
<Button
variant="contained"
type="submit"
disabled={isSubmitting}
sx={{
borderRadius: "12px",
px: 4,
py: 1.5,
bgcolor: props.step === 12 ? "green" : "#2563eb",
fontWeight: 700,
}}
>
{props.step === 12 ? "اتمام و ثبت نهایی" : "گام بعدی"}
</Button>
</Box>
</>
)}
</FieldArray>
</Form>
);
}