feature/IO-1113-Online-Dark-Mode - Toggle / Local storage solution

This commit is contained in:
Dave Richer
2025-08-08 11:53:51 -04:00
parent c9572d2db5
commit ec6c0279de
10 changed files with 131 additions and 41 deletions

View File

@@ -25,7 +25,7 @@ import {
UsergroupAddOutlined,
UserOutlined
} from "@ant-design/icons";
import { FaCalendarAlt, FaCarCrash, FaTasks } from "react-icons/fa";
import { FaCalendarAlt, FaCarCrash, FaMoon, FaSun, FaTasks } from "react-icons/fa";
import { BsKanban } from "react-icons/bs";
import { FiLogOut } from "react-icons/fi";
import { GiPlayerTime, GiSettingsKnobs } from "react-icons/gi";
@@ -33,6 +33,7 @@ import { RiSurveyLine } from "react-icons/ri";
import { IoBusinessOutline } from "react-icons/io5";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import LockWrapper from "../../components/lock-wrapper/lock-wrapper.component.jsx";
import { Tooltip } from "antd";
const buildLeftMenuItems = ({
t,
@@ -41,7 +42,9 @@ const buildLeftMenuItems = ({
setTaskUpsertContext,
setReportCenterContext,
signOutStart,
accountingChildren
accountingChildren,
handleDarkModeToggle,
darkMode
}) => {
return [
{
@@ -331,6 +334,15 @@ const buildLeftMenuItems = ({
label: t("user.actions.signout"),
onClick: () => signOutStart()
},
{
key: "darkmode-toggle",
id: "header-darkmode-toggle",
label: darkMode ? t("user.actions.light_theme") : t("user.actions.dark_theme"),
icon: (
<Tooltip title={darkMode ? t("Light mode") : t("Dark mode")}>{darkMode ? <FaSun /> : <FaMoon />}</Tooltip>
),
onClick: handleDarkModeToggle
},
{
key: "help",
id: "header-help",

View File

@@ -12,7 +12,7 @@ import { createStructuredSelector } from "reselect";
import { TASKS_CENTER_POLL_INTERVAL, useSocket } from "../../contexts/SocketIO/useSocket.js";
import { GET_UNREAD_COUNT } from "../../graphql/notifications.queries.js";
import { QUERY_MY_TASKS_COUNT } from "../../graphql/tasks.queries.js";
import { selectRecentItems, selectSelectedHeader } from "../../redux/application/application.selectors";
import { selectDarkMode, selectRecentItems, selectSelectedHeader } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions";
import { signOutStart } from "../../redux/user/user.actions";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
@@ -22,13 +22,15 @@ import NotificationCenterContainer from "../notification-center/notification-cen
import TaskCenterContainer from "../task-center/task-center.container.jsx";
import buildAccountingChildren from "./buildAccountingChildren.jsx";
import buildLeftMenuItems from "./buildLeftMenuItems.jsx";
import { toggleDarkMode } from "../../redux/application/application.actions";
// --- Redux mappings ---
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
recentItems: selectRecentItems,
selectedHeader: selectSelectedHeader,
bodyshop: selectBodyshop
bodyshop: selectBodyshop,
darkMode: selectDarkMode
});
const mapDispatchToProps = (dispatch) => ({
@@ -38,7 +40,8 @@ const mapDispatchToProps = (dispatch) => ({
setReportCenterContext: (context) => dispatch(setModalContext({ context, modal: "reportCenter" })),
signOutStart: () => dispatch(signOutStart()),
setCardPaymentContext: (context) => dispatch(setModalContext({ context, modal: "cardPayment" })),
setTaskUpsertContext: (context) => dispatch(setModalContext({ context, modal: "taskUpsert" }))
setTaskUpsertContext: (context) => dispatch(setModalContext({ context, modal: "taskUpsert" })),
toggleDarkMode: () => dispatch(toggleDarkMode())
});
// --- Utility Hooks ---
@@ -84,22 +87,22 @@ function useIncompleteTaskCount(assignedToId, bodyshopId, isEmployee, isConnecte
}
// --- Main Component ---
function Header(props) {
const {
handleMenuClick,
currentUser,
bodyshop,
selectedHeader,
signOutStart,
setBillEnterContext,
setTimeTicketContext,
setPaymentContext,
setReportCenterContext,
recentItems,
setCardPaymentContext,
setTaskUpsertContext
} = props;
function Header({
handleMenuClick,
currentUser,
bodyshop,
selectedHeader,
signOutStart,
setBillEnterContext,
setTimeTicketContext,
setPaymentContext,
setReportCenterContext,
recentItems,
setCardPaymentContext,
setTaskUpsertContext,
toggleDarkMode,
darkMode
}) {
// Feature flags
const {
treatments: { ImEXPay, DmsAp, Simple_Inventory }
@@ -216,6 +219,10 @@ function Header(props) {
[handleMenuClick]
);
const handleDarkModeToggle = useCallback(() => {
toggleDarkMode();
}, [toggleDarkMode]);
// --- Menu Items ---
// built externally to keep the component clean, but on this level to prevent unnecessary re-renders
@@ -257,9 +264,21 @@ function Header(props) {
setTaskUpsertContext,
setReportCenterContext,
signOutStart,
accountingChildren
accountingChildren,
darkMode,
handleDarkModeToggle
}),
[t, bodyshop, recentItems, setTaskUpsertContext, setReportCenterContext, signOutStart, accountingChildren]
[
t,
bodyshop,
recentItems,
setTaskUpsertContext,
setReportCenterContext,
signOutStart,
accountingChildren,
darkMode,
handleDarkModeToggle
]
);
const rightMenuItems = useMemo(() => {
@@ -292,6 +311,7 @@ function Header(props) {
),
onClick: handleTaskCenterClick
});
return items;
}, [
scenarioNotificationsOn,