'use client'; import { useTranslations } from 'next-intl'; import type { CSSProperties } from 'react'; import { useDashboardStore } from '@/lib/stores/dashboard-store'; import { WIDGET_REGISTRY, type WidgetType } from '../widget-registry'; import { WidgetIcon } from './widget-icon'; /** * Kacheltypen ohne eigene Kopfzeile, denen der Rahmen eine einheitliche * Kopfzeile (Symbol + Name) gibt (Design „Mosaik“, Runde 2; Erinnerungen seit * quick-260929-if2). Notiz, * Favoriten, Proxmox und XFrame bringen ihre eigene (mit editierbarem Titel) * mit; Suche und Bilderrahmen bleiben bewusst randlos — ein Suchfeld bzw. * ein Foto braucht keine Ueberschrift. */ const FRAME_HEADER_TYPES = new Set(['calendar', 'clock', 'calculator', 'stopwatch', 'reminder']); /** * Kacheltypen mit Titelzeile — nur diese bekommen im Bearbeitungsmodus den * Schalter „Titel ausblenden“ (quick-260928-wtt). Die Wahl steht als * `hideTitle: true` in der Widget-Konfiguration und gilt nur in der Ansicht; * im Bearbeitungsmodus bleibt der Titel sichtbar (und editierbar). */ const TITLE_TYPES = new Set([...FRAME_HEADER_TYPES, 'note', 'favorites', 'proxmox', 'xframe']); interface WidgetWrapperProps { widget: { id: string; widgetType: string; config: Record; }; isEditMode: boolean; onRemove: (id: string) => void; /** Position im Raster — staffelt das Einblenden beim Laden (Runde 3). */ enterIndex?: number; } /** * Wrapper card for all dashboard widgets. * * quick-260916-dyv: Im Bearbeitungsmodus ist die GANZE Karte der Griff * (`widget-drag-handle`, `cursor-grab`). Eine 20 px hohe Kopfleiste mit * Griff-Symbol liegt als Overlay ueber dem oberen Kachelrand — nur optischer * Hinweis (Tooltip `widgets.dragHint`), kein eigener Griff. Der Loesch-Knopf * sitzt rechts in dieser Kopfleiste und traegt `data-no-drag`; welche Ziele * KEIN Ziehen starten (Eingabefelder, Knoepfe, Links, [data-no-drag], * .widgetNoDrag), entscheidet der cancel-Selektor in dashboard-grid.tsx. * Renders the actual widget component via WIDGET_REGISTRY lookup. */ export function WidgetWrapper({ widget, isEditMode, onRemove, enterIndex = 0, }: WidgetWrapperProps) { const t = useTranslations('widgets'); const definition = WIDGET_REGISTRY[widget.widgetType as WidgetType]; const WidgetComponent = definition?.component; const setWidgetConfig = useDashboardStore((state) => state.setWidgetConfig); const hasTitle = TITLE_TYPES.has(widget.widgetType); const titleHidden = widget.config?.hideTitle === true; // Design „Mosaik“: in der Ansicht eine ruhige Fluent-Karte (hell Schatten, // dunkel Haarlinie), die Akzent-Umrandung nur im Bearbeitungsmodus. const cardClassName = isEditMode ? 'widget-card widget-drag-handle relative h-full w-full cursor-grab overflow-hidden rounded-lg bg-card shadow-md active:cursor-grabbing' : 'widget-card relative h-full w-full overflow-hidden rounded-lg bg-card shadow-sm dark:border dark:border-border'; return (
{/* Edit mode: Overlay-Kopfleiste (Griff-Hinweis) mit Loesch-Knopf rechts. Bewusst `absolute` und NICHT im Fluss: der Rumpf bleibt h-full, die Hoehenkette Karte -> Rumpf bleibt definit (cqh loest weiter auf). */} {isEditMode && (
{hasTitle && ( )}
)} {/* Widget body. quick-260916-bwo: Groessen-Container (@container-size -> container-type: size), damit die Widget-Inhalte per cqw/cqh mit der Kachel skalieren. Braucht eine definite Hoehe — die kommt ueber h-full aus der Karte, die das RGL-Element mit Pixelhoehe fuellt. Steht am Rumpf statt an der Karte, weil die Karte im Bearbeitungsmodus zusaetzlich den Griff traegt. quick-260916-dyv: Die Kopfleiste liegt als Overlay ueber dem Rumpf und aendert die Hoehenkette nicht. */}
{WidgetComponent && definition && FRAME_HEADER_TYPES.has(widget.widgetType) && (

{t(definition.nameKey)}

)}
{WidgetComponent ? ( ) : ( /* quick-260922-m1h: Kein Bauteil zu diesem Typ — entweder eine alte Kachel eines entfernten Typs oder (ab der ersten Modul-Kachel) eine Kachel, deren Modul dem Benutzer nicht freigegeben ist. Vorher stand hier der rohe Typname, der dem Anwender nichts sagte. */

{t('unavailable')}

)}
); }