From 48bd09188cad2ec3bffe597d3ca9f1bd19c34a13 Mon Sep 17 00:00:00 2001 From: Till JS Date: Wed, 29 Apr 2026 02:50:16 +0200 Subject: [PATCH] =?UTF-8?q?feat(forms):=20FormsWidget=20=E2=80=94=20Workbe?= =?UTF-8?q?nch-Karte=20mit=20Stats=20+=20letzte=20Forms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Heimstart-Karte für das Forms-Modul, parallele zu BroadcastsWidget / InvoicesOpenWidget: - modules/forms/widgets/FormsWidget.svelte: 3-Spalten-Stats (veröffentlicht / Entwurf / Antworten total + "+N/7T" delta für letzte 7 Tage), bis zu 2 zuletzt aktualisierte Forms mit Status-Punkt (grün=published, grau=sonst) + Response-Count + relative-Zeit, "+N weitere"-Link wenn mehr als 2 Forms existieren. Empty-State mit "+ Erstes Formular bauen". Live aus Dexie via 2 parallele liveQuery-Subs (forms + formResponses). - types/dashboard.ts: WidgetType-Union erweitert um 'forms'; WIDGET_REGISTRY-Eintrag mit defaultSize 'medium' + 📋-Icon. - components/dashboard/widget-registry.ts: FormsWidget importiert + in widgetComponents map registriert. - 5 Locales × 2 dashboard-Keys (forms.title + forms.description). App-Registry-Eintrag für /forms in app-registry/apps.ts existiert bereits (Parallel-Session). FormsWidget ist die _aggregierte_ Heimstart-Variante; der app-registry-Eintrag mountet die ListView direkt als Modul-Card. i18n-parity 6417 keys aligned. svelte-check 0 errors in modules/forms/widgets/. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../components/dashboard/widget-registry.ts | 2 + .../src/lib/i18n/locales/dashboard/de.json | 4 + .../src/lib/i18n/locales/dashboard/en.json | 4 + .../src/lib/i18n/locales/dashboard/es.json | 4 + .../src/lib/i18n/locales/dashboard/fr.json | 4 + .../src/lib/i18n/locales/dashboard/it.json | 4 + .../modules/forms/widgets/FormsWidget.svelte | 164 ++++++++++++++++++ apps/mana/apps/web/src/lib/types/dashboard.ts | 11 +- 8 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 apps/mana/apps/web/src/lib/modules/forms/widgets/FormsWidget.svelte diff --git a/apps/mana/apps/web/src/lib/components/dashboard/widget-registry.ts b/apps/mana/apps/web/src/lib/components/dashboard/widget-registry.ts index 410e16956..9bb138afa 100644 --- a/apps/mana/apps/web/src/lib/components/dashboard/widget-registry.ts +++ b/apps/mana/apps/web/src/lib/components/dashboard/widget-registry.ts @@ -35,6 +35,7 @@ import ArticlesUnreadWidget from '$lib/modules/articles/widgets/ArticlesUnreadWi import BodyStatsWidget from '$lib/modules/body/widgets/BodyStatsWidget.svelte'; import InvoicesOpenWidget from '$lib/modules/invoices/widgets/InvoicesOpenWidget.svelte'; import BroadcastsWidget from '$lib/modules/broadcasts/widgets/BroadcastsWidget.svelte'; +import FormsWidget from '$lib/modules/forms/widgets/FormsWidget.svelte'; import DayTimelineWidget from './widgets/DayTimelineWidget.svelte'; import ActivityFeedWidget from './widgets/ActivityFeedWidget.svelte'; @@ -66,4 +67,5 @@ export const widgetComponents: Record = { 'body-stats': BodyStatsWidget, 'invoices-open': InvoicesOpenWidget, broadcasts: BroadcastsWidget, + forms: FormsWidget, }; diff --git a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/de.json b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/de.json index 66db4f411..52f65f982 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/de.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/de.json @@ -154,6 +154,10 @@ "body_stats": { "title": "Body", "description": "Aktuelles Gewicht und Trainings-Status" + }, + "forms": { + "title": "Formulare", + "description": "Status-Übersicht und letzte Antworten" } } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/en.json b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/en.json index 83c7be3c6..1da6db476 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/en.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/en.json @@ -154,6 +154,10 @@ "body_stats": { "title": "Body", "description": "Latest weight and training status" + }, + "forms": { + "title": "Forms", + "description": "Status overview and latest responses" } } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/es.json b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/es.json index 9425fe838..7efb5ef8e 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/es.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/es.json @@ -154,6 +154,10 @@ "articles_unread": { "title": "Artículos", "description": "Artículos no leídos de tu lista de lectura" + }, + "forms": { + "title": "Formularios", + "description": "Resumen de estado y últimas respuestas" } } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/fr.json b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/fr.json index 0ba144bd5..8364448b9 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/fr.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/fr.json @@ -154,6 +154,10 @@ "articles_unread": { "title": "Articles", "description": "Articles non lus de ta liste de lecture" + }, + "forms": { + "title": "Formulaires", + "description": "Aperçu des statuts et dernières réponses" } } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/it.json b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/it.json index 9e5fcae96..4b88bc52d 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/dashboard/it.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/dashboard/it.json @@ -154,6 +154,10 @@ "articles_unread": { "title": "Articoli", "description": "Articoli non letti dalla tua lista di lettura" + }, + "forms": { + "title": "Moduli", + "description": "Panoramica degli stati e ultime risposte" } } } diff --git a/apps/mana/apps/web/src/lib/modules/forms/widgets/FormsWidget.svelte b/apps/mana/apps/web/src/lib/modules/forms/widgets/FormsWidget.svelte new file mode 100644 index 000000000..ae033b26c --- /dev/null +++ b/apps/mana/apps/web/src/lib/modules/forms/widgets/FormsWidget.svelte @@ -0,0 +1,164 @@ + + +
+
+

+ + Formulare +

+ Alle → +
+ + {#if loading} +
+ {#each Array(2) as _} +
+ {/each} +
+ {:else if forms.length === 0} +
+

Noch keine Formulare.

+ + + Erstes Formular bauen + +
+ {:else} +
+
+
{stats.published}
+
veröffentlicht
+
+
+
{stats.drafts}
+
Entwurf
+
+
+
{totalResponses}
+
+ Antworten + {#if recentResponseCount > 0} + +{recentResponseCount}/7T + {/if} +
+
+
+ + + + {#if stats.total > recentForms.length} + + + {stats.total - recentForms.length} weitere + + {/if} + {/if} +
diff --git a/apps/mana/apps/web/src/lib/types/dashboard.ts b/apps/mana/apps/web/src/lib/types/dashboard.ts index 91c27e4ec..3ae0f7402 100644 --- a/apps/mana/apps/web/src/lib/types/dashboard.ts +++ b/apps/mana/apps/web/src/lib/types/dashboard.ts @@ -34,7 +34,8 @@ export type WidgetType = | 'articles-unread' // Articles: saved read-it-later articles | 'body-stats' // Body: latest weight + active workout summary | 'invoices-open' // Invoices: open/overdue totals + oldest overdue - | 'broadcasts'; // Broadcast: YTD counts + last sent + next scheduled + | 'broadcasts' // Broadcast: YTD counts + last sent + next scheduled + | 'forms'; // Forms: status counts + last forms + recent response count /** * Widget size - maps to CSS Grid columns @@ -378,6 +379,14 @@ export const WIDGET_REGISTRY: WidgetMeta[] = [ defaultSize: 'medium', allowMultiple: false, }, + { + type: 'forms', + nameKey: 'dashboard.widgets.forms.title', + descriptionKey: 'dashboard.widgets.forms.description', + icon: '📋', + defaultSize: 'medium', + allowMultiple: false, + }, ]; /**