import { Accessibility, AlignJustify, Check, CloudSun, Eye, GalleryHorizontalEnd, Gauge, Grid3X3, Layers3, Maximize2, MonitorCog, Image as ImageIcon, RefreshCw, Server, Sparkles, Trash2, Upload, } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import type { Accent, BackgroundStyle, ContentWidth, DashboardPayload, Density, Theme, ViewMode, WallpaperFit, } from "../../shared/contracts"; import { api } from "../api"; type Performer = ( action: () => Promise, message: string, ) => Promise; interface AppearanceSettingsProps { data: DashboardPayload; perform: Performer; } const themes: { id: Theme; label: string; copy: string }[] = [ { id: "dark", label: "Donker", copy: "Diep navy en rustig contrast.", }, { id: "light", label: "Licht", copy: "Helder, rustig en verfijnd." }, { id: "harbor", label: "Haven", copy: "Koel marineblauw voor late avonden." }, ]; const accents: { id: Accent; label: string }[] = [ { id: "coral", label: "Koraal" }, { id: "ocean", label: "Oceaan" }, { id: "violet", label: "Violet" }, { id: "lime", label: "Limoen" }, ]; const views: { id: ViewMode; label: string; copy: string }[] = [ { id: "overview", label: "Volledig overzicht", copy: "Alle verzamelingen op één doorlopende pagina.", }, { id: "categories", label: "Categorienavigatie", copy: "Wissel tussen gerichte verzamelingstabbladen.", }, ]; const widths: { id: ContentWidth; label: string; copy: string; icon: typeof Maximize2; }[] = [ { id: "focused", label: "Gericht", copy: "Rustig en gecentreerd tot 1120 px.", icon: AlignJustify, }, { id: "wide", label: "Breed", copy: "Evenwichtig voor alledaagse desktops.", icon: GalleryHorizontalEnd, }, { id: "fluid", label: "Vloeiend", copy: "Benut ultrabrede schermen volledig.", icon: Maximize2, }, ]; const densities: { id: Density; label: string; copy: string; icon: typeof Gauge; }[] = [ { id: "compact", label: "Compact", copy: "Meer services per rij.", icon: Grid3X3, }, { id: "comfortable", label: "Comfortabel", copy: "Een evenwichtige standaard voor dagelijks gebruik.", icon: Gauge, }, { id: "spacious", label: "Ruim", copy: "Grotere, rustigere starttegels.", icon: Layers3, }, ]; const backgrounds: { id: BackgroundStyle; label: string; copy: string }[] = [ { id: "aurora", label: "Aurora", copy: "Zachte omgevingskleur en diepte." }, { id: "grid", label: "Blauwdruk", copy: "Een subtiel technisch raster." }, { id: "minimal", label: "Minimaal", copy: "Zuivere kleur zonder textuur." }, ]; export function AppearanceSettings({ data, perform }: AppearanceSettingsProps) { const preferences = data.preferences; const wallpaperInput = useRef(null); const [wallpaperDraft, setWallpaperDraft] = useState<{ fit: WallpaperFit; positionX: number; positionY: number; zoom: number; }>(() => ({ fit: preferences.wallpaperFit, positionX: preferences.wallpaperPositionX, positionY: preferences.wallpaperPositionY, zoom: preferences.wallpaperZoom, })); useEffect(() => { setWallpaperDraft({ fit: preferences.wallpaperFit, positionX: preferences.wallpaperPositionX, positionY: preferences.wallpaperPositionY, zoom: preferences.wallpaperZoom, }); }, [ preferences.wallpaperFit, preferences.wallpaperPositionX, preferences.wallpaperPositionY, preferences.wallpaperZoom, ]); const wallpaperDraftChanged = wallpaperDraft.fit !== preferences.wallpaperFit || wallpaperDraft.positionX !== preferences.wallpaperPositionX || wallpaperDraft.positionY !== preferences.wallpaperPositionY || wallpaperDraft.zoom !== preferences.wallpaperZoom; return ( <>

Instellingen › Weergave

Thema

Kies de visuele stijl die het beste bij je workflow past.

{themes.map((theme) => ( ))}

Dashboardmodus

{views.map((view) => ( ))}

Grid-dichtheid

{densities.map((density) => { const Icon = density.icon; return ( ); })}
Meer personalisatie Accent, canvasbreedte, achtergrond en dashboarddetails

Accentkleur

{accents.map((accent) => ( ))}

Ruimtegebruik

{widths.map((width) => { const Icon = width.icon; return ( ); })}

Achtergrond

{backgrounds.map((background) => ( ))}
Wallpaperstudio Stem de uitsnede af op het zichtbare centrale vlak. De preview reageert direct; pas toe wanneer het beeld goed staat.
{ const file = event.target.files?.[0]; if (!file) return; void perform( () => api.uploadWallpaper(file), "Wallpaper bijgewerkt", ); event.target.value = ""; }} /> {data.wallpaper && ( )}
{data.wallpaper ? ( <> Huidige dashboardwallpaper ) : ( Upload eerst een PNG, JPEG of WebP tot 8 MB. )}
Schaalmethode Passend toont de volledige afbeelding; Vullend benut het volledige vlak.
{( [ ["contain", "Passend"], ["cover", "Vullend"], ] as const ).map(([fit, label]) => ( ))}
De dashboardwallpaper blijft vast in het zichtbare centrale vlak terwijl de inhoud scrolt.

Dashboarddetails

Weer in de topbalk Toon actuele temperatuur en weersituatie voor Mol.
Weerlocatie Naam en coördinaten voor de weerkaart.
{ const value = event.target.value.trim(); if (value && value !== preferences.weatherLocation) void perform( () => api.updatePreferences({ weatherLocation: value }), "Weerlocatie bijgewerkt", ); }} /> { const value = Number(event.target.value); if (Number.isFinite(value)) void perform( () => api.updatePreferences({ weatherLatitude: value }), "Breedtegraad bijgewerkt", ); }} /> { const value = Number(event.target.value); if (Number.isFinite(value)) void perform( () => api.updatePreferences({ weatherLongitude: value }), "Lengtegraad bijgewerkt", ); }} />
Welkomstblok Toon de begroeting, het overzicht en snelle statistieken.
Servicestatus Toon beschikbaarheidstekst en statusindicatoren op tegels.
Unraid-serverpaneel Toon hostcapaciteit, containerstatus en Docker-details.
Verminderde beweging Schakel decoratieve animaties en vloeiende overgangen uit.
Verversingsinterval Hoe vaak DockDeck statussen en actieve panelen opnieuw ophaalt.
); }