first commit

This commit is contained in:
2026-05-31 14:22:39 +03:30
commit 98af7d639b
54 changed files with 11545 additions and 0 deletions

263
ui/forms/JobRequestForm.tsx Normal file
View File

@@ -0,0 +1,263 @@
import React, { useMemo, useState } from "react";
import {
Box,
MenuItem,
Paper,
TextField,
Typography,
InputAdornment,
} from "@mui/material";
type JobCategoryOption = {
id: string;
name: string;
};
type JobOption = {
id: string;
title: string;
jobCategoryId: string;
};
interface JobRequestFormData {
jobCategoryId: string;
jobId: string;
requestedJobDescription: string;
employmentRelationType: string;
description: string;
requestedShiftType: string;
expectedSalary: string;
}
interface JobRequestFormProps {
jobCategories?: JobCategoryOption[];
jobs?: JobOption[];
value?: JobRequestFormData;
onChange?: (data: JobRequestFormData) => void;
}
const relationTypes = [
"تمام وقت",
"پاره وقت",
"پروژه‌ای",
"ساعتی",
"قراردادی",
"کارورزی",
];
const shiftTypes = [
"ثابت صبح",
"ثابت عصر",
"ثابت شب",
"چرخشی",
"شیفتی",
"فرقی ندارد",
];
const defaultCategories: JobCategoryOption[] = [
{ id: "1", name: "پاراکلینیک" },
{ id: "2", name: "اداری" },
{ id: "3", name: "درمانی" },
];
const defaultJobs: JobOption[] = [
{ id: "1", title: "کارشناس آزمایشگاه", jobCategoryId: "1" },
{ id: "2", title: "کارشناس رادیولوژی", jobCategoryId: "1" },
{ id: "3", title: "منشی", jobCategoryId: "2" },
{ id: "4", title: "مسئول بایگانی", jobCategoryId: "2" },
{ id: "5", title: "پرستار", jobCategoryId: "3" },
{ id: "6", title: "کمک پرستار", jobCategoryId: "3" },
];
const initialValues: JobRequestFormData = {
jobCategoryId: "",
jobId: "",
requestedJobDescription: "",
employmentRelationType: "",
description: "",
requestedShiftType: "",
expectedSalary: "",
};
export default function JobRequestForm({
jobCategories = defaultCategories,
jobs = defaultJobs,
value,
onChange,
}: JobRequestFormProps) {
const [formData, setFormData] = useState<JobRequestFormData>(
value ?? initialValues,
);
const [errors, setErrors] = useState<Record<string, string>>({});
const filteredJobs = useMemo(() => {
if (!formData.jobCategoryId) return [];
return jobs.filter((job) => job.jobCategoryId === formData.jobCategoryId);
}, [jobs, formData.jobCategoryId]);
const updateForm = (next: JobRequestFormData) => {
setFormData(next);
onChange?.(next);
};
const handleChange =
(field: keyof JobRequestFormData) =>
(event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
let next = { ...formData, [field]: value };
// اگر رسته شغلی عوض شد، شغل قبلی پاک شود
if (field === "jobCategoryId") {
next.jobId = "";
}
// فقط عدد برای حقوق
if (field === "expectedSalary") {
next.expectedSalary = value.replace(/[^\d]/g, "");
}
updateForm(next);
setErrors((prev) => ({
...prev,
[field]: "",
}));
};
const validate = () => {
const newErrors: Record<string, string> = {};
if (!formData.jobCategoryId) {
newErrors.jobCategoryId = "یک گزینه را انتخاب کنید!";
}
if (!formData.jobId) {
newErrors.jobId = "یک گزینه را انتخاب کنید!";
}
if (!formData.employmentRelationType) {
newErrors.employmentRelationType = "یک گزینه را انتخاب کنید!";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
// اگر خواستی بعداً برای submit استفاده کن
// const handleSubmit = () => {
// if (!validate()) return;
// console.log(formData);
// };
return (
<Paper
elevation={0}
sx={{
borderRadius: "32px",
backgroundColor: "#ffffff",
}}
>
<Box
sx={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(340px, 1fr))",
gap: 2,
}}
>
<TextField
select
fullWidth
label="رسته شغلی*"
value={formData.jobCategoryId}
onChange={handleChange("jobCategoryId")}
error={!!errors.jobCategoryId}
helperText={errors.jobCategoryId || " "}
>
<MenuItem value="">انتخاب...</MenuItem>
{jobCategories.map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.name}
</MenuItem>
))}
</TextField>
<TextField
select
fullWidth
label="شغل درخواستی*"
value={formData.jobId}
onChange={handleChange("jobId")}
error={!!errors.jobId}
helperText={errors.jobId || " "}
disabled={!formData.jobCategoryId}
>
<MenuItem value="">انتخاب...</MenuItem>
{filteredJobs.map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.title}
</MenuItem>
))}
</TextField>
<TextField
fullWidth
label="توضیحات شغل درخواست"
value={formData.requestedJobDescription}
onChange={handleChange("requestedJobDescription")}
/>
<TextField
select
fullWidth
label="نوع رابطه کاری*"
value={formData.employmentRelationType}
onChange={handleChange("employmentRelationType")}
error={!!errors.employmentRelationType}
helperText={errors.employmentRelationType || " "}
>
<MenuItem value="">انتخاب ...</MenuItem>
{relationTypes.map((item) => (
<MenuItem key={item} value={item}>
{item}
</MenuItem>
))}
</TextField>
<TextField
fullWidth
label="نوع شیفت درخواستی"
value={formData.requestedShiftType}
onChange={handleChange("requestedShiftType")}
/>
<TextField
fullWidth
label="حقوق درخواستی(ریال)"
value={formData.expectedSalary}
onChange={handleChange("expectedSalary")}
/>
<Box sx={{ gridColumn: { xs: "1", md: "1 / -1" } }}>
<TextField
fullWidth
label="توضیحات"
value={formData.description}
onChange={handleChange("description")}
multiline
minRows={3}
/>
</Box>
</Box>
</Paper>
);
}