Move dark mode toggle from sidebar to Settings > Display
This commit is contained in:
1 parent
5c35080e22
commit
4ba86429d5
2 files changed
+31
-18
No files matched your search
@@ -18,11 +18,8 @@ import {
|
|||||||
IconStethoscope,
|
IconStethoscope,
|
||||||
IconSettings,
|
IconSettings,
|
||||||
IconMenu2,
|
IconMenu2,
|
||||||
IconSun,
|
|
||||||
IconMoon,
|
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import type { CurrentUser } from "../api/client";
|
import type { CurrentUser } from "../api/client";
|
||||||
import { getTheme, setTheme, type Theme } from "../utils/theme";
|
|
||||||
|
|
||||||
interface NavItem {
|
interface NavItem {
|
||||||
to: string;
|
to: string;
|
||||||
@@ -54,17 +51,10 @@ const roleRank: Record<CurrentUser["role"], number> = { viewer: 0, operator: 1,
|
|||||||
|
|
||||||
export default function AppShell({ user, children }: { user: CurrentUser; children: ReactNode }) {
|
export default function AppShell({ user, children }: { user: CurrentUser; children: ReactNode }) {
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
const [theme, setThemeState] = useState<Theme>(() => getTheme());
|
|
||||||
const visibleItems = NAV_ITEMS.filter(
|
const visibleItems = NAV_ITEMS.filter(
|
||||||
(item) => !item.minRole || roleRank[user.role] >= roleRank[item.minRole],
|
(item) => !item.minRole || roleRank[user.role] >= roleRank[item.minRole],
|
||||||
);
|
);
|
||||||
|
|
||||||
function toggleTheme() {
|
|
||||||
const next: Theme = theme === "dark" ? "light" : "dark";
|
|
||||||
setTheme(next);
|
|
||||||
setThemeState(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
<aside className="navbar navbar-vertical navbar-expand-lg" data-bs-theme="dark">
|
<aside className="navbar navbar-vertical navbar-expand-lg" data-bs-theme="dark">
|
||||||
@@ -97,14 +87,6 @@ export default function AppShell({ user, children }: { user: CurrentUser; childr
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<div className="navbar-footer px-3">
|
<div className="navbar-footer px-3">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-outline-secondary btn-sm w-100 mb-2 d-flex align-items-center justify-content-center gap-2"
|
|
||||||
onClick={toggleTheme}
|
|
||||||
>
|
|
||||||
{theme === "dark" ? <IconSun size={16} /> : <IconMoon size={16} />}
|
|
||||||
{theme === "dark" ? "Light mode" : "Dark mode"}
|
|
||||||
</button>
|
|
||||||
<div className="text-secondary small mb-2">
|
<div className="text-secondary small mb-2">
|
||||||
Signed in as {user.name ?? user.email ?? user.sub} · {user.role}
|
Signed in as {user.name ?? user.email ?? user.sub} · {user.role}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { IconMoon, IconSun } from "@tabler/icons-react";
|
||||||
import { api, type AppSettings, type DateFormat, type TimeFormat } from "../../api/client";
|
import { api, type AppSettings, type DateFormat, type TimeFormat } from "../../api/client";
|
||||||
import { setDateTimeSettings } from "../../utils/date";
|
import { setDateTimeSettings } from "../../utils/date";
|
||||||
import { setPageSize } from "../../utils/pageSize";
|
import { setPageSize } from "../../utils/pageSize";
|
||||||
|
import { getTheme, setTheme, type Theme } from "../../utils/theme";
|
||||||
|
|
||||||
const DATE_FORMAT_OPTIONS: { value: DateFormat; label: string; example: string }[] = [
|
const DATE_FORMAT_OPTIONS: { value: DateFormat; label: string; example: string }[] = [
|
||||||
{ value: "ymd", label: "Year-Month-Day", example: "2026-09-15" },
|
{ value: "ymd", label: "Year-Month-Day", example: "2026-09-15" },
|
||||||
@@ -19,10 +21,17 @@ export default function DisplaySettings() {
|
|||||||
const [dateFormat, setDateFormatState] = useState<DateFormat>("ymd");
|
const [dateFormat, setDateFormatState] = useState<DateFormat>("ymd");
|
||||||
const [timeFormat, setTimeFormatState] = useState<TimeFormat>("24h");
|
const [timeFormat, setTimeFormatState] = useState<TimeFormat>("24h");
|
||||||
const [pageSize, setPageSizeState] = useState(20);
|
const [pageSize, setPageSizeState] = useState(20);
|
||||||
|
const [theme, setThemeState] = useState<Theme>(() => getTheme());
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
const [saved, setSaved] = useState(false);
|
const [saved, setSaved] = useState(false);
|
||||||
const [saveError, setSaveError] = useState<string | null>(null);
|
const [saveError, setSaveError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
function toggleTheme() {
|
||||||
|
const next: Theme = theme === "dark" ? "light" : "dark";
|
||||||
|
setTheme(next);
|
||||||
|
setThemeState(next);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.settings
|
api.settings
|
||||||
.get()
|
.get()
|
||||||
@@ -136,6 +145,28 @@ export default function DisplaySettings() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-5">
|
||||||
|
<div className="card h-100">
|
||||||
|
<div className="card-header">
|
||||||
|
<h3 className="card-title">Theme</h3>
|
||||||
|
</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<p className="text-secondary">
|
||||||
|
A personal preference remembered on this browser only — it doesn't affect other signed-in
|
||||||
|
users.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-secondary d-flex align-items-center gap-2"
|
||||||
|
onClick={toggleTheme}
|
||||||
|
>
|
||||||
|
{theme === "dark" ? <IconSun size={16} /> : <IconMoon size={16} />}
|
||||||
|
Switch to {theme === "dark" ? "light" : "dark"} mode
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user