Permission Groups - Copy this React, Tailwind Component to your project
import React, { useEffect } from 'react'; import { useFormik } from 'formik'; import * as Yup from 'yup'; import { X } from 'lucide-react'; import { useDispatch, useSelector } from 'react-redux'; import { createManager, updateManager } from '../redux/slices/managerSlice'; import apiUrl from '../utills/apiUrl'; const AddEditManagerModal = ({ isOpen, closeModal, manager, closeDrawer,setAddedManager,addedManager }) => { const dispatch = useDispatch(); const { managers, loading, error,sucessMessages } = useSelector((state) => state.managers); useEffect(() => { if (isOpen) { document.body.style.overflow = 'hidden'; window.scrollTo(0,document.body.scrollHeight*0.5) } else { document.body.style.overflow = ''; } return () => { document.body.style.overflow = ''; // Clean up when the component unmounts }; }, [isOpen]); const initialPermissions={ dashboard:{read:false}, // allAccess:{read:false,write:false,update:false,delete:false}, users:{ read:false, write:false, update:false, delete:false, }, drivers:{ read:false, subMenus:{ allDrivers:{read:false,write:false,update:false,delete:false,approveDriver:false,rejectDriver:false,approveDocuments:false,rejectDocuments:false}, approvedDrivers:{read:false,write:false,update:false,delete:false,approveDriver:false,rejectDriver:false,approveDocument:false,rejectDocuments:false}, pendingDrivers:{read:false,write:false,update:false,delete:false,approveDriver:false,rejectDriver:false,approveDocuments:false,rejectDocuments:false} } }, notifications:{read:false,write:false,update:false,delete:false}, sos:{read:false,write:false,update:false,delete:false}, requests:{read:false}, complaints:{read:false,update:false,delete:false}, managers:{read:false,write:false,update:false,delete:false}, region:{read:false,write:false,update:false,delete:false}, marketing:{read:false,subMenus:{ coupons:{read:false,write:false,update:false,delete:false} }}, vehicleSettings:{ read:false, subMenus:{ vehicle_categories:{read:false,write:false,update:false,delete:false}, vehicle_Types:{read:false,write:false,update:false,delete:false}, vehicle_manufacturer:{read:false,write:false,update:false,delete:false} } }, administration_tools:{read:false,subMenus:{ settings:{read:false,write:false,update:false,delete:false}, privacy_policy:{read:false,write:false,update:false,delete:false}, terms_and_conditions:{read:false,write:false,update:false,delete:false} }}, expense_settings:{ read:false, subMenus:{ manage_expense:{read:false,write:false,update:false,delete:false}, expense_categories:{read:false,write:false,update:false,delete:false} } } } const initialValues = { name: manager?.name || '', email: manager?.email || '', password: '', permissions:manager?.permissions||initialPermissions, priority:manager?.priority||"" }; const validationSchema = Yup.object({ name: Yup.string().required('Name is required'), email: Yup.string().email('Invalid email').required('Email is required'), password: manager ? Yup.string() : Yup.string().min(6, 'Password must be at least 6 characters').required('Password is required'), }); const formik = useFormik({ initialValues, validationSchema, onSubmit: async (values) => { try { setAddedManager(values) if (!manager) { await dispatch(createManager({ apiUrl, managerData: values })).unwrap(); if (closeModal) closeModal(); alert("Manager Created Successfully") } else { const data = { ...values, id: manager._id }; await dispatch(updateManager({ apiUrl, managerData: data })).unwrap(); alert("Manager Updated Successfully") if (closeDrawer) { closeDrawer(); } else if (closeModal) { closeModal(); } } } catch (err) { console.log(err,"err") console.error('Failed to create or update manager:', err.message); alert(err.message) } }, }); const handleAllAccessChange = (checked) => { const updatedPermissions = Object.fromEntries( Object.keys(formik.values.permissions).map((key) => [key, checked]) ); formik.setFieldValue('permissions', updatedPermissions); }; const handlePermissionChange = (section, subsection, type) => { const updatedPermissions = { ...formik.values.permissions }; if (subsection) { updatedPermissions[section].subMenus[subsection][type] = !updatedPermissions[section].subMenus[subsection][type]; } else { updatedPermissions[section][type] = !updatedPermissions[section][type]; } formik.setFieldValue('permissions', updatedPermissions); }; if (!isOpen) return null; return ( <div className="fixed inset-0 bg-gray-700 bg-opacity-60 flex justify-center items-center"> <div className="bg-white p-6 rounded-lg shadow-lg w-full max-w-md relative max-h-[90vh] overflow-y-auto"> <div className="absolute top-4 right-4"> <button onClick={() => { if (closeModal) closeModal(); if (closeDrawer) closeDrawer(); }} className="p-2 hover:bg-gray-100 rounded-full focus:outline-none" > <X className="w-6 h-6 text-gray-700" /> </button> </div> <h3 className="text-lg font-semibold mb-6 text-gray-800"> {manager ? 'Edit Manager' : 'Add Manager'} </h3> <form onSubmit={formik.handleSubmit} className="space-y-6"> <div> <label className="block text-sm font-medium text-gray-700 mb-2">Name</label> <input name="name" type="text" onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.name} className="w-full px-4 py-2 border rounded-md focus:ring-blue-500 focus:border-blue-500 text-gray-700 shadow-sm" /> {formik.touched.name && formik.errors.name && ( <div className="text-sm text-red-500 mt-1">{formik.errors.name}</div> )} </div> <div> <label className="block text-sm font-medium text-gray-700 mb-2">Email</label> <input name="email" type="email" onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.email} className="w-full px-4 py-2 border rounded-md focus:ring-blue-500 focus:border-blue-500 text-gray-700 shadow-sm" /> {formik.touched.email && formik.errors.email && ( <div className="text-sm text-red-500 mt-1">{formik.errors.email}</div> )} </div> {!manager && ( <div> <label className="block text-sm font-medium text-gray-700 mb-2">Password</label> <input name="password" type="password" onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.password} className="w-full px-4 py-2 border rounded-md focus:ring-blue-500 focus:border-blue-500 text-gray-700 shadow-sm" /> {formik.touched.password && formik.errors.password && ( <div className="text-sm text-red-500 mt-1">{formik.errors.password}</div> )} </div> )} <div> <label className="block text-sm font-medium text-gray-700 mb-2">Priority</label> <input name="priority" type="text" onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.priority} className="w-full px-4 py-2 border rounded-md focus:ring-blue-500 focus:border-blue-500 text-gray-700 shadow-sm" /> {formik.touched.priority && formik.errors.priority && ( <div className="text-sm text-red-500 mt-1">{formik.errors.priority}</div> )} </div> <div className="mt-4"> <h4 className="text-md font-semibold text-gray-800 mb-2">Permissions</h4> {Object.entries(formik.values.permissions).map(([sectionKey, section]) => ( <div key={sectionKey} className="mb-4 border rounded-lg"> <div className="bg-gray-50 p-2 font-semibold capitalize">{sectionKey}</div> <div className="p-4"> {section.subMenus ? ( Object.entries(section.subMenus).map(([subKey, subPerms]) => ( <div key={subKey} className="grid grid-cols-5 gap-2 mb-2"> <div>{subKey}</div> {['read', 'write', 'update', 'delete'].map((perm) => ( <div key={perm}> <label> <input type="checkbox" checked={subPerms[perm]} onChange={() => handlePermissionChange(sectionKey, subKey, perm)} /> {perm} </label> </div> ))} </div> )) ) : ( <div className="grid grid-cols-5 gap-2"> <div>General</div> {['read', 'write', 'update', 'delete'].map((perm) => ( <div key={perm}> <label> <input type="checkbox" checked={section[perm]} onChange={() => handlePermissionChange(sectionKey, null, perm)} /> {perm} </label> </div> ))} </div> )} </div> </div> ))} </div> <div className="mt-6"> <button type="submit" className="w-full bg-blue-600 text-white py-2 px-4 rounded-md shadow hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500" > {manager ? 'Update Manager' : 'Save Manager'} </button> </div> </form> </div> </div> ); }; export default AddEditManagerModal; make this design better make