import React, { useContext, useEffect, useState, useCallback } from "react"; import { useFormik } from "formik"; import { useDispatch } from "react-redux"; import { Button, Box, Typography, Dialog, DialogTitle, DialogContent, DialogActions, } from "@mui/material"; import { Add as AddIcon } from "@mui/icons-material"; import { Grid } from "../../../../components/grid/Grid"; import { SPACING } from "../../../../data/spacing"; import { CLOSE_MODAL } from "../../../../lib/redux/slices/appSlice"; import { AppContext } from "../../../../contexts/AppContext"; import { updateGuildByNationalIdNewService } from "../../services/update-guild-by-national-id-new"; import { deactivateGuildService } from "../../services/deactivate-guild"; import { provinceGetCitiesService } from "../../services/province-get-cities"; import { provinceGetFieldOfWorks } from "../../services/ProvinceGetFieldOfWorks"; import { provinceGetTypeActivity } from "../../services/provinceGetTypeActivity"; import { provinceGetRegisterCodeStateService } from "../../services/province-get-register-code-state"; import { mainGetGuildsForUpdateOrCreateService } from "../../services/main-get-guilds-for-update-or-create"; import { cityGetProvinces } from "../../../city/services/CityGetProvinces"; import { cityGetCity } from "../../../city/services/city-get-city"; import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl"; import { PersonalInfoSection } from "./components/PersonalInfoSection"; import { InquiryForm } from "./components/InquiryForm"; import { UpdateFromExternalButton } from "./components/UpdateFromExternalButton"; import { ConfirmationDialog } from "./components/ConfirmationDialog"; import { FormActions } from "./components/FormActions"; import { GuildInfoAccordionItem } from "./components/GuildInfoAccordionItem"; import { getValidationSchema, getInitialValues } from "./utils/formUtils"; import { mapResponseDataToFormFields, prepareSubmitData, } from "./utils/dataMapping"; import { handleSubmitSuccess, handleSubmitError } from "./utils/submitHandlers"; const DeleteConfirmationDialog = ({ open, onClose, onConfirm, isDeleting }) => { return ( آیا مطمئن هستید؟ آیا از حذف این صنف مطمئن هستید؟ این عمل قابل بازگشت نیست. ); }; export const CreateGuilds = ({ guild, updateTable }) => { const dispatch = useDispatch(); const [openNotif] = useContext(AppContext); const [hasRegisterCode, setHasRegisterCode] = useState(); const [inquiryNationalCode, setInquiryNationalCode] = useState(""); const [isInquiryDone, setIsInquiryDone] = useState(false); const [dbRegister, setDbRegister] = useState(null); const [hasInquiry, setHasInquiry] = useState(null); const [guildActive, setGuildActive] = useState(null); const [guildsList, setGuildsList] = useState(() => (guild ? [guild] : [])); const [expandedAccordion, setExpandedAccordion] = useState(0); const [guildsFormValues, setGuildsFormValues] = useState(() => { // Initialize with guild data if editing if (guild) { return [getInitialValues(guild)]; } return []; }); const [cities, setCities] = useState([]); const [provinces, setProvinces] = useState([]); const [provinceCities, setProvinceCities] = useState([]); const [typeActivities, setTypeActivities] = useState([]); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteDialogIndex, setDeleteDialogIndex] = useState(null); const [isDeletingGuild, setIsDeletingGuild] = useState(false); const originalPhoneNumber = guild?.phoneNumber || null; const currentRole = getRoleFromUrl(); const isAdmin = currentRole === "AdminX"; const isSuperAdmin = currentRole === "SuperAdmin"; const isKillHouse = currentRole === "KillHouse"; const formik = useFormik({ initialValues: getInitialValues(guild), validationSchema: getValidationSchema(!!guild), validateOnMount: true, onSubmit: (values) => { const guildsDataArray = guildsList.map((guildItem, index) => { const guildValues = guildsFormValues[index] || values; const combinedValues = { ...values, // Personal info (shared) ...guildValues, // Guild-specific info (overrides if same keys exist) national_id: values?.national_id, gender: values?.gender, first_name: values?.first_name, last_name: values?.last_name, national_code: values?.last_name, is_alive: values?.is_alive, birth_date: values?.birth_date, father_name: values?.father_name, mobile: values?.mobile, }; return prepareSubmitData( combinedValues, guildItem, originalPhoneNumber, hasInquiry ); }); dispatch(updateGuildByNationalIdNewService(guildsDataArray)).then( (result) => { if (result.payload.error) { handleSubmitError(openNotif, result.payload.error); } else { handleSubmitSuccess( dispatch, openNotif, updateTable, values, result.payload?.data ); } } ); }, }); useEffect(() => { dispatch(provinceGetRegisterCodeStateService()).then((r) => { const isActive = r.payload.data?.[0]?.active; setHasRegisterCode(isActive); if (isActive === false) { formik.setFieldValue("isAccepted", true); } }); dispatch(provinceGetCitiesService()).then((r) => { setCities(r.payload.data || []); }); dispatch(provinceGetFieldOfWorks()); dispatch(provinceGetTypeActivity()).then((r) => { setTypeActivities(r.payload.data || []); }); // Fetch provinces for province/city selection dispatch(cityGetProvinces()).then((r) => { if (r?.payload?.data) { setProvinces(r.payload.data); } }); }, []); useEffect(() => { // Initialize Formik's guilds array if we have initial guild data if (guild && guildsList.length > 0) { const guildsForFormik = guildsList.map((guildItem) => { const combinedGuild = { ...guildItem, user: guild?.user || {}, }; const initialValues = getInitialValues(combinedGuild); return { steward: initialValues.steward || false, guild: initialValues.guild || false, license_number: initialValues.license_number ?? "", }; }); formik.setFieldValue("guilds", guildsForFormik, false).then(() => { formik.validateField("guilds"); }); } formik.validateForm(); }, []); // Set province ID from state name when provinces are loaded useEffect(() => { if ( formik.values.state && provinces.length > 0 && !formik.values.province ) { const province = provinces.find((p) => p.name === formik.values.state); if (province) { formik.setFieldValue("province", province.key); } } }, [provinces, formik.values.state, formik.values.province]); // Fetch cities when province is selected useEffect(() => { if (formik.values.province) { dispatch(cityGetCity(formik.values.province)).then((r) => { if (r?.payload?.data) { setProvinceCities(r.payload.data); } }); } else { setProvinceCities([]); } }, [formik.values.province, dispatch]); // Set city ID from person_city name when provinceCities are loaded useEffect(() => { if ( formik.values.person_city && !formik.values.city && provinceCities.length > 0 ) { const city = provinceCities.find( (c) => c.name === formik.values.person_city ); if (city) { formik.setFieldValue("city", city.key); } } }, [provinceCities, formik.values.person_city, formik.values.city]); const mapResponseToFormFields = useCallback( (responseData) => { const guildsData = Array.isArray(responseData.guilds) ? responseData.guilds : []; mapResponseDataToFormFields(responseData, inquiryNationalCode, formik); if (responseData.dbRegister === false) { setDbRegister(false); setHasInquiry(null); } else { setHasInquiry(responseData.hasInquiry ?? null); const firstGuild = guildsData.length > 0 ? guildsData[0] : null; const activeStatus = firstGuild?.active ?? responseData.active ?? null; setGuildActive(activeStatus); formik.setFieldValue("active", activeStatus); setDbRegister(true); } if (guildsData.length > 0) { setGuildsList(guildsData); const initialGuildValues = guildsData.map((guildItem) => { const combinedGuild = { ...guildItem, user: responseData.user || {}, }; return getInitialValues(combinedGuild); }); setGuildsFormValues(initialGuildValues); // Update Formik's guilds array for validation (include validated fields) const guildsForFormik = initialGuildValues.map((g) => ({ steward: g.steward ?? false, guild: g.guild ?? false, license_number: g.license_number ?? "", })); formik.setFieldValue("guilds", guildsForFormik, true).then(() => { formik.validateField("guilds"); }); setExpandedAccordion(0); } else { setGuildsList([]); setGuildsFormValues([]); formik.setFieldValue("guilds", [], true).then(() => { formik.validateField("guilds"); }); } setTimeout(() => { formik.validateField("mobile"); formik.validateField("national_id"); }, 0); }, [formik, inquiryNationalCode] ); const handleInquiry = useCallback(() => { if (!inquiryNationalCode) { openNotif({ vertical: "top", horizontal: "center", msg: "لطفا کد ملی را وارد کنید", severity: "error", }); return; } if (!isAdmin && inquiryNationalCode.length !== 10) { openNotif({ vertical: "top", horizontal: "center", msg: "لطفا کد ملی 10 رقمی معتبر وارد کنید", severity: "error", }); return; } dispatch( mainGetGuildsForUpdateOrCreateService({ national_code: inquiryNationalCode, update: false, }) ).then((r) => { if (r.payload.error) { setHasInquiry(false); if (isAdmin) { setIsInquiryDone(true); formik.setFieldValue("national_id", inquiryNationalCode); } openNotif({ vertical: "top", horizontal: "center", msg: r.payload.error, severity: "error", }); if (!isAdmin) { return; } } if (r.payload.data) { mapResponseToFormFields(r.payload.data); setIsInquiryDone(true); if (r.payload.data.dbRegister === false) { setHasInquiry(true); } const successMsg = r.payload.data.dbRegister === false ? "اطلاعات از سامانه خارجی دریافت شد" : "اطلاعات از پایگاه داده دریافت شد"; openNotif({ vertical: "top", horizontal: "center", msg: successMsg, severity: "success", }); } else { setHasInquiry(false); setIsInquiryDone(true); if (isAdmin) { formik.setFieldValue("national_id", inquiryNationalCode); } } }); }, [ dispatch, inquiryNationalCode, openNotif, mapResponseToFormFields, isAdmin, formik, ]); const handleUpdateFromExternal = useCallback(() => { if (!formik.values.national_id || formik.values.national_id.length !== 10) { openNotif({ vertical: "top", horizontal: "center", msg: "لطفا کد ملی 10 رقمی معتبر وارد کنید", severity: "error", }); return; } dispatch( mainGetGuildsForUpdateOrCreateService({ national_code: formik.values.national_id, update: true, }) ).then((r) => { if (r.payload.error) { setHasInquiry(false); openNotif({ vertical: "top", horizontal: "center", msg: r.payload.error, severity: "error", }); return; } if (r.payload.data) { const updateResponse = { ...r.payload.data, dbRegister: false, }; mapResponseToFormFields(updateResponse); setHasInquiry(true); openNotif({ vertical: "top", horizontal: "center", msg: "اطلاعات از سامانه خارجی بروزرسانی شد", severity: "success", }); } else { setHasInquiry(false); } }); }, [dispatch, formik.values.national_id, openNotif, mapResponseToFormFields]); const handleAddGuild = () => { const newIndex = guildsList.length; setGuildsList([...guildsList, null]); setGuildsFormValues([...guildsFormValues, getInitialValues(null)]); // Add to Formik's guilds array for validation const currentGuilds = formik.values.guilds || []; formik .setFieldValue( "guilds", [...currentGuilds, { steward: false, guild: false }], true ) .then(() => { formik.validateField("guilds"); }); setExpandedAccordion(newIndex); }; const handleDeleteGuild = (index) => { const guildToDelete = guildsList[index]; if (guildToDelete?.key) { setDeleteDialogIndex(index); setDeleteDialogOpen(true); return; } if (guildsList.length > 1) { setGuildsList(guildsList.filter((_, i) => i !== index)); setGuildsFormValues(guildsFormValues.filter((_, i) => i !== index)); // Remove from Formik's guilds array const currentGuilds = formik.values.guilds || []; formik .setFieldValue( "guilds", currentGuilds.filter((_, i) => i !== index), true ) .then(() => { formik.validateField("guilds"); }); if (expandedAccordion === index) { setExpandedAccordion(0); } else if (expandedAccordion > index) { setExpandedAccordion(expandedAccordion - 1); } } }; const handleConfirmDelete = () => { if (deleteDialogIndex === null) return; const guildToDelete = guildsList[deleteDialogIndex]; if (!guildToDelete?.key) return; setIsDeletingGuild(true); dispatch(deactivateGuildService(guildToDelete.key)).then((r) => { setIsDeletingGuild(false); setDeleteDialogOpen(false); setDeleteDialogIndex(null); if (r.payload?.error) { openNotif({ vertical: "top", horizontal: "center", msg: r.payload.error, severity: "error", }); } else { openNotif({ vertical: "top", horizontal: "center", msg: "صنف با موفقیت حذف شد", severity: "success", }); // Remove from list after successful deletion if (guildsList.length > 1) { setGuildsList(guildsList.filter((_, i) => i !== deleteDialogIndex)); setGuildsFormValues( guildsFormValues.filter((_, i) => i !== deleteDialogIndex) ); // Remove from Formik's guilds array const currentGuilds = formik.values.guilds || []; formik .setFieldValue( "guilds", currentGuilds.filter((_, i) => i !== deleteDialogIndex), true ) .then(() => { formik.validateField("guilds"); }); // If deleted accordion was expanded, expand the first one if (expandedAccordion === deleteDialogIndex) { setExpandedAccordion(0); } else if (expandedAccordion > deleteDialogIndex) { // Adjust expanded index if deleted item was before it setExpandedAccordion(expandedAccordion - 1); } } if (updateTable) { updateTable(); } } }); }; const handleCloseDeleteDialog = () => { if (!isDeletingGuild) { setDeleteDialogOpen(false); setDeleteDialogIndex(null); } }; const handleGuildValuesChange = useCallback( (index, fieldName, value) => { setGuildsFormValues((prev) => { const newValues = [...prev]; if (!newValues[index]) { newValues[index] = getInitialValues(null); } newValues[index] = { ...newValues[index], [fieldName]: value, }; return newValues; }); // Sync validated guild fields to Formik's guilds array (schema: license_number, steward, guild) if ( fieldName === "steward" || fieldName === "guild" || fieldName === "license_number" ) { const currentGuilds = formik.values.guilds || []; const updatedGuilds = [...currentGuilds]; if (!updatedGuilds[index]) { updatedGuilds[index] = { steward: false, guild: false }; } updatedGuilds[index] = { ...updatedGuilds[index], [fieldName]: value, }; formik.setFieldValue("guilds", updatedGuilds, true).then(() => { formik.validateField("guilds"); }); } }, [formik] ); const handleAccordionChange = (index) => (event, isExpanded) => { setExpandedAccordion(isExpanded ? index : false); }; const shouldShowUpdateButton = formik?.values?.national_id && (isAdmin || (dbRegister !== false && (guild || (!guild && ((dbRegister === true && hasInquiry === false) || (isAdmin && isInquiryDone)))))); const shouldShowInquiryForm = !guild && !isInquiryDone; const shouldShowFormContent = guild || isInquiryDone; return (
{shouldShowUpdateButton && ( )} {shouldShowInquiryForm && ( )} {shouldShowFormContent && ( <> اطلاعات واحد {guildsList.map((guildItem, index) => ( 0 ? provinceCities : cities } typeActivities={typeActivities} onDelete={() => handleDeleteGuild(index)} canDelete={ (guildsList.length > 1 || !guild) && isAdmin } guildFormValues={guildsFormValues[index]} onGuildValuesChange={handleGuildValuesChange} expanded={expandedAccordion === index} onChange={handleAccordionChange(index)} mainFormik={formik} /> ))} {isAdmin && ( )} {hasRegisterCode && (!(!guild && hasInquiry === true) || isAdmin || isSuperAdmin || isKillHouse) && ( formik.setFieldValue("isAccepted", true)} onReject={() => formik.setFieldValue("isAccepted", false)} /> )} dispatch(CLOSE_MODAL())} showCloseButton={ !guild && hasInquiry === true && !isAdmin && !isSuperAdmin && !isKillHouse } formData={guildsList.map((guildItem, index) => { const guildValues = guildsFormValues[index]; const combinedValues = { ...guildValues, // Guild-specific info (overrides if same keys exist) }; return prepareSubmitData( combinedValues, guildItem, originalPhoneNumber, hasInquiry ); })} isKillHouse={isKillHouse} onSubmit={formik.handleSubmit} /> )} ); };