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

249
ui/MultiForm.tsx Normal file
View File

@@ -0,0 +1,249 @@
"use client";
import React, { useState } from "react";
import {
Box,
Button,
Typography,
Paper,
Container,
useTheme,
useMediaQuery,
} from "@mui/material";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import CenterRegistrationForm from "./forms/register-center/RegistrationCenterForm";
import IdentityForm from "./forms/IdentityForm";
import PersonalInfoForm from "./forms/PersonalInfoForm";
import PhysicalInfoForm from "./forms/PhysicalInfoForm";
import EducationForm from "./forms/EducationForm";
import EducationSection from "./forms/EducationSection";
import JobRequestForm from "./forms/JobRequestForm";
import JobRequestSection from "./forms/JobRequestSection";
import CourseSection from "./forms/CourseSection";
import SkillsForm from "./forms/SkillsForm";
import { WorkExperienceSection } from "./forms/WorkExperienceSection";
import JobInfoForm from "./forms/JobInfoForm";
import { ReferralSection } from "./forms/ReferralForm";
import RelationsForm from "./forms/RelationForm";
// کامپوننت پیش‌فرض برای مراحلی که هنوز نساختید
const PlaceholderStep = ({ step }: any) => (
<Typography color="text.secondary">
محتوای مرحله {step} در حال طراحی است...
</Typography>
);
// --- ۲. نگاشت (Mapping) مراحل به کامپوننت‌ها ---
const STEP_COMPONENTS: Record<number, React.FC<any>> = {
1: CenterRegistrationForm,
2: IdentityForm,
3: PersonalInfoForm,
4: PhysicalInfoForm,
5: EducationSection,
6: JobRequestSection,
7: CourseSection,
8: SkillsForm,
9: WorkExperienceSection,
10: JobInfoForm,
11: ReferralSection,
12: RelationsForm,
// بقیه مراحل از Placeholder استفاده می‌کنند
};
const STEP_LABELS = [
"انتخاب مركز",
"مشخصات هويتي",
"مشخصات فردي",
"مشخصات ظاهري",
"مشخصات تحصيلي",
"شغل درخواستي",
"دوره هاي آموزشي",
"مهارت ها",
"سوابق كاري",
"اطلاعات كاري",
"معرف",
"مشخصات آشنايان",
];
// --- ۳. کامپوننت اصلی استپر ---
export default function MultiStepForm() {
const [activeStep, setActiveStep] = useState(1);
const [maxStepReached, setMaxStepReached] = useState(1);
const [formData, setFormData] = useState({
name: "",
address: "",
isUrgent: false,
});
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
const updateFormData = (newData: Partial<typeof formData>) => {
setFormData((prev) => ({ ...prev, ...newData }));
};
const handleNext = () => {
if (activeStep < 12) {
setActiveStep((prev) => prev + 1);
if (activeStep + 1 > maxStepReached) setMaxStepReached(activeStep + 1);
}
};
const ActiveStepComponent = STEP_COMPONENTS[activeStep] || PlaceholderStep;
return (
<Box
sx={{
minHeight: "100vh",
display: "flex",
alignItems: "center",
bgcolor: "#f8fafc",
py: 4,
}}
>
<Container maxWidth="xl">
<div
style={{
display: "flex",
flexDirection: isMobile ? "column" : "row",
gap: "40px",
}}
>
{/* Sidebar Navigation */}
{!isMobile && (
<div style={{ width: "200px", flexShrink: 0 }}>
<Typography
variant="h5"
sx={{ fontWeight: 900, mb: 4, color: "#1e293b" }}
>
پنل ثبت مرکز
</Typography>
{STEP_LABELS.map((label, i) => (
<Box
key={i}
onClick={() =>
i + 1 <= maxStepReached && setActiveStep(i + 1)
}
sx={{
display: "flex",
alignItems: "center",
mb: 2,
cursor: i + 1 <= maxStepReached ? "pointer" : "not-allowed",
opacity: i + 1 <= maxStepReached ? 1 : 0.4,
color: i + 1 === activeStep ? "#2563eb" : "#64748b",
transition: "0.2s",
}}
>
<Box
sx={{
width: 32,
height: 32,
borderRadius: "10px",
mr: 2,
display: "flex",
alignItems: "center",
justifyContent: "center",
bgcolor:
i + 1 === activeStep
? "#2563eb"
: i + 1 < activeStep
? "#4CAF5033"
: "#f1f5f9",
color: i + 1 === activeStep ? "#fff" : "#2563eb",
fontWeight: 700,
fontSize: "0.8rem",
border:
i + 1 === activeStep ? "none" : "1px solid #e2e8f0",
}}
>
{i + 1 < activeStep ? (
<CheckCircleIcon sx={{ fontSize: 18 }} color="success" />
) : (
i + 1
)}
</Box>
<Typography
variant="body2"
sx={{
fontWeight: i + 1 === activeStep ? 800 : 500,
color: i + 1 < activeStep ? "green" : "",
}}
>
{label}
</Typography>
</Box>
))}
</div>
)}
{/* Main Form Area */}
<div style={{ flexGrow: 1 }}>
<Paper
sx={{
p: { xs: 3, md: 6 },
borderRadius: "35px",
boxShadow: "0 25px 50px -12px rgba(0,0,0,0.05)",
border: "1px solid #e2e8f0",
}}
>
<Box sx={{ mb: 4 }}>
<Typography
variant="overline"
sx={{ color: "#2563eb", fontWeight: 900 }}
>
مرحله {activeStep.toLocaleString("fa-IR")} از{" "}
{STEP_LABELS.length.toLocaleString("fa-IR")}
</Typography>
<Typography
variant="h4"
sx={{ fontWeight: 900, color: "#0f172a" }}
>
{STEP_LABELS[activeStep - 1]}
</Typography>
</Box>
{/* رندر شدن داینامیک کامپوننت مرحله فعلی */}
<div className="w-full">
<ActiveStepComponent
data={formData}
update={updateFormData}
step={activeStep}
/>
</div>
<Box
sx={{ display: "flex", justifyContent: "space-between", mt: 5 }}
>
<Button
disabled={activeStep === 1}
onClick={() => setActiveStep((prev) => prev - 1)}
sx={{
borderRadius: "12px",
color: "#64748b",
fontWeight: 700,
}}
>
بازگشت
</Button>
<Button
variant="contained"
onClick={handleNext}
sx={{
borderRadius: "12px",
px: 4,
py: 1.5,
bgcolor: `${activeStep === 12 ? "green" : "#2563eb"}`,
fontWeight: 700,
}}
>
{activeStep === 12 ? "اتمام و ثبت نهايي" : "گام بعدی"}
</Button>
</Box>
</Paper>
</div>
</div>
</Container>
</Box>
);
}