2025-06-26 12:28:02 +05:30

169 lines
5.1 KiB
JavaScript

import React, { useEffect, useRef, useState, useMemo } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useDispatch } from "react-redux";
import { useEmployeeRoles, useUpdateEmployeeRoles } from "../../hooks/useEmployees";
import useMaster from "../../hooks/masterHook/useMaster";
import { changeMaster } from "../../slices/localVariablesSlice";
import { RolesRepository } from "../../repositories/MastersRepository";
import showToast from "../../services/toastService";
const formSchema = z.object({
selectedRole: z.record(z.boolean()),
});
const ManageRole = ( {employeeId, onClosed} ) =>
{
const dispatch = useDispatch();
const formStateRef = useRef({});
useEffect(() => {
dispatch(changeMaster("Application Role"));
}, [dispatch]);
const { employeeRoles = [], loading: empLoading } = useEmployeeRoles(employeeId);
const { data: roles = [], loading: roleLoading } = useMaster();
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm({
resolver: zodResolver(formSchema),
defaultValues: { selectedRole: {} },
});
const {
updateRoles,
isPending : isLoading,
isError,
error,
} = useUpdateEmployeeRoles({
onClose: onClosed,
resetForm: reset,
});
// Prepare default form values based on roles and current assignments
const selectedRoleDefaults = useMemo(() => {
const defaults = {};
roles.forEach((role) => {
const enabled = employeeRoles.some(
(empRole) => empRole.roleId === role.id && empRole.isEnabled
);
defaults[role.id] = enabled;
});
return defaults;
}, [roles, employeeRoles]);
// Avoid infinite loop by comparing previous form values
useEffect(() => {
const prev = JSON.stringify(formStateRef.current);
const next = JSON.stringify(selectedRoleDefaults);
if (prev !== next) {
formStateRef.current = selectedRoleDefaults;
reset({ selectedRole: selectedRoleDefaults });
}
}, [selectedRoleDefaults, reset]);
const onSubmit = async (formData) => {
// setIsLoading(true);
const updates = [];
const selected = formData.selectedRole;
for (const [roleId, isChecked] of Object.entries(selected)) {
const existing = employeeRoles.find((r) => r.roleId === roleId);
const wasChecked = !!existing?.isEnabled;
if (isChecked !== wasChecked) {
updates.push({
id: existing?.id || "00000000-0000-0000-0000-000000000000",
employeeId,
roleId,
isEnabled: isChecked,
});
}
}
if (updates.length === 0) {
showToast("No changes made", "info");
// setIsLoading(false);
return;
}
// try {
// await RolesRepository.createEmployeeRoles(updates);
// showToast("Roles updated successfully", "success");
// reset();
// onClosed();
// } catch (err) {
// const message =
// err?.response?.data?.message || err?.message || "Error occurred while updating roles";
// showToast(message, "error");
// } finally {
// setIsLoading(false);
// }
updateRoles(updates);
};
const isLoadingData = roleLoading || empLoading;
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="text-start mb-3">
<p className="lead">Select Roles</p>
</div>
{isLoadingData ? (
<p>Loading...</p>
) : (
<div
className="d-flex flex-wrap justify-content-between pb-4"
style={{ maxHeight: "70vh", overflowY: "auto" }}
>
{roles.map((role) => (
<div className="col-md-6 col-lg-4 mb-3" key={role.id}>
<div className="form-check ms-2 text-start">
<input
className="form-check-input"
type="checkbox"
id={role.id}
{...register(`selectedRole.${role.id}`)}
/>
<label className="form-check-label" htmlFor={role.id}>
<small>{role.role || "--"}</small>
</label>
</div>
</div>
))}
</div>
)}
{errors.selectedRole && (
<div className="text-danger text-center">
{errors.selectedRole.message}
</div>
)}
<div className="text-center mt-3">
<button type="submit" className="btn btn-sm btn-primary me-3" disabled={isLoading}>
{isLoading ? "Please Wait..." : "Submit"}
</button>
<button
type="reset"
className="btn btn-sm btn-label-secondary"
data-bs-dismiss="modal"
aria-label="Close"
>
Cancel
</button>
</div>
</form>
);
};
export default ManageRole;