335 lines
11 KiB
TypeScript
335 lines
11 KiB
TypeScript
"use client";
|
||
|
||
import React from "react";
|
||
import {
|
||
Box,
|
||
MenuItem,
|
||
TextField,
|
||
Typography,
|
||
Button,
|
||
IconButton,
|
||
Paper,
|
||
} from "@mui/material";
|
||
import DeleteOutlineOutlinedIcon from "@mui/icons-material/DeleteOutlineOutlined";
|
||
import AddIcon from "@mui/icons-material/Add";
|
||
import { FieldArray, Form, getIn, type FormikProps } from "formik";
|
||
|
||
import type {
|
||
JobRequestFormProps,
|
||
JobRequestFormValues,
|
||
JobRequestItem,
|
||
} from "./types";
|
||
import {
|
||
JOB_REQUEST_EMPTY_ITEM,
|
||
defaultCategories,
|
||
defaultJobs,
|
||
relationTypes,
|
||
shiftTypes,
|
||
} from "./constant";
|
||
|
||
type Props = FormikProps<JobRequestFormValues> & JobRequestFormProps;
|
||
|
||
export default function InnerJobRequestForm(props: Props) {
|
||
const {
|
||
values,
|
||
errors,
|
||
touched,
|
||
handleChange,
|
||
setFieldValue,
|
||
jobCategories = defaultCategories,
|
||
jobs = defaultJobs,
|
||
isSubmitting,
|
||
} = props;
|
||
|
||
const handleBack = () => {
|
||
props.update({
|
||
jobRequests: props.values.jobRequests,
|
||
});
|
||
props.setStep(props.step - 1);
|
||
};
|
||
|
||
return (
|
||
<Form>
|
||
<FieldArray name="jobRequests">
|
||
{({ push, remove }) => (
|
||
<>
|
||
{values.jobRequests.map((item: JobRequestItem, index: number) => {
|
||
const itemErrors = getIn(errors, `jobRequests.${index}`) || {};
|
||
const itemTouched = getIn(touched, `jobRequests.${index}`) || {};
|
||
|
||
const filteredJobs = jobs.filter(
|
||
(job) => job.jobCategoryId === item.jobCategoryId,
|
||
);
|
||
|
||
return (
|
||
<Paper
|
||
key={item.id || index}
|
||
elevation={0}
|
||
sx={{
|
||
borderRadius: "24px",
|
||
backgroundColor: "#ffffff",
|
||
border: "1px solid #e2e8f0",
|
||
p: 3,
|
||
mb: 3,
|
||
position: "relative",
|
||
}}
|
||
>
|
||
{values.jobRequests.length > 1 && (
|
||
<IconButton
|
||
onClick={() => remove(index)}
|
||
color="error"
|
||
sx={{
|
||
position: "absolute",
|
||
top: 12,
|
||
right: 12,
|
||
zIndex: 1,
|
||
}}
|
||
aria-label="remove-job-request"
|
||
>
|
||
<DeleteOutlineOutlinedIcon />
|
||
</IconButton>
|
||
)}
|
||
|
||
<Typography
|
||
sx={{
|
||
fontWeight: 700,
|
||
mb: 3,
|
||
color: "#0f172a",
|
||
}}
|
||
>
|
||
درخواست شغلی {index + 1}
|
||
</Typography>
|
||
|
||
<Box
|
||
sx={{
|
||
display: "grid",
|
||
gridTemplateColumns:
|
||
"repeat(auto-fit, minmax(340px, 1fr))",
|
||
gap: 2,
|
||
}}
|
||
>
|
||
<TextField
|
||
select
|
||
fullWidth
|
||
label="رسته شغلی*"
|
||
name={`jobRequests.${index}.jobCategoryId`}
|
||
value={item.jobCategoryId}
|
||
onChange={(e) => {
|
||
const categoryId = e.target.value;
|
||
setFieldValue(
|
||
`jobRequests.${index}.jobCategoryId`,
|
||
categoryId,
|
||
);
|
||
setFieldValue(`jobRequests.${index}.jobId`, "");
|
||
}}
|
||
error={
|
||
!!itemTouched.jobCategoryId &&
|
||
!!itemErrors.jobCategoryId
|
||
}
|
||
helperText={
|
||
itemTouched.jobCategoryId
|
||
? itemErrors.jobCategoryId
|
||
: " "
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب...</MenuItem>
|
||
{jobCategories.map((category) => (
|
||
<MenuItem key={category.id} value={category.id}>
|
||
{category.name}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
|
||
<TextField
|
||
select
|
||
fullWidth
|
||
label="شغل درخواستی*"
|
||
name={`jobRequests.${index}.jobId`}
|
||
value={item.jobId}
|
||
onChange={handleChange}
|
||
error={!!itemTouched.jobId && !!itemErrors.jobId}
|
||
helperText={itemTouched.jobId ? itemErrors.jobId : " "}
|
||
disabled={!item.jobCategoryId}
|
||
>
|
||
<MenuItem value="">انتخاب...</MenuItem>
|
||
{filteredJobs.map((job) => (
|
||
<MenuItem key={job.id} value={job.id}>
|
||
{job.title}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
|
||
<TextField
|
||
fullWidth
|
||
label="توضیحات شغل درخواست"
|
||
name={`jobRequests.${index}.requestedJobDescription`}
|
||
value={item.requestedJobDescription}
|
||
onChange={handleChange}
|
||
error={
|
||
!!itemTouched.requestedJobDescription &&
|
||
!!itemErrors.requestedJobDescription
|
||
}
|
||
helperText={
|
||
itemTouched.requestedJobDescription
|
||
? itemErrors.requestedJobDescription
|
||
: ""
|
||
}
|
||
/>
|
||
|
||
<TextField
|
||
select
|
||
fullWidth
|
||
label="نوع رابطه کاری*"
|
||
name={`jobRequests.${index}.employmentRelationType`}
|
||
value={item.employmentRelationType}
|
||
onChange={handleChange}
|
||
error={
|
||
!!itemTouched.employmentRelationType &&
|
||
!!itemErrors.employmentRelationType
|
||
}
|
||
helperText={
|
||
itemTouched.employmentRelationType
|
||
? itemErrors.employmentRelationType
|
||
: " "
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب...</MenuItem>
|
||
{relationTypes.map((relation) => (
|
||
<MenuItem key={relation} value={relation}>
|
||
{relation}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
|
||
<TextField
|
||
select
|
||
fullWidth
|
||
label="نوع شیفت درخواستی"
|
||
name={`jobRequests.${index}.requestedShiftType`}
|
||
value={item.requestedShiftType}
|
||
onChange={handleChange}
|
||
error={
|
||
!!itemTouched.requestedShiftType &&
|
||
!!itemErrors.requestedShiftType
|
||
}
|
||
helperText={
|
||
itemTouched.requestedShiftType
|
||
? itemErrors.requestedShiftType
|
||
: ""
|
||
}
|
||
>
|
||
<MenuItem value="">انتخاب...</MenuItem>
|
||
{shiftTypes.map((shift) => (
|
||
<MenuItem key={shift} value={shift}>
|
||
{shift}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
|
||
<TextField
|
||
fullWidth
|
||
label="حقوق درخواستی (ریال)"
|
||
name={`jobRequests.${index}.expectedSalary`}
|
||
value={item.expectedSalary}
|
||
onChange={(e) => {
|
||
const onlyDigits = e.target.value.replace(/[^\d]/g, "");
|
||
setFieldValue(
|
||
`jobRequests.${index}.expectedSalary`,
|
||
onlyDigits,
|
||
);
|
||
}}
|
||
error={
|
||
!!itemTouched.expectedSalary &&
|
||
!!itemErrors.expectedSalary
|
||
}
|
||
helperText={
|
||
itemTouched.expectedSalary
|
||
? itemErrors.expectedSalary
|
||
: ""
|
||
}
|
||
/>
|
||
|
||
<Box sx={{ gridColumn: { xs: "1", md: "1 / -1" } }}>
|
||
<TextField
|
||
fullWidth
|
||
label="توضیحات"
|
||
name={`jobRequests.${index}.description`}
|
||
value={item.description}
|
||
onChange={handleChange}
|
||
multiline
|
||
minRows={3}
|
||
error={
|
||
!!itemTouched.description && !!itemErrors.description
|
||
}
|
||
helperText={
|
||
itemTouched.description ? itemErrors.description : ""
|
||
}
|
||
/>
|
||
</Box>
|
||
</Box>
|
||
</Paper>
|
||
);
|
||
})}
|
||
|
||
<Button
|
||
type="button"
|
||
variant="outlined"
|
||
startIcon={<AddIcon />}
|
||
onClick={() =>
|
||
push({
|
||
...JOB_REQUEST_EMPTY_ITEM,
|
||
id: Date.now(),
|
||
})
|
||
}
|
||
sx={{
|
||
borderRadius: "12px",
|
||
mb: 3,
|
||
fontWeight: 700,
|
||
}}
|
||
>
|
||
افزودن درخواست شغلی
|
||
</Button>
|
||
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
justifyContent: "space-between",
|
||
mt: 5,
|
||
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>
|
||
);
|
||
}
|