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:
BOHA
2026-06-06 19:08:35 +02:00
parent d2e368a05e
commit bb7e53f47a
3 changed files with 187 additions and 149 deletions

View File

@@ -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>
); );
} }

View 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;
}

View 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>
);
}