push rasad front on new repo
This commit is contained in:
574
src/features/province/components/create-guilds/CreateGuilds.js
Normal file
574
src/features/province/components/create-guilds/CreateGuilds.js
Normal file
@@ -0,0 +1,574 @@
|
||||
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 { 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 (
|
||||
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>آیا مطمئن هستید؟</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant="body2">
|
||||
آیا از حذف این صنف مطمئن هستید؟ این عمل قابل بازگشت نیست.
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ gap: 2, p: 2 }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={onClose}
|
||||
disabled={isDeleting}
|
||||
sx={{ flex: 1 }}
|
||||
>
|
||||
انصراف
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={onConfirm}
|
||||
disabled={isDeleting}
|
||||
sx={{ flex: 1 }}
|
||||
>
|
||||
{isDeleting ? "در حال حذف..." : "حذف"}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
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 [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)
|
||||
};
|
||||
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 || []);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
formik.validateForm();
|
||||
}, []);
|
||||
|
||||
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);
|
||||
setExpandedAccordion(0);
|
||||
} else {
|
||||
setGuildsList([]);
|
||||
setGuildsFormValues([]);
|
||||
}
|
||||
|
||||
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)]);
|
||||
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));
|
||||
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)
|
||||
);
|
||||
// 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;
|
||||
});
|
||||
}, []);
|
||||
|
||||
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 (
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<Grid
|
||||
container
|
||||
gap={SPACING.TINY}
|
||||
maxHeight="80vh"
|
||||
minWidth={
|
||||
!guild && !isInquiryDone
|
||||
? "auto"
|
||||
: { xs: "96vw", md: "90vw", nlg: "1280px" }
|
||||
}
|
||||
overflow="auto"
|
||||
p={2}
|
||||
>
|
||||
{shouldShowUpdateButton && (
|
||||
<UpdateFromExternalButton
|
||||
onUpdate={handleUpdateFromExternal}
|
||||
disabled={!!formik.errors.national_id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldShowInquiryForm && (
|
||||
<InquiryForm
|
||||
inquiryNationalCode={inquiryNationalCode}
|
||||
setInquiryNationalCode={setInquiryNationalCode}
|
||||
onInquiry={handleInquiry}
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldShowFormContent && (
|
||||
<>
|
||||
<Grid container xs={12}>
|
||||
<PersonalInfoSection
|
||||
formik={formik}
|
||||
guild={guild}
|
||||
hasInquiry={hasInquiry}
|
||||
isAdmin={isAdmin}
|
||||
isSuperAdmin={isSuperAdmin}
|
||||
isKillHouse={isKillHouse}
|
||||
/>
|
||||
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
lg={6}
|
||||
pr={{ xs: 0, md: 2 }}
|
||||
pl={{ xs: 0, md: 3 }}
|
||||
>
|
||||
<Grid container gap={SPACING.TINY} direction="column">
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
اطلاعات صنفی
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
{guildsList.map((guildItem, index) => (
|
||||
<Box key={index} sx={{ mb: 2 }}>
|
||||
<GuildInfoAccordionItem
|
||||
guildIndex={index}
|
||||
guildData={guildItem}
|
||||
guildActive={guildActive}
|
||||
isAdmin={isAdmin}
|
||||
cities={cities}
|
||||
typeActivities={typeActivities}
|
||||
onDelete={() => handleDeleteGuild(index)}
|
||||
canDelete={
|
||||
(guildsList.length > 1 || !guild) && isAdmin
|
||||
}
|
||||
guildFormValues={guildsFormValues[index]}
|
||||
onGuildValuesChange={handleGuildValuesChange}
|
||||
expanded={expandedAccordion === index}
|
||||
onChange={handleAccordionChange(index)}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</Grid>
|
||||
{isAdmin && (
|
||||
<Grid item xs={12} xl={4}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<AddIcon />}
|
||||
onClick={handleAddGuild}
|
||||
fullWidth
|
||||
sx={{ mb: 2 }}
|
||||
>
|
||||
افزودن واحد صنفی
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container item xs={12}>
|
||||
{hasRegisterCode &&
|
||||
(!(!guild && hasInquiry === true) ||
|
||||
isAdmin ||
|
||||
isSuperAdmin ||
|
||||
isKillHouse) && (
|
||||
<ConfirmationDialog
|
||||
isAccepted={formik.values.isAccepted}
|
||||
onAccept={() => formik.setFieldValue("isAccepted", true)}
|
||||
onReject={() => formik.setFieldValue("isAccepted", false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormActions
|
||||
formik={formik}
|
||||
onClose={() => dispatch(CLOSE_MODAL())}
|
||||
showCloseButton={
|
||||
!guild &&
|
||||
hasInquiry === true &&
|
||||
!isAdmin &&
|
||||
!isSuperAdmin &&
|
||||
!isKillHouse
|
||||
}
|
||||
isKillHouse={isKillHouse}
|
||||
onSubmit={formik.handleSubmit}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<DeleteConfirmationDialog
|
||||
open={deleteDialogOpen}
|
||||
onClose={handleCloseDeleteDialog}
|
||||
onConfirm={handleConfirmDelete}
|
||||
isDeleting={isDeletingGuild}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user