From d7ddbbbb702be0772e30a3350160bcd4ccbcdd78 Mon Sep 17 00:00:00 2001 From: Lixian Zhou Date: Mon, 16 Mar 2026 16:30:17 -0400 Subject: [PATCH] fix --- TITLE.md | 110 ++++++++++++++++++ .../src/components/employees/EmployeeList.js | 4 +- .../employees/ExternalEmployeesImport.js | 4 +- client/src/components/home/layout.js | 3 +- .../src/shared/constants/hr-title.constant.js | 91 +++++++++++++++ client/src/shared/constants/index.js | 1 + 6 files changed, 208 insertions(+), 5 deletions(-) create mode 100644 TITLE.md create mode 100644 client/src/shared/constants/hr-title.constant.js diff --git a/TITLE.md b/TITLE.md new file mode 100644 index 0000000..de1c550 --- /dev/null +++ b/TITLE.md @@ -0,0 +1,110 @@ +# HR Title Display Mapping + +This change adds standardized display names for HR user titles and applies them consistently in the UI. + +## What Was Added + +- A centralized title mapping constant and formatter: + - `client/src/shared/constants/hr-title.constant.js` + - `HR_TITLE_DISPLAY_MAP` + - `getHrTitleDisplayName(titleValue)` + +- Shared export: + - `client/src/shared/constants/index.js` + +## Where It Is Used + +- Top-right user profile title: + - `client/src/components/home/layout.js` + +- HR user title column on **All Employees**: + - `client/src/components/employees/EmployeeList.js` + +- HR user title column on **Add New Employee From HR System**: + - `client/src/components/employees/ExternalEmployeesImport.js` + +## Behavior + +- Known HR title codes (e.g. `IT_SPECIALIST`) are displayed as mapped names (e.g. `IT Specialist`). +- Unknown underscore-based codes fall back to a readable format (e.g. `CUSTOM_CODE_NAME` -> `Custom Code Name`). +- Empty title values remain empty. + +## Title Mapping List + +```text +ACTIVITY_ASSISTANT:Activity Assistant +ACTIVITY_COORDINATOR:Activity Coordinator +ACTIVITY_DIRECTOR:Activity Manager +ACTIVITY_SPECIALIST:Activity Specialist +ADMINISTRATION_ASSISTANT:Administration Assistant +ADMINISTRATOR:Administrator +ASSISTANT_PROGRAM_DIRECTOR:Assistant Program Director +BILLING_MANAGER:Billing Manager +BUILDING_ENGINEER:Building Engineer +BUSINESS_DEVELOPMENT_SPECIALIST:Business Development Specialist +BUSINESS_INTELLIGENCE_ANALYST:Business Intelligence Analyst +CAREGIVER:Caregiver +CENTER_COORDINATOR:Center Coordinator +CERTIFIED_MEDICATION_TECHNICIAN:Certified Medication Technician +CERTIFIED_NURSE_ASSISTANT:CNA +CEO:CEO +CFO:CFO +CHEF:Chef +CHEF_ASSISTANT:Chef Assistant +COMPLIANCE_MANAGER:Compliance Manager +COO:COO +DEPUTY_CENTER_DIRECTOR:Deputy Center Director +DIRECTOR_OF_ACCOUNTING:Director of Accounting +DIRECTOR_OF_OPERATIONS:Director of Operations +DRIVER:Driver +DRIVER_TEAM_LEAD:Driver Team Lead +EXECUTIVE_ASSISTANT:Executive Assistant +EXECUTIVE_CHEF:Executive Chef +FINANCE_ADMIN_MANAGER:Finance & Administration Manager +FINANCIAL_ANALYST:Financial Analyst +FLEET_MANAGEMENT_SPECIALIST:Fleet Management Specialist +FLEET_MANAGER:Fleet Manager +FOOD_SERVICE_DIRECTOR:Food Service Director +FOOD_SERVICES_COORDINATOR:Food Service Coordinator +HANDYMAN:Handyman +HEAD_NURSE:Nursing Manager +HR:HR +HR_AND_ADMINISTRATIVE_COORDINATOR:HR & Administrative Coordinator +INTERN:Intern +IT_SPECIALIST:IT Specialist +IT_SUPPORT:IT Support +JANITOR:Janitor +KITCHEN_ASSISTANT:Kitchen Staff +KITCHEN_HELPER:Kitchen Helper +KITCHEN_MANAGER:Kitchen Manager +LOBBY_ASSISTANT:Lobby Assistant +LOBBY_MANAGER:Lobby Manager +MARKETING_SPECIALIST:Marketing Specialist +MEDICAL_APPOINTMENT_COORDINATOR:Medical Appointment Coordinator +MEDICAL_APPOINTMENT_SCHEDULER:Medical Appointment Scheduler +MEDICAL_DRIVER:Medical Driver +NURSING_DIRECTOR:Nursing Director +OFFICE_MANAGER:Office Manager +OPRATIONS_DIRECTOR:Center Director +PASTRY_CHEF:Pastry Chef +PRESIDENT:President +PROCESS_ASSISTANT:Program Assistant +PROGRAM_ASSISTANT:Program Assistant +PROGRAM_ASSISTANT_DRIVER:Program Assistant - Driver +PROGRAM_ASSISTANT_MEDICAL_DRIVER:Program Assistant - Medical Driver +PROGRAM_ASSISTANT_MEDICAL_DRIVER_LEAD:Program Assistant - Medical Driver Lead +PROGRAM_DIRECTOR:Program Director +PROJECT_ASSISTANT:Project Assistant +PROJECT_DIRECTOR:Project Director +QUALITY_CONTROL_SPECIALIST:Quality Control Specialist +REGISTERED_NURSE:Registered Nurse +SOCIAL_AND_COMMUNITY_SERVICE_MANAGER:Social and Community Service Manager +SOCIAL_WORK:Social Work +SOCIAL_WORK_ASSISTANT:Social Work Assistant +SOCIAL_WORK_DIRECTOR:Social Work Director +SOCIAL_WORKER_MANAGER:Social Work Manager +SPIRITUAL_CARE_SPECIALIST:Spiritual Care Specialist +TRANSPORTATION_COORDINATOR:Transportation Coordinator +TRANSPORTATION_DIRECTOR:Transportation Manager +VP:VP +``` diff --git a/client/src/components/employees/EmployeeList.js b/client/src/components/employees/EmployeeList.js index dab6a13..6f46ab3 100644 --- a/client/src/components/employees/EmployeeList.js +++ b/client/src/components/employees/EmployeeList.js @@ -2,7 +2,7 @@ import React, { useMemo, useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { Button, Modal, Spinner } from "react-bootstrap"; import { AuthService, EmployeeService, EventsService } from "../../services"; -import { EMPLOYEE_PERMISSION_GROUPS } from "../../shared"; +import { EMPLOYEE_PERMISSION_GROUPS, getHrTitleDisplayName } from "../../shared"; const SYSTEM_ACCESS_PERMISSION = "System Access"; @@ -248,7 +248,7 @@ const EmployeeList = () => { {hrUser?.username} {hrUser?.name} - {hrUser?.title || '-'} + {getHrTitleDisplayName(hrUser?.title || '-')} {hrUser?.allow_site || currentSite} {configuredPermissions.length > 0 ? configuredPermissions.join(', ') : '-'} diff --git a/client/src/components/employees/ExternalEmployeesImport.js b/client/src/components/employees/ExternalEmployeesImport.js index f607c6c..a04d815 100644 --- a/client/src/components/employees/ExternalEmployeesImport.js +++ b/client/src/components/employees/ExternalEmployeesImport.js @@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from "react"; import { useNavigate } from "react-router-dom"; import { Button, Modal, Spinner } from "react-bootstrap"; import { AuthService, EmployeeService, EventsService } from "../../services"; -import { EMPLOYEE_PERMISSION_GROUPS } from "../../shared"; +import { EMPLOYEE_PERMISSION_GROUPS, getHrTitleDisplayName } from "../../shared"; const SYSTEM_ACCESS_PERMISSION = "System Access"; @@ -219,7 +219,7 @@ const ExternalEmployeesImport = () => { {item?.username} {item?.name} - {item?.title} + {getHrTitleDisplayName(item?.title)} {item?.site} {(() => { diff --git a/client/src/components/home/layout.js b/client/src/components/home/layout.js index 63cfb4d..18b07d6 100644 --- a/client/src/components/home/layout.js +++ b/client/src/components/home/layout.js @@ -1,6 +1,7 @@ import { Bell, ChevronDown, PersonCircle } from 'react-bootstrap-icons'; import { Outlet, useLocation, Navigate } from 'react-router-dom'; import { AuthService } from '../../services'; +import { getHrTitleDisplayName } from '../../shared'; import SideMenu from './menu'; import { Dropdown } from "react-bootstrap"; @@ -9,7 +10,7 @@ function Layout() { const showMenu = location.pathname !== '/login' && location.pathname !== '/landing'; // Example: Hide menu on login page const userRaw = localStorage.getItem('user'); const user = userRaw ? JSON.parse(userRaw) : null; - const displayTitle = (user?.title || user?.roles?.[0] || '').toString(); + const displayTitle = getHrTitleDisplayName((user?.title || user?.roles?.[0] || '').toString()); const getLogoSuffix = () => { return (window.location.hostname.includes('worldshine2.mayo.llc') || window.location.hostname.includes('site2') || window.location.host.includes('ws2') ||window.location.hostname.includes('localhost')) ? "Care LLC" : ((window.location.hostname.includes('worldshine3.mayo.llc') ||window.location.hostname.includes('site3') || window.location.hostname.includes('ws3')) ? "Cloverleaf LLC" : "International LLC"); } diff --git a/client/src/shared/constants/hr-title.constant.js b/client/src/shared/constants/hr-title.constant.js new file mode 100644 index 0000000..22e8dda --- /dev/null +++ b/client/src/shared/constants/hr-title.constant.js @@ -0,0 +1,91 @@ +export const HR_TITLE_DISPLAY_MAP = { + ACTIVITY_ASSISTANT: "Activity Assistant", + ACTIVITY_COORDINATOR: "Activity Coordinator", + ACTIVITY_DIRECTOR: "Activity Manager", + ACTIVITY_SPECIALIST: "Activity Specialist", + ADMINISTRATION_ASSISTANT: "Administration Assistant", + ADMINISTRATOR: "Administrator", + ASSISTANT_PROGRAM_DIRECTOR: "Assistant Program Director", + BILLING_MANAGER: "Billing Manager", + BUILDING_ENGINEER: "Building Engineer", + BUSINESS_DEVELOPMENT_SPECIALIST: "Business Development Specialist", + BUSINESS_INTELLIGENCE_ANALYST: "Business Intelligence Analyst", + CAREGIVER: "Caregiver", + CENTER_COORDINATOR: "Center Coordinator", + CERTIFIED_MEDICATION_TECHNICIAN: "Certified Medication Technician", + CERTIFIED_NURSE_ASSISTANT: "CNA", + CEO: "CEO", + CFO: "CFO", + CHEF: "Chef", + CHEF_ASSISTANT: "Chef Assistant", + COMPLIANCE_MANAGER: "Compliance Manager", + COO: "COO", + DEPUTY_CENTER_DIRECTOR: "Deputy Center Director", + DIRECTOR_OF_ACCOUNTING: "Director of Accounting", + DIRECTOR_OF_OPERATIONS: "Director of Operations", + DRIVER: "Driver", + DRIVER_TEAM_LEAD: "Driver Team Lead", + EXECUTIVE_ASSISTANT: "Executive Assistant", + EXECUTIVE_CHEF: "Executive Chef", + FINANCE_ADMIN_MANAGER: "Finance & Administration Manager", + FINANCIAL_ANALYST: "Financial Analyst", + FLEET_MANAGEMENT_SPECIALIST: "Fleet Management Specialist", + FLEET_MANAGER: "Fleet Manager", + FOOD_SERVICE_DIRECTOR: "Food Service Director", + FOOD_SERVICES_COORDINATOR: "Food Service Coordinator", + HANDYMAN: "Handyman", + HEAD_NURSE: "Nursing Manager", + HR: "HR", + HR_AND_ADMINISTRATIVE_COORDINATOR: "HR & Administrative Coordinator", + INTERN: "Intern", + IT_SPECIALIST: "IT Specialist", + IT_SUPPORT: "IT Support", + JANITOR: "Janitor", + KITCHEN_ASSISTANT: "Kitchen Staff", + KITCHEN_HELPER: "Kitchen Helper", + KITCHEN_MANAGER: "Kitchen Manager", + LOBBY_ASSISTANT: "Lobby Assistant", + LOBBY_MANAGER: "Lobby Manager", + MARKETING_SPECIALIST: "Marketing Specialist", + MEDICAL_APPOINTMENT_COORDINATOR: "Medical Appointment Coordinator", + MEDICAL_APPOINTMENT_SCHEDULER: "Medical Appointment Scheduler", + MEDICAL_DRIVER: "Medical Driver", + NURSING_DIRECTOR: "Nursing Director", + OFFICE_MANAGER: "Office Manager", + OPRATIONS_DIRECTOR: "Center Director", + PASTRY_CHEF: "Pastry Chef", + PRESIDENT: "President", + PROCESS_ASSISTANT: "Program Assistant", + PROGRAM_ASSISTANT: "Program Assistant", + PROGRAM_ASSISTANT_DRIVER: "Program Assistant - Driver", + PROGRAM_ASSISTANT_MEDICAL_DRIVER: "Program Assistant - Medical Driver", + PROGRAM_ASSISTANT_MEDICAL_DRIVER_LEAD: "Program Assistant - Medical Driver Lead", + PROGRAM_DIRECTOR: "Program Director", + PROJECT_ASSISTANT: "Project Assistant", + PROJECT_DIRECTOR: "Project Director", + QUALITY_CONTROL_SPECIALIST: "Quality Control Specialist", + REGISTERED_NURSE: "Registered Nurse", + SOCIAL_AND_COMMUNITY_SERVICE_MANAGER: "Social and Community Service Manager", + SOCIAL_WORK: "Social Work", + SOCIAL_WORK_ASSISTANT: "Social Work Assistant", + SOCIAL_WORK_DIRECTOR: "Social Work Director", + SOCIAL_WORKER_MANAGER: "Social Work Manager", + SPIRITUAL_CARE_SPECIALIST: "Spiritual Care Specialist", + TRANSPORTATION_COORDINATOR: "Transportation Coordinator", + TRANSPORTATION_DIRECTOR: "Transportation Manager", + VP: "VP" +}; + +export const getHrTitleDisplayName = (titleValue) => { + const raw = `${titleValue || ""}`.trim(); + if (!raw) return ""; + if (HR_TITLE_DISPLAY_MAP[raw]) return HR_TITLE_DISPLAY_MAP[raw]; + if (raw.includes("_")) { + return raw + .toLowerCase() + .split("_") + .map((part) => (part ? part[0].toUpperCase() + part.slice(1) : "")) + .join(" "); + } + return raw; +}; diff --git a/client/src/shared/constants/index.js b/client/src/shared/constants/index.js index 87c5f63..ff89887 100644 --- a/client/src/shared/constants/index.js +++ b/client/src/shared/constants/index.js @@ -1,6 +1,7 @@ export * from "./customer.constant"; export * from "./route-status.constant"; export * from "./employee.constant"; +export * from "./hr-title.constant"; export * from "./report.constant"; export * from "./vehicle.constant"; export * from "./resource.constant"; \ No newline at end of file