diff --git a/client/src/components/customers/ViewCustomer.js b/client/src/components/customers/ViewCustomer.js index a2227fa..defcfec 100644 --- a/client/src/components/customers/ViewCustomer.js +++ b/client/src/components/customers/ViewCustomer.js @@ -36,10 +36,7 @@ const ViewCustomer = () => { const [activeTab, setActiveTab] = useState(normalizedInitialTab || 'personalInfo'); const [formFiles, setFormFiles] = useState({}); const customerTabOrder = ['personalInfo', 'careServices', 'medicalInsurance', 'confidentialDetails', 'formSubmission']; - const canAccessCustomerTab = (tabKey) => { - return AuthService.canViewCustomerTab(tabKey) || AuthService.canEditCustomerTab(tabKey); - }; - const visibleTabs = customerTabOrder.filter((tabKey) => canAccessCustomerTab(tabKey)); + const visibleTabs = customerTabOrder.filter((tabKey) => AuthService.canViewCustomerTab(tabKey)); const firstVisibleTab = visibleTabs[0] || 'personalInfo'; @@ -162,7 +159,7 @@ const ViewCustomer = () => {
setActiveTab(k)} id="customers-tab"> - {canAccessCustomerTab('personalInfo') && + {AuthService.canViewCustomerTab('personalInfo') && {/* Basic Info Section */}
Basic Info
@@ -564,7 +561,7 @@ const ViewCustomer = () => {
} - {canAccessCustomerTab('careServices') && + {AuthService.canViewCustomerTab('careServices') &&
Care & Services
@@ -609,7 +606,7 @@ const ViewCustomer = () => {
} - {canAccessCustomerTab('medicalInsurance') && + {AuthService.canViewCustomerTab('medicalInsurance') && {/* Providers Section */}
Providers
@@ -705,7 +702,7 @@ const ViewCustomer = () => {
} - {canAccessCustomerTab('confidentialDetails') && + {AuthService.canViewCustomerTab('confidentialDetails') &&
Confidential Details
@@ -728,7 +725,7 @@ const ViewCustomer = () => { } - {canAccessCustomerTab('formSubmission') && + {AuthService.canViewCustomerTab('formSubmission') && {/* Admission Forms Section */}
Admission Forms
diff --git a/client/src/components/employees/UpdateEmployee.js b/client/src/components/employees/UpdateEmployee.js index 4257ad4..7652c89 100644 --- a/client/src/components/employees/UpdateEmployee.js +++ b/client/src/components/employees/UpdateEmployee.js @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from "react"; +import React, {useState, useEffect, useMemo} from "react"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate, useParams } from "react-router-dom"; import { driverSlice } from "./../../store"; @@ -41,6 +41,56 @@ const UpdateEmployee = () => { const [selectedFile, setSelectedFile] = useState(); const isAlwaysAllPermissionsUser = (value) => (value || '').toString().trim().toLowerCase() === 'testadmin03'; const isSuperPermissionLocked = isAlwaysAllPermissionsUser(username || currentEmployee?.username); + const permissionPairMaps = useMemo(() => { + const VIEW_PREFIXES = ['View_', 'View _']; + const EDIT_PREFIXES = ['Edit_', 'Edit&Create ', 'Create&Edit ', 'Edit & Create_', 'Create & Edit _']; + const normalizePairId = (value) => `${value || ''}`.replace(/\s*_\s*/g, '_').replace(/\s+/g, ' ').trim().toLowerCase(); + const parsePermission = (permissionKey) => { + const matchedViewPrefix = VIEW_PREFIXES.find((prefix) => permissionKey.startsWith(prefix)); + if (matchedViewPrefix) { + return { type: 'view', pairId: normalizePairId(permissionKey.slice(matchedViewPrefix.length)) }; + } + const matchedEditPrefix = EDIT_PREFIXES.find((prefix) => permissionKey.startsWith(prefix)); + if (matchedEditPrefix) { + return { type: 'edit', pairId: normalizePairId(permissionKey.slice(matchedEditPrefix.length)) }; + } + return null; + }; + + const viewByPairId = new Map(); + const editsByPairId = new Map(); + EMPLOYEE_ALL_PERMISSIONS.forEach((permissionKey) => { + const parsed = parsePermission(permissionKey); + if (!parsed) return; + if (parsed.type === 'view') { + viewByPairId.set(parsed.pairId, permissionKey); + return; + } + const currentEdits = editsByPairId.get(parsed.pairId) || []; + editsByPairId.set(parsed.pairId, [...currentEdits, permissionKey]); + }); + + return { parsePermission, viewByPairId, editsByPairId }; + }, []); + + const enforcePermissionPairRules = (permissionList = []) => { + const nextSet = new Set(permissionList); + const nextList = Array.from(nextSet); + nextList.forEach((permissionKey) => { + const parsed = permissionPairMaps.parsePermission(permissionKey); + if (!parsed || parsed.type !== 'edit') return; + const pairedView = permissionPairMaps.viewByPairId.get(parsed.pairId); + if (pairedView) { + nextSet.add(pairedView); + } + }); + permissionPairMaps.viewByPairId.forEach((viewPermission, pairId) => { + if (nextSet.has(viewPermission)) return; + const editPermissions = permissionPairMaps.editsByPairId.get(pairId) || []; + editPermissions.forEach((editPermission) => nextSet.delete(editPermission)); + }); + return Array.from(nextSet); + }; const params = new URLSearchParams(window.location.search); const redirectTo = () => { const redirect = params.get('redirect'); @@ -115,9 +165,9 @@ const UpdateEmployee = () => { if (isSuperPermissionLocked) return; setPermissions((prevPermissions) => { if (prevPermissions.includes(permissionKey)) { - return prevPermissions.filter((permission) => permission !== permissionKey); + return enforcePermissionPairRules(prevPermissions.filter((permission) => permission !== permissionKey)); } - return [...prevPermissions, permissionKey]; + return enforcePermissionPairRules([...prevPermissions, permissionKey]); }); }; @@ -127,10 +177,10 @@ const UpdateEmployee = () => { const togglePermissionGroup = (permissionItems = [], checked) => { if (isSuperPermissionLocked) return; if (checked) { - setPermissions((prevPermissions) => Array.from(new Set([...prevPermissions, ...permissionItems]))); + setPermissions((prevPermissions) => enforcePermissionPairRules(Array.from(new Set([...prevPermissions, ...permissionItems])))); return; } - setPermissions((prevPermissions) => prevPermissions.filter((permission) => !permissionItems.includes(permission))); + setPermissions((prevPermissions) => enforcePermissionPairRules(prevPermissions.filter((permission) => !permissionItems.includes(permission)))); }; const triggerShowDeleteModal = () => {