WIP: dark mode

This commit is contained in:
ISA
2025-09-08 13:14:04 +02:00
parent a596422056
commit eb0585072d
7 changed files with 59 additions and 16 deletions

View File

@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.869 NEXT_PUBLIC_APP_VERSION=1.6.870
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)

View File

@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
NEXT_PUBLIC_EXPORT_STATIC=true NEXT_PUBLIC_EXPORT_STATIC=true
NEXT_PUBLIC_USE_CGI=true NEXT_PUBLIC_USE_CGI=true
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.869 NEXT_PUBLIC_APP_VERSION=1.6.870
NEXT_PUBLIC_CPL_MODE=production NEXT_PUBLIC_CPL_MODE=production

View File

@@ -1,3 +1,8 @@
## [1.6.870] 2025-09-08
- fix: Beim Aufruf der TDR-Detailseite erscheint im Hintergrund auf der KÜ ein Schleifenwiderstand von 0 KOhm. In der Daten Javascriptdatei steht jedoch der richtige Wert.
---
## [1.6.869] 2025-09-08 ## [1.6.869] 2025-09-08
- fix: Beim Ausführen einer TDR-Messung (Klick auf blauen Button in der TDR-Detailseite) erscheint keine Rückmeldung. Dort müsste ein Hinweis erscheinen “TDR-Messung wird ausgeführt und kann bis zu zwei Minuten dauern” - fix: Beim Ausführen einer TDR-Messung (Klick auf blauen Button in der TDR-Detailseite) erscheint keine Rückmeldung. Dort müsste ein Hinweis erscheinen “TDR-Messung wird ausgeführt und kann bis zu zwei Minuten dauern”

View File

@@ -109,19 +109,46 @@ function Header() {
}, [deviceName, dispatch]); }, [deviceName, dispatch]);
//---------------------------------------------------------------- //----------------------------------------------------------------
// Dark/Light Mode Toggle // Dark/Light Mode Toggle (persist in localStorage)
const [isDark, setIsDark] = useState(false); const [isDark, setIsDark] = useState<boolean>(() => {
useEffect(() => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
const html = document.documentElement; return document.documentElement.classList.contains("dark");
if (isDark) { }
html.classList.add("dark"); return false;
} else { });
html.classList.remove("dark");
// Apply + persist when toggled
useEffect(() => {
if (typeof window === "undefined") return;
const html = document.documentElement;
if (isDark) {
html.classList.add("dark");
try {
localStorage.setItem("theme", "dark");
} catch {
/* ignore storage write errors */
}
} else {
html.classList.remove("dark");
try {
localStorage.setItem("theme", "light");
} catch {
/* ignore storage write errors */
} }
} }
}, [isDark]); }, [isDark]);
// Sync if another tab changes the theme
useEffect(() => {
const handler = (e: StorageEvent) => {
if (e.key === "theme" && e.newValue) {
setIsDark(e.newValue === "dark");
}
};
window.addEventListener("storage", handler);
return () => window.removeEventListener("storage", handler);
}, []);
return ( return (
<header className="bg-gray-300 dark:bg-gray-800 flex justify-between items-center w-full h-[13vh] laptop:h-[10vh] relative text-black dark:text-white "> <header className="bg-gray-300 dark:bg-gray-800 flex justify-between items-center w-full h-[13vh] laptop:h-[10vh] relative text-black dark:text-white ">
<div <div

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.869", "version": "1.6.870",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.869", "version": "1.6.870",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",
"@headlessui/react": "^2.2.4", "@headlessui/react": "^2.2.4",

View File

@@ -1,6 +1,6 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.869", "version": "1.6.870",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 3000", "dev": "next dev -p 3000",

View File

@@ -1,15 +1,26 @@
import { Html, Head, Main, NextScript } from "next/document"; import { Html, Head, Main, NextScript } from "next/document";
/**
* Custom Document to inject an early theme script so the dark-mode preference
* (stored in localStorage under key 'theme': 'dark' | 'light') is applied
* before the first paint. This verhindert ein "Flash" von Light-Mode beim
* Seitenwechsel / Reload in der statisch gebauten Produktion.
*/
export default function Document() { export default function Document() {
const setThemeScript = `(()=>{try{const k='theme';const t=localStorage.getItem(k);const m=window.matchMedia('(prefers-color-scheme: dark)').matches;const useDark = t? t==='dark' : m;const c=document.documentElement.classList;useDark?c.add('dark'):c.remove('dark');}catch(e){/* ignore */}})();`;
return ( return (
<Html lang="de"> <Html lang="de">
<Head> <Head>
{/* Füge Meta-Tags, CSS-Links und andere Header-Inhalte hier hinzu */}
<link rel="icon" href="/favicon.png" type="image/png" /> <link rel="icon" href="/favicon.png" type="image/png" />
{/* Early inline script (no external blocking) */}
<script
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: setThemeScript }}
/>
</Head> </Head>
<body> <body>
<Main /> {/* Hier wird der Seiteninhalt eingebettet */} <Main />
<NextScript /> {/* Fügt Next.js-Skripte für die Seite hinzu */} <NextScript />
</body> </body>
</Html> </Html>
); );