diff --git a/client/src/components/customers/CustomersList.js b/client/src/components/customers/CustomersList.js index b4f5e5c..1d6ca60 100644 --- a/client/src/components/customers/CustomersList.js +++ b/client/src/components/customers/CustomersList.js @@ -8,7 +8,34 @@ import DashboardCustomersList from "../dashboard/DashboardCustomersList"; const CustomersList = () => { const navigate = useNavigate(); const [customers, setCustomers] = useState([]); - const [columns] = useState([ + const CUSTOMER_LIST_COLUMN_TAB_MAP = { + name: 'personalInfo', + chinese_name: 'personalInfo', + email: 'personalInfo', + type: 'careServices', + pickup_status: 'careServices', + birth_date: 'personalInfo', + gender: 'personalInfo', + language: 'personalInfo', + medicare_number: 'medicalInsurance', + medicaid_number: 'medicalInsurance', + address: 'personalInfo', + phone: 'personalInfo', + emergency_contact: 'medicalInsurance', + health_condition: 'medicalInsurance', + payment_status: 'careServices', + payment_due_date: 'careServices', + service_requirement: 'careServices', + tags: 'personalInfo' + }; + const getVisibleColumnsByPermission = (columnList = []) => { + return columnList.filter((column) => { + const mappedTab = CUSTOMER_LIST_COLUMN_TAB_MAP[column.key]; + if (!mappedTab) return true; + return AuthService.canViewCustomerTab(mappedTab); + }); + }; + const [columns] = useState(getVisibleColumnsByPermission([ { key: 'name', label:'Name', show: true }, { key: 'chinese_name', label: 'Preferred Name', show: true }, { key: 'email', label: 'Email', show: true }, @@ -27,7 +54,7 @@ const CustomersList = () => { { key: 'payment_due_date', label: 'Payment Due Date', show: true }, { key: 'service_requirement', label: 'Service Requirement', show: true }, { key: 'tags', label: 'Tags', show: true } - ]); + ])); useEffect(() => { if (!AuthService.canViewCustomers()) { diff --git a/client/src/components/dashboard/DashboardCustomersList.js b/client/src/components/dashboard/DashboardCustomersList.js index 42a7c36..1a12178 100644 --- a/client/src/components/dashboard/DashboardCustomersList.js +++ b/client/src/components/dashboard/DashboardCustomersList.js @@ -8,6 +8,29 @@ import { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab, Dropdown, Modal } from import { Columns, Download, Filter, PencilSquare, PersonSquare, Plus } from "react-bootstrap-icons"; const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, title = null }) => { + const CUSTOMER_LIST_COLUMN_TAB_MAP = { + name: 'personalInfo', + chinese_name: 'personalInfo', + email: 'personalInfo', + type: 'careServices', + pickup_status: 'careServices', + birth_date: 'personalInfo', + gender: 'personalInfo', + language: 'personalInfo', + medicare_number: 'medicalInsurance', + medicaid_number: 'medicalInsurance', + address: 'personalInfo', + phone: 'personalInfo', + emergency_contact: 'medicalInsurance', + tags: 'personalInfo' + }; + const getVisibleColumnsByPermission = (columnList = []) => { + return columnList.filter((column) => { + const mappedTab = CUSTOMER_LIST_COLUMN_TAB_MAP[column.key]; + if (!mappedTab) return true; + return AuthService.canViewCustomerTab(mappedTab); + }); + }; const navigate = useNavigate(); const dispatch = useDispatch(); const site = EventsService.site; @@ -33,7 +56,7 @@ const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, tit const [avatarLoading, setAvatarLoading] = useState(false); const [customerAvatars, setCustomerAvatars] = useState({}); const isAllCustomersPage = title === 'All Customers'; - const [columns, setColumns] = useState([ + const [columns, setColumns] = useState(getVisibleColumnsByPermission([ { key: 'name', label:'Name', @@ -104,7 +127,11 @@ const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, tit label: 'Tags', show: true } - ]); + ])); + useEffect(() => { + setColumns((prevColumns) => getVisibleColumnsByPermission(prevColumns)); + }, []); + useEffect(() => { if (!AuthService.canViewCustomers()) { @@ -257,7 +284,7 @@ const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, tit }; const handleColumnsChange = (newColumns) => { - setColumns(newColumns); + setColumns(getVisibleColumnsByPermission(newColumns)); } const goToEdit = (id) => { diff --git a/client/src/components/home/menu.js b/client/src/components/home/menu.js index 82f798a..2680581 100644 --- a/client/src/components/home/menu.js +++ b/client/src/components/home/menu.js @@ -139,7 +139,7 @@ const SideMenu = () => { name: 'Templates', link: '/trans-routes/daily-templates/list', category: '/trans-routes/daily-templates', - roleFunc: AuthService.canViewRoutes + roleFunc: () => AuthService.canViewRouteTemplates() || AuthService.canEditRouteTemplates() }, { name: 'Appointment One-Day List', @@ -194,7 +194,7 @@ const SideMenu = () => { name: 'Template', link: '/medical/template', category: '/medical/template', - roleFunc: AuthService.canViewMedicalSection + roleFunc: AuthService.canViewMedicalTemplate } ] }, diff --git a/client/src/components/medical/TemplateManager.js b/client/src/components/medical/TemplateManager.js index eeb9545..74bd5c1 100644 --- a/client/src/components/medical/TemplateManager.js +++ b/client/src/components/medical/TemplateManager.js @@ -22,7 +22,7 @@ const TemplateManager = () => { }; useEffect(() => { - if (!AuthService.canViewMedicalSection()) { + if (!AuthService.canViewMedicalTemplate()) { window.alert("You haven't login yet OR this user does not have access to this page. Please change an admin account to login."); AuthService.logout(); navigate("/login"); diff --git a/client/src/components/trans-routes/RouteCustomerEditor.js b/client/src/components/trans-routes/RouteCustomerEditor.js index 262dff9..29e5cc8 100644 --- a/client/src/components/trans-routes/RouteCustomerEditor.js +++ b/client/src/components/trans-routes/RouteCustomerEditor.js @@ -94,7 +94,7 @@ const Card = ({ content, index, moveCard }) => { ) } -const RouteCustomerEditor = ({currentRoute, setNewCustomerList = (a) => {}, viewMode, editFun, onAddCustomer = null, scheduledAbsentCustomerIds = []}) => { +const RouteCustomerEditor = ({currentRoute, setNewCustomerList = (a) => {}, viewMode, editFun = () => {}, canEdit = true, onAddCustomer = null, scheduledAbsentCustomerIds = []}) => { const [customers, setCustomers] = useState([]); const [initializedRouteId, setInitializedRouteId] = useState(null); const [showAddPersonnelModal, setShowAddPersonnelModal] = useState(false); @@ -713,7 +713,7 @@ const RouteCustomerEditor = ({currentRoute, setNewCustomerList = (a) => {}, view return ( { !viewMode &&
Customers Assigned ({getCurrentAssignedNumber()})
} - { viewMode &&
Route Assignment
} + { viewMode &&
Route Assignment {canEdit && }
} {!viewMode && {customers.map((item, index) => { if (item?.customers) { @@ -763,7 +763,7 @@ const RouteCustomerEditor = ({currentRoute, setNewCustomerList = (a) => {}, view if (item?.customers) { return
{`Stop ${index+1}`}
-
openEditAptGroupModal(index, item)}> +
canEdit && openEditAptGroupModal(index, item)} style={{ cursor: canEdit ? 'pointer' : 'default' }}> {item.customer_group} {item.customers[0]?.customer_group_address}
{item.customers.map(customer =>
diff --git a/client/src/components/trans-routes/RouteView.js b/client/src/components/trans-routes/RouteView.js index b8a35ff..2da34b2 100644 --- a/client/src/components/trans-routes/RouteView.js +++ b/client/src/components/trans-routes/RouteView.js @@ -60,6 +60,7 @@ const RouteView = () => { }; const routeForStatusView = mergeRouteCustomerMeta(latestRouteForStatus || routeSnapshot || currentRoute); const routeForAssignmentView = routeSnapshot || currentRoute; + const canEditRoutes = AuthService.canAddOrEditRoutes(); const closeModal = () => { setShowVehicleDetails(false); } @@ -81,6 +82,7 @@ const RouteView = () => { navigate(`/trans-routes/dashboard?dateSchedule=${moment(currentRoute?.schedule_date).format('YYYY-MM-DD')}`); } const edit = (editSection) => { + if (!canEditRoutes) return; if (scheduleDate) { navigate(`/trans-routes/edit/${currentRoute?.id}?dateSchedule=${scheduleDate}&editSection=${editSection}`) } else { @@ -227,7 +229,7 @@ const RouteView = () => {
-
Route Details
+
Route Details {canEditRoutes && }
Route Name
@@ -299,7 +301,7 @@ const RouteView = () => { {currentRoute && currentRoute?.checklist_result.length === 0 && <>No Checklist found}
- +
@@ -333,7 +335,7 @@ const RouteView = () => {
- {routeForStatusView && } + {routeForStatusView && }
diff --git a/client/src/components/trans-routes/RoutesHistory.js b/client/src/components/trans-routes/RoutesHistory.js index 20ac4d4..99837dd 100644 --- a/client/src/components/trans-routes/RoutesHistory.js +++ b/client/src/components/trans-routes/RoutesHistory.js @@ -66,7 +66,7 @@ const RoutesHistory = () => {
- +
diff --git a/client/src/components/trans-routes/ViewDailyTemplate.js b/client/src/components/trans-routes/ViewDailyTemplate.js index 9724ba8..aeb1235 100644 --- a/client/src/components/trans-routes/ViewDailyTemplate.js +++ b/client/src/components/trans-routes/ViewDailyTemplate.js @@ -1,7 +1,7 @@ import React, {useState, useEffect} from "react"; import { useParams, useNavigate } from "react-router-dom"; import { useSelector } from "react-redux"; -import { DailyRoutesTemplateService } from "../../services"; +import { AuthService, DailyRoutesTemplateService } from "../../services"; import { Breadcrumb, Modal, Button, Spinner } from "react-bootstrap"; import { PencilSquare, Trash } from "react-bootstrap-icons"; import RoutesSection from "./RoutesSection"; @@ -20,6 +20,7 @@ const ViewDailyTemplate = () => { const [newName, setNewName] = useState(''); const [saving, setSaving] = useState(false); const [deleting, setDeleting] = useState(false); + const canEditTemplateRoutes = AuthService.canEditRouteTemplates(); useEffect(() => { fetchTemplate(); @@ -44,6 +45,7 @@ const ViewDailyTemplate = () => { }; const openEditNameModal = () => { + if (!canEditTemplateRoutes) return; setShowEditNameModal(true); }; @@ -77,6 +79,7 @@ const ViewDailyTemplate = () => { }; const confirmDelete = () => { + if (!canEditTemplateRoutes) return; setShowDeleteModal(true); }; @@ -93,6 +96,7 @@ const ViewDailyTemplate = () => { }; const goToCreateRoute = (type) => { + if (!canEditTemplateRoutes) return; navigate(`/trans-routes/daily-templates/${params.id}/create-route?type=${type}`); }; @@ -121,16 +125,16 @@ const ViewDailyTemplate = () => {

{template.name} - + />} - + }

Template Date: {template.template_date} | Created by: {template.create_by} @@ -149,7 +153,7 @@ const ViewDailyTemplate = () => { onRouteClick={handleRouteClick} isTemplate={true} templateId={params.id} - canAddNew={true} + canAddNew={canEditTemplateRoutes} addText="+Add Route" redirect={goToCreateRoute} routeType="inbound" @@ -165,7 +169,7 @@ const ViewDailyTemplate = () => { onRouteClick={handleRouteClick} isTemplate={true} templateId={params.id} - canAddNew={true} + canAddNew={canEditTemplateRoutes} addText="+Add Route" redirect={goToCreateRoute} routeType="outbound" diff --git a/client/src/components/trans-routes/ViewDailyTemplateRoute.js b/client/src/components/trans-routes/ViewDailyTemplateRoute.js index 4e7564d..f1fc0b4 100644 --- a/client/src/components/trans-routes/ViewDailyTemplateRoute.js +++ b/client/src/components/trans-routes/ViewDailyTemplateRoute.js @@ -1,7 +1,7 @@ import React, {useState, useEffect} from "react"; import { useSelector } from "react-redux"; import { useParams, useNavigate } from "react-router-dom"; -import { DailyRoutesTemplateService } from "../../services"; +import { AuthService, DailyRoutesTemplateService } from "../../services"; import { selectAllActiveDrivers, selectAllActiveVehicles } from "./../../store"; import { Breadcrumb, Spinner, Modal, Button } from "react-bootstrap"; import { Pencil, Trash } from "react-bootstrap-icons"; @@ -16,6 +16,7 @@ const ViewDailyTemplateRoute = () => { const [currentRoute, setCurrentRoute] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); const [deleting, setDeleting] = useState(false); + const canEditTemplateRoutes = AuthService.canEditRouteTemplates(); const currentVehicle = vehicles.find(item => item.id === currentRoute?.vehicle); const currentDriver = drivers.find(item => item.id === currentRoute?.driver); @@ -37,10 +38,12 @@ const ViewDailyTemplateRoute = () => { }; const goToEdit = () => { + if (!canEditTemplateRoutes) return; navigate(`/trans-routes/daily-templates/${params.id}/update-route/${params.routeId}`); }; const confirmDelete = () => { + if (!canEditTemplateRoutes) return; setShowDeleteModal(true); }; @@ -125,14 +128,14 @@ const ViewDailyTemplateRoute = () => {
- - } + {canEditTemplateRoutes && + }
@@ -140,6 +143,7 @@ const ViewDailyTemplateRoute = () => { currentRoute={currentRoute} viewMode={true} editFun={() => goToEdit()} + canEdit={canEditTemplateRoutes} />
diff --git a/client/src/services/AuthService.js b/client/src/services/AuthService.js index 8b26981..1ac8038 100644 --- a/client/src/services/AuthService.js +++ b/client/src/services/AuthService.js @@ -194,6 +194,10 @@ const canEditAppointmentRequests = () => { return hasPermission('Edit & Create_Appointment Request'); } +const canViewMedicalTemplate = () => { + return hasPermission('Medical Template'); +} + const canViewMedicalEvents = () => { return hasAnyPermission([ 'View _Calendar _Medical Appointment', @@ -365,6 +369,7 @@ export const AuthService = { canEditProviderInfo, canViewAppointmentRequests, canEditAppointmentRequests, + canViewMedicalTemplate, canViewMedicalEvents, canEditMedicalEvents, canViewMealStatus,