feat(mui): mount MUI provider + sync color scheme to data-theme
Wraps AdminApp in MuiProvider (ThemeProvider v7, defaultMode=dark) and adds MuiColorSchemeSync to mirror ThemeContext's data-theme attribute into MUI's JS color-scheme state so useColorScheme().mode stays in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import { queryClient } from "./lib/queryClient";
|
|||||||
import ErrorBoundary from "./components/ErrorBoundary";
|
import ErrorBoundary from "./components/ErrorBoundary";
|
||||||
import AdminLayout from "./components/AdminLayout";
|
import AdminLayout from "./components/AdminLayout";
|
||||||
import AlertContainer from "./components/AlertContainer";
|
import AlertContainer from "./components/AlertContainer";
|
||||||
|
import MuiProvider from "./ui/MuiProvider";
|
||||||
import Login from "./pages/Login";
|
import Login from "./pages/Login";
|
||||||
import Dashboard from "./pages/Dashboard";
|
import Dashboard from "./pages/Dashboard";
|
||||||
import "./variables.css";
|
import "./variables.css";
|
||||||
@@ -84,154 +85,159 @@ const WarehouseCategories = lazy(() => import("./pages/WarehouseCategories"));
|
|||||||
|
|
||||||
export default function AdminApp() {
|
export default function AdminApp() {
|
||||||
return (
|
return (
|
||||||
<AuthProvider>
|
<MuiProvider>
|
||||||
<AlertProvider>
|
<AuthProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<AlertProvider>
|
||||||
<AlertContainer />
|
<QueryClientProvider client={queryClient}>
|
||||||
<ErrorBoundary>
|
<AlertContainer />
|
||||||
<Suspense
|
<ErrorBoundary>
|
||||||
fallback={
|
<Suspense
|
||||||
<div className="admin-loading">
|
fallback={
|
||||||
<div className="admin-spinner" />
|
<div className="admin-loading">
|
||||||
</div>
|
<div className="admin-spinner" />
|
||||||
}
|
</div>
|
||||||
>
|
}
|
||||||
<Routes>
|
>
|
||||||
<Route path="login" element={<Login />} />
|
<Routes>
|
||||||
<Route element={<AdminLayout />}>
|
<Route path="login" element={<Login />} />
|
||||||
<Route index element={<Dashboard />} />
|
<Route element={<AdminLayout />}>
|
||||||
<Route path="users" element={<Users />} />
|
<Route index element={<Dashboard />} />
|
||||||
<Route path="attendance" element={<Attendance />} />
|
<Route path="users" element={<Users />} />
|
||||||
<Route
|
<Route path="attendance" element={<Attendance />} />
|
||||||
path="attendance/history"
|
<Route
|
||||||
element={<AttendanceHistory />}
|
path="attendance/history"
|
||||||
/>
|
element={<AttendanceHistory />}
|
||||||
<Route
|
/>
|
||||||
path="attendance/admin"
|
<Route
|
||||||
element={<AttendanceAdmin />}
|
path="attendance/admin"
|
||||||
/>
|
element={<AttendanceAdmin />}
|
||||||
<Route
|
/>
|
||||||
path="attendance/balances"
|
<Route
|
||||||
element={<AttendanceBalances />}
|
path="attendance/balances"
|
||||||
/>
|
element={<AttendanceBalances />}
|
||||||
<Route
|
/>
|
||||||
path="attendance/requests"
|
<Route
|
||||||
element={<LeaveRequests />}
|
path="attendance/requests"
|
||||||
/>
|
element={<LeaveRequests />}
|
||||||
<Route
|
/>
|
||||||
path="attendance/approval"
|
<Route
|
||||||
element={<LeaveApproval />}
|
path="attendance/approval"
|
||||||
/>
|
element={<LeaveApproval />}
|
||||||
<Route
|
/>
|
||||||
path="attendance/create"
|
<Route
|
||||||
element={<AttendanceCreate />}
|
path="attendance/create"
|
||||||
/>
|
element={<AttendanceCreate />}
|
||||||
<Route
|
/>
|
||||||
path="attendance/location/:id"
|
<Route
|
||||||
element={<AttendanceLocation />}
|
path="attendance/location/:id"
|
||||||
/>
|
element={<AttendanceLocation />}
|
||||||
<Route path="plan-work" element={<PlanWork />} />
|
/>
|
||||||
<Route path="trips" element={<Trips />} />
|
<Route path="plan-work" element={<PlanWork />} />
|
||||||
<Route path="trips/history" element={<TripsHistory />} />
|
<Route path="trips" element={<Trips />} />
|
||||||
<Route path="trips/admin" element={<TripsAdmin />} />
|
<Route path="trips/history" element={<TripsHistory />} />
|
||||||
<Route path="vehicles" element={<Vehicles />} />
|
<Route path="trips/admin" element={<TripsAdmin />} />
|
||||||
<Route path="offers" element={<Offers />} />
|
<Route path="vehicles" element={<Vehicles />} />
|
||||||
<Route path="offers/new" element={<OfferDetail />} />
|
<Route path="offers" element={<Offers />} />
|
||||||
<Route path="offers/:id" element={<OfferDetail />} />
|
<Route path="offers/new" element={<OfferDetail />} />
|
||||||
<Route
|
<Route path="offers/:id" element={<OfferDetail />} />
|
||||||
path="offers/customers"
|
<Route
|
||||||
element={<OffersCustomers />}
|
path="offers/customers"
|
||||||
/>
|
element={<OffersCustomers />}
|
||||||
<Route
|
/>
|
||||||
path="offers/templates"
|
<Route
|
||||||
element={<OffersTemplates />}
|
path="offers/templates"
|
||||||
/>
|
element={<OffersTemplates />}
|
||||||
<Route path="orders" element={<Orders />} />
|
/>
|
||||||
<Route path="orders/:id" element={<OrderDetail />} />
|
<Route path="orders" element={<Orders />} />
|
||||||
<Route path="projects" element={<Projects />} />
|
<Route path="orders/:id" element={<OrderDetail />} />
|
||||||
<Route path="projects/:id" element={<ProjectDetail />} />
|
<Route path="projects" element={<Projects />} />
|
||||||
<Route path="invoices" element={<Invoices />} />
|
<Route path="projects/:id" element={<ProjectDetail />} />
|
||||||
<Route path="invoices/new" element={<InvoiceDetail />} />
|
<Route path="invoices" element={<Invoices />} />
|
||||||
<Route path="invoices/:id" element={<InvoiceDetail />} />
|
<Route path="invoices/new" element={<InvoiceDetail />} />
|
||||||
<Route path="settings" element={<Settings />} />
|
<Route path="invoices/:id" element={<InvoiceDetail />} />
|
||||||
<Route path="audit-log" element={<AuditLog />} />
|
<Route path="settings" element={<Settings />} />
|
||||||
<Route path="warehouse" element={<Warehouse />} />
|
<Route path="audit-log" element={<AuditLog />} />
|
||||||
<Route path="warehouse/items" element={<WarehouseItems />} />
|
<Route path="warehouse" element={<Warehouse />} />
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/items/:id"
|
path="warehouse/items"
|
||||||
element={<WarehouseItemDetail />}
|
element={<WarehouseItems />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/receipts"
|
path="warehouse/items/:id"
|
||||||
element={<WarehouseReceipts />}
|
element={<WarehouseItemDetail />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/receipts/new"
|
path="warehouse/receipts"
|
||||||
element={<WarehouseReceiptForm />}
|
element={<WarehouseReceipts />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/receipts/:id"
|
path="warehouse/receipts/new"
|
||||||
element={<WarehouseReceiptDetail />}
|
element={<WarehouseReceiptForm />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/receipts/:id/edit"
|
path="warehouse/receipts/:id"
|
||||||
element={<WarehouseReceiptForm />}
|
element={<WarehouseReceiptDetail />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/issues"
|
path="warehouse/receipts/:id/edit"
|
||||||
element={<WarehouseIssues />}
|
element={<WarehouseReceiptForm />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/issues/new"
|
path="warehouse/issues"
|
||||||
element={<WarehouseIssueForm />}
|
element={<WarehouseIssues />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/issues/:id"
|
path="warehouse/issues/new"
|
||||||
element={<WarehouseIssueDetail />}
|
element={<WarehouseIssueForm />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/issues/:id/edit"
|
path="warehouse/issues/:id"
|
||||||
element={<WarehouseIssueForm />}
|
element={<WarehouseIssueDetail />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/reservations"
|
path="warehouse/issues/:id/edit"
|
||||||
element={<WarehouseReservations />}
|
element={<WarehouseIssueForm />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/inventory"
|
path="warehouse/reservations"
|
||||||
element={<WarehouseInventory />}
|
element={<WarehouseReservations />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/inventory/new"
|
path="warehouse/inventory"
|
||||||
element={<WarehouseInventoryForm />}
|
element={<WarehouseInventory />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/inventory/:id"
|
path="warehouse/inventory/new"
|
||||||
element={<WarehouseInventoryDetail />}
|
element={<WarehouseInventoryForm />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/reports"
|
path="warehouse/inventory/:id"
|
||||||
element={<WarehouseReports />}
|
element={<WarehouseInventoryDetail />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/suppliers"
|
path="warehouse/reports"
|
||||||
element={<WarehouseSuppliers />}
|
element={<WarehouseReports />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/locations"
|
path="warehouse/suppliers"
|
||||||
element={<WarehouseLocations />}
|
element={<WarehouseSuppliers />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="warehouse/categories"
|
path="warehouse/locations"
|
||||||
element={<WarehouseCategories />}
|
element={<WarehouseLocations />}
|
||||||
/>
|
/>
|
||||||
</Route>
|
<Route
|
||||||
<Route path="*" element={<NotFound />} />
|
path="warehouse/categories"
|
||||||
</Routes>
|
element={<WarehouseCategories />}
|
||||||
</Suspense>
|
/>
|
||||||
</ErrorBoundary>
|
</Route>
|
||||||
</QueryClientProvider>
|
<Route path="*" element={<NotFound />} />
|
||||||
</AlertProvider>
|
</Routes>
|
||||||
</AuthProvider>
|
</Suspense>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</QueryClientProvider>
|
||||||
|
</AlertProvider>
|
||||||
|
</AuthProvider>
|
||||||
|
</MuiProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/admin/ui/MuiColorSchemeSync.tsx
Normal file
19
src/admin/ui/MuiColorSchemeSync.tsx
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useColorScheme } from "@mui/material/styles";
|
||||||
|
import { useTheme as useAppTheme } from "../../context/ThemeContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ThemeContext is the single owner of the `data-theme` attribute. This mirrors
|
||||||
|
* its value into MUI's JS color-scheme state so theme.applyStyles('dark') and
|
||||||
|
* useColorScheme().mode stay in sync with the attribute the CSS selector reads.
|
||||||
|
*/
|
||||||
|
export default function MuiColorSchemeSync() {
|
||||||
|
const { theme } = useAppTheme();
|
||||||
|
const { mode, setMode } = useColorScheme();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mode !== theme) setMode(theme as "light" | "dark");
|
||||||
|
}, [theme, mode, setMode]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
13
src/admin/ui/MuiProvider.tsx
Normal file
13
src/admin/ui/MuiProvider.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { ReactNode } from "react";
|
||||||
|
import { ThemeProvider } from "@mui/material/styles";
|
||||||
|
import { theme } from "../theme";
|
||||||
|
import MuiColorSchemeSync from "./MuiColorSchemeSync";
|
||||||
|
|
||||||
|
export default function MuiProvider({ children }: { children: ReactNode }) {
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={theme} defaultMode="dark">
|
||||||
|
<MuiColorSchemeSync />
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user