"use client"; import React, { useRef, useState } from "react"; import axios from "axios"; import { Box, Button, LinearProgress, MenuItem, TextField, Typography, IconButton, Divider, } from "@mui/material"; import { UploadFile, Add, DeleteOutlineOutlined } from "@mui/icons-material"; import { FieldArray, Form, type FormikProps, getIn } from "formik"; import { DEGREE_OPTIONS } from "./constants"; import { EducationFormProps } from "./EducationForm"; export interface EducationItem { degree: string; field: string; university: string; startYear: number | ""; endYear: number | ""; gpa: number | ""; certificateImageId: string; description: string; } export interface EducationFormValues { education: EducationItem[]; } const emptyEducationItem: EducationItem = { degree: "", field: "", university: "", startYear: "", endYear: "", gpa: "", certificateImageId: "", description: "", }; type Props = FormikProps & EducationFormProps; export default function InnerEducationForm(props: Props) { const { values, errors, touched, handleChange, setFieldValue } = props; const [uploadError, setUploadError] = useState>({}); const [uploading, setUploading] = useState>({}); const [uploadProgress, setUploadProgress] = useState>( {}, ); const [selectedFile, setSelectedFile] = useState>( {}, ); const abortControllerRef = useRef>({}); const validateImageFile = (file: File) => { if (!file.type.startsWith("image/")) { return "فقط فایل تصویری مجاز است"; } const maxSize = 500 * 1024; if (file.size > maxSize) { return "حجم عکس باید حداکثر ۵۰۰ کیلوبایت باشد"; } return ""; }; const handleFileChange = async ( event: React.ChangeEvent, index: number, ) => { const file = event.target.files?.[0]; if (!file) return; const error = validateImageFile(file); if (error) { setSelectedFile((prev) => ({ ...prev, [index]: null })); setUploadError((prev) => ({ ...prev, [index]: error })); setFieldValue(`education.${index}.certificateImageId`, ""); return; } setSelectedFile((prev) => ({ ...prev, [index]: file })); setUploadError((prev) => ({ ...prev, [index]: "" })); setUploadProgress((prev) => ({ ...prev, [index]: 0 })); const formData = new FormData(); formData.append("file", file); const controller = new AbortController(); abortControllerRef.current[index] = controller; try { setUploading((prev) => ({ ...prev, [index]: true })); const response = await axios.post("/api/cdn/upload", formData, { signal: controller.signal, onUploadProgress: (progressEvent) => { const total = progressEvent.total ?? 0; if (!total) return; setUploadProgress((prev) => ({ ...prev, [index]: Math.round((progressEvent.loaded * 100) / total), })); }, }); const uploadedUrl = response?.data?.url ?? ""; if (!uploadedUrl) { setUploadError((prev) => ({ ...prev, [index]: "آپلود انجام شد اما آدرس فایل دریافت نشد", })); setFieldValue(`education.${index}.certificateImageId`, ""); return; } setFieldValue(`education.${index}.certificateImageId`, uploadedUrl); } catch (error: any) { if ( axios.isCancel?.(error) || error?.name === "CanceledError" || error?.code === "ERR_CANCELED" ) { setUploadError((prev) => ({ ...prev, [index]: "آپلود توسط کاربر لغو شد", })); } else { setUploadError((prev) => ({ ...prev, [index]: "خطا در بارگذاری فایل", })); } setFieldValue(`education.${index}.certificateImageId`, ""); } finally { setUploading((prev) => ({ ...prev, [index]: false })); } }; const handleCancelUpload = (index: number) => { abortControllerRef.current[index]?.abort(); setUploading((prev) => ({ ...prev, [index]: false })); setUploadProgress((prev) => ({ ...prev, [index]: 0 })); }; const handleBack = () => { props?.update({ education: props.values.education }); props.setStep(props?.step - 1); }; return (
{({ push, remove }) => ( <> {values?.education?.map((item, index) => { const itemErrors = getIn(errors, `education.${index}`) || {}; const itemTouched = getIn(touched, `education.${index}`) || {}; return ( سابقه تحصیلی {index + 1} {values.education.length > 1 && ( remove(index)}> )} انتخاب کنید {DEGREE_OPTIONS.map((d) => ( {d} ))} setFieldValue( `education.${index}.startYear`, e.target.value === "" ? "" : Number(e.target.value), ) } fullWidth error={!!itemTouched.startYear && !!itemErrors.startYear} helperText={ itemTouched.startYear ? itemErrors.startYear : " " } /> setFieldValue( `education.${index}.endYear`, e.target.value === "" ? "" : Number(e.target.value), ) } fullWidth error={!!itemTouched.endYear && !!itemErrors.endYear} helperText={itemTouched.endYear ? itemErrors.endYear : " "} /> setFieldValue( `education.${index}.gpa`, e.target.value === "" ? "" : Number(e.target.value), ) } fullWidth error={!!itemTouched.gpa && !!itemErrors.gpa} helperText={itemTouched.gpa ? itemErrors.gpa : " "} /> تصویر مدرک تحصیلی {uploading[index] && ( )} {selectedFile[index] && ( فایل انتخاب‌شده: {selectedFile[index]?.name} )} {uploading[index] && ( {uploadProgress[index] || 0}% در حال بارگذاری... )} {!uploading[index] && item.certificateImageId && ( فایل با موفقیت بارگذاری شد )} {uploadError[index] && ( {uploadError[index]} )} {index < values.education.length - 1 && ( )} ); })} )}
); }