294 lines
9.8 KiB
TypeScript
294 lines
9.8 KiB
TypeScript
"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>
|
||
);
|
||
}
|