import { LoadingButton } from "@mui/lab"; import { Box, Button, Chip, Grid, MenuItem, Select, Switch, TextField } from "@mui/material"; import { useFormik } from "formik"; import React, { useMemo, useRef, useState } from "react"; import { useSelector } from "react-redux"; import * as Yup from "yup"; import EditIcon from '@mui/icons-material/Edit'; /* ----------------- Custom Imports ----------------- */ import PageHeader from "../../components/PageHeader"; import Table from "../../components/Table"; import ConfirmationModal from "../Modal/ConfirmationModal"; import CustomModal from "../Modal/Modal"; import { useStyles } from "./userStyles"; /* ----------------- Assets ----------------- */ import AddIcon from "@mui/icons-material/Add"; import { getUsers, deleteUserById, getRoles, getUserById, resendPasswordMailer, revokeAdminTransferAccess, transferMasterAdminAccess, } from "../../services/users.service"; /* ----------------- Utils ----------------- */ import { format } from "date-fns"; import MultiSelect from "../../components/MultiSelect"; import { NOTIFICATION, NOT_AVAILABLE_TEXT } from "../../constants"; import { pushNotification } from "../../utils/notification"; /* ----------------- Validation Schema ----------------- */ const validationSchema = Yup.object().shape({ userName: Yup.string().required("User Name is required"), email: Yup.string() .email("Invalid Email Address") .required("Email is required"), mobile: Yup.string() .matches(/^\d{10}$/, "Mobile Number must be exactly 10 digits") .required("Mobile Number is required"), }); function Users() { const ref = useRef(null); const defaultFormData = useRef({ userName: "", email: "q@gmail.com", mobile: "1234567890", isEditUser: false, lastName: "", userType: "", appointmentType: [], appointmentTypeObject: "", }); const fieldRefs = { userName: useRef(null), email: useRef(null), mobile: useRef(null), lastName: useRef(null), userType: useRef(null), appointmentType: useRef(null), }; const classes = useStyles(); /* ----------------- State Variables ----------------- */ const [showModal, setShowModal] = useState(false); const [showUserAccessModal, setShowUserAccessModal] = useState(false); const [isEditUser, setIsEditUser] = useState(false); const [deleteModal, setDeleteModal] = useState(false); const [masterAdminModal, setMasterAdminModal] = useState(false); const [buttonLoading, setButtonLoading] = useState(false); const [userId, setUserId] = useState(); const [userTotalCount, setUserTotalCount] = useState(0); const [selectedCheckboxes, setSelectedCheckboxes] = useState({}); const [checkboxError, setCheckboxError] = useState(false); const [roles, setRoles] = useState(); const [isAdmin, setIsAdmin] = useState(); const isBsAdmin = useSelector((state) => state?.login?.user?.isBsAdmin); /* ----------------- Get Users ----------------- */ const getData = async (filters) => { const resp = await getUsers(filters); console.log(resp); console.log(resp?.data?.totalCount); setUserTotalCount(resp?.data?.totalCount); const role = await getRoles({ page: 0 }); setRoles(role?.data); return { data: resp?.data?.records, rowCount: resp?.data?.totalCount }; }; const editUser = async (row) => { try { const userData = await getUserById(row?.original?.id); const formData = { userName: userData?.name, email: userData?.email, mobile: userData?.mobile, isEditUser: true, }; // const updatedCheckboxes = roles.reduce( // (acc, role) => ({ // ...acc, // [role?.id]: userData?.roles.some( // (roleData) => roleData?.id === role?.id // ), // }), // {} // ); // setSelectedCheckboxes(updatedCheckboxes); // formik.setValues(formData); // toggle(); // setIsEditUser(true); // setUserId(row?.original?.id); } catch ({ resp }) { // eslint-disable-next-line no-console console.error(resp?.data?.message); } }; const handleToggleButton = async (row) => { try { // Replace this with your actual API call to update user status // Example: await updateUserStatus(row.id, !row.isActive); // For now, just show a notification pushNotification( `${row.name}'s status has been ${row.isActive ? 'deactivated' : 'activated'}`, NOTIFICATION.SUCCESS ); // Refresh the table data ref.current.reFetchData(); } catch (error) { console.error(error); pushNotification('Failed to update status', NOTIFICATION.ERROR); } }; /* ----------------- Handle Submit ----------------- */ const handleSubmit = async (values, formik) => { try { // if (!showUserAccessModal) { // setShowUserAccessModal(true); // return; // } // const hasSelectedCheckbox = // Object.values(selectedCheckboxes).some(Boolean); // if (!hasSelectedCheckbox) { // setCheckboxError(true); // return; // } // setCheckboxError(false); // const combinedValues = { // ...values, // name: values.userName, // roles: Object.entries(selectedCheckboxes) // .filter( // ([id, isChecked]) => // isChecked && id !== 'transferMasterAdminAccess' && id !== null // ) // .map(([id]) => parseInt(id)), // transferMasterAdminAccess: // selectedCheckboxes.transferMasterAdminAccess || false, // }; // delete combinedValues.userName; // delete combinedValues.confirmPassword; // let response = isEditUser // ? await updateUserById(userId, combinedValues) // : await addUser(combinedValues); // if (response.status === 200) { // pushNotification(response?.data?.message, NOTIFICATION.SUCCESS); pushNotification("Doctor added successfully", NOTIFICATION.SUCCESS); // ref.current.reFetchData(); toggle(); formik.resetForm(); setSelectedCheckboxes({}); // } } catch (error) { // eslint-disable-next-line no-console console.log(error); } }; /* ----------------- Toggle Modal ----------------- */ const toggle = () => { setIsEditUser(false); setShowUserAccessModal(false); setShowModal(!showModal); }; /* ----------------- Handle Checkbox Change ----------------- */ const handleCheckboxChange = (id, isChecked) => { setSelectedCheckboxes({ ...selectedCheckboxes, [id]: isChecked }); }; /* ----------------- Table Columns ----------------- */ const columns = useMemo( () => [ { size: 30, header: "S.no.", Cell: (props) => { const tableState = props?.table?.getState(); const serialNumber = ( props?.row?.index + 1 + tableState?.pagination?.pageIndex * tableState?.pagination?.pageSize ) ?.toString() ?.padStart(1, "0"); return {serialNumber}.; }, enableSorting: false, }, { accessorFn: ({ name }) => name || NOT_AVAILABLE_TEXT, accessorKey: "name", header: "Doctor/Nurse Name", isBold: true, }, { accessorFn: ({ userType }) => userType || NOT_AVAILABLE_TEXT, accessorKey: "userType", header: "User Type", }, { accessorKey: "appointmentTypes", header: "Appointment Types", Cell: ({ row }) => { const appointmentTypes = row?.original?.appointmentTypes; // Convert to array if it's a string (comma-separated values) const typesArray = Array.isArray(appointmentTypes) && appointmentTypes.length > 0 ? appointmentTypes : typeof appointmentTypes === 'string' && appointmentTypes.trim() !== '' ? appointmentTypes.split(',').map(type => type.trim()) : []; return ( {typesArray.length > 0 ? ( typesArray.map((type, index) => { const label = typeof type === 'string' ? type : type?.name || type?.type || String(type); return ( ); }) ) : ( )} ); }, }, { accessorKey: "createdAt", Cell: ({ row }) => (
{format(new Date(row?.original?.createdAt), "dd MMM, yyyy")}
), header: "Added On", }, { accessorFn: ({ email }) => email || NOT_AVAILABLE_TEXT, accessorKey: "status", header: "Status", }, { size: 30, accessorKey: "actions", header: "Actions", enableSorting: false, Cell: ({ row }) => (
handleToggleButton(row?.original)} inputProps={{ "aria-label": "Status toggle" }} color="primary" />
), } ], [] ); const formik = useFormik({ initialValues: defaultFormData.current, validationSchema, onSubmit: (values) => handleSubmit(values, formik), }); /* ----------------- Handle Cancel ----------------- */ const handleCancel = () => { toggle(); formik.resetForm(); }; const deleteUserToggle = (row) => { setDeleteModal(!deleteModal); setSelectedUserData(row?.original); }; const makeMasterAdminToggle = (row) => { setMasterAdminModal((prev) => !prev); setSelectedUserData(row?.original); }; /* ----------------- Transfer Master Admin Access to User ----------------- */ const handleTransferMasterAdminAccess = async () => { setButtonLoading(true); try { const response = await transferMasterAdminAccess(seletedUserData?.id); if (response.status === 200) { pushNotification(response?.data?.message, NOTIFICATION.SUCCESS); ref.current.resetPage(true); makeMasterAdminToggle(); } } catch (error) { // eslint-disable-next-line no-console console.error(error?.response?.data?.message); } finally { ref.current.reFetchData(); setButtonLoading(false); } }; /* ----------------- Delete User ----------------- */ const deleteUser = async () => { setButtonLoading(true); try { const response = await deleteUserById(seletedUserData?.id); if (response.status === 200) { pushNotification(response?.data?.message, NOTIFICATION.SUCCESS); ref.current.resetPage(true); deleteUserToggle(); } } catch (error) { // eslint-disable-next-line no-console console.error(error?.response?.data?.message); } finally { ref.current.reFetchData(); setButtonLoading(false); } }; const handleuserAccessCancel = () => { setCheckboxError(false); setShowUserAccessModal(false); }; const getRowStyle = (row) => row?.original?.isAdmin ? { backgroundColor: "#E7F4EE !important" } : {}; const handleSubmitClick = async () => { const formikErrors = await formik.validateForm(); const errors = Object.keys(formikErrors); if (errors.length) { // Find the first invalid field and focus it const firstErrorField = errors[0]; const firstErrorRef = fieldRefs[firstErrorField]?.current; if (firstErrorRef) { // Scroll to the first invalid field smoothly if (typeof firstErrorRef?.scrollIntoView === "function") { firstErrorRef?.scrollIntoView({ behavior: "smooth", block: "center", }); } // Focus the field after a slight delay (to ensure scrolling completes first) setTimeout(() => firstErrorRef.focus(), 300); } // Show error notification if (formik?.touched[firstErrorField]) pushNotification(formikErrors[firstErrorField], NOTIFICATION.ERROR); } formik.handleSubmit(); }; return ( } addButtonDisabled={userTotalCount === 10} // permissionName={'CREATE_USERS'} infiniteDropdown /> ), // permissionName: "CREATE_USERS", }, ]} /> {/* --------------- ADD User Modal --------------- */} {showModal && !showUserAccessModal && ( handleCancel()} onFooterRightButtonClick={() => handleSubmit()} title={isEditUser ? "Edit Doctor/Nurse" : "Add New Doctor/Nurse"} isTitleLeft={true} onClose={() => { formik.resetForm(); setShowModal(false); setSelectedCheckboxes([]); setIsAdmin(false); }} modalBodyFunction={() => (
{ formik.setFieldValue("userName", e.target.value.trim()); formik.handleBlur(e); }} inputRef={fieldRefs.userName} error={Boolean( formik.errors.userName && formik.touched.userName )} helperText={ formik.errors.userName && formik.touched.userName ? ( {formik.errors.userName} ) : ( "" ) } /> { formik.setFieldValue("lastName", e.target.value.trim()); formik.handleBlur(e); }} inputRef={fieldRefs.lastName} error={Boolean( formik.errors.lastName && formik.touched.lastName )} helperText={ formik.errors.lastName && formik.touched.lastName ? ( {formik.errors.lastName} ) : ( "" ) } /> option.name} searchDebounceTime={500} fieldName="appointmentType" placeholderText="Select Appointment Types" styleForSelectorParent={classes.multiSelectParent} styleForSelector={classes.multiSelectChild} inputRef={fieldRefs.appointmentType} /> {/* {formik.errors.email} ) : ( '' ) } /> { if (e.target.value.length <= 10) { formik.handleChange(e); } }} onBlur={formik.handleBlur} inputRef={fieldRefs.mobile} error={Boolean(formik.errors.mobile && formik.touched.mobile)} helperText={ formik.errors.mobile && formik.touched.mobile ? ( {formik.errors.mobile} ) : ( '' ) } inputProps={{ type: 'string', pattern: '[0-9]*', autocomplete: 'password', form: { autocomplete: 'off', }, }} /> */}
)} /> )} {/* ----------- Choose User Access Modal----------- */} {showModal && showUserAccessModal && formik.isValid && ( handleuserAccessCancel()} onFooterRightButtonClick={() => formik.handleSubmit()} footerLeftButtonTitle="Cancel" footerRightButtonTitle="Add" showFooter onClose={() => { formik.resetForm(); setSelectedCheckboxes([]); setShowModal(false); setIsAdmin(false); }} backFunctionCall={() => { setShowUserAccessModal(false); }} modalBodyFunction={() => <>} footerContent={ setCheckboxError(false)} // Clear error on cancel > Cancel Add } /> )} {/* ----------- Delete User Modal ----------- */} {deleteModal && ( )} {/* ----------- Make User Master Admin Modal ----------- */} {masterAdminModal && ( )} ); } export default Users;