From ee7ff7d5e8a9f885f495dff806d5d37c054897ea Mon Sep 17 00:00:00 2001 From: Till JS Date: Sun, 5 Apr 2026 15:19:53 +0200 Subject: [PATCH] feat(dashboard): add "Mein Tag" timeline widget using timeBlocks Chronological day timeline showing all timeBlocks for today across all modules (events, tasks, habits, time entries). Shows summary stats (total time, counts per type), live indicators for running timers, and habit icons. Links to calendar for full view. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/dashboard/widget-registry.ts | 6 +- .../widgets/DayTimelineWidget.svelte | 177 ++++++++++++++++++ .../apps/web/src/lib/types/dashboard.ts | 23 ++- 3 files changed, 197 insertions(+), 9 deletions(-) create mode 100644 apps/manacore/apps/web/src/lib/components/dashboard/widgets/DayTimelineWidget.svelte diff --git a/apps/manacore/apps/web/src/lib/components/dashboard/widget-registry.ts b/apps/manacore/apps/web/src/lib/components/dashboard/widget-registry.ts index 60d91e5a8..98dc2c7d0 100644 --- a/apps/manacore/apps/web/src/lib/components/dashboard/widget-registry.ts +++ b/apps/manacore/apps/web/src/lib/components/dashboard/widget-registry.ts @@ -21,7 +21,7 @@ import PictureRecentWidget from './widgets/PictureRecentWidget.svelte'; import CardsProgressWidget from './widgets/CardsProgressWidget.svelte'; import ClockTimersWidget from './widgets/ClockTimersWidget.svelte'; import StorageUsageWidget from './widgets/StorageUsageWidget.svelte'; -import MukkeLibraryWidget from './widgets/MukkeLibraryWidget.svelte'; +import MusicLibraryWidget from './widgets/MusicLibraryWidget.svelte'; import PresiDecksWidget from './widgets/PresiDecksWidget.svelte'; import ContextDocsWidget from './widgets/ContextDocsWidget.svelte'; @@ -30,6 +30,7 @@ import RecentContactsWidget from '$lib/modules/core/widgets/RecentContactsWidget import ActiveTimerWidget from '$lib/modules/core/widgets/ActiveTimerWidget.svelte'; import NutritionProgressWidget from '$lib/modules/core/widgets/NutritionProgressWidget.svelte'; import PlantWateringWidget from '$lib/modules/core/widgets/PlantWateringWidget.svelte'; +import DayTimelineWidget from './widgets/DayTimelineWidget.svelte'; export const widgetComponents: Record = { credits: CreditsWidget, @@ -46,10 +47,11 @@ export const widgetComponents: Record = { 'cards-progress': CardsProgressWidget, 'clock-timers': ClockTimersWidget, 'storage-usage': StorageUsageWidget, - 'mukke-library': MukkeLibraryWidget, + 'music-library': MusicLibraryWidget, 'presi-decks': PresiDecksWidget, 'context-docs': ContextDocsWidget, 'active-timer': ActiveTimerWidget, 'nutrition-progress': NutritionProgressWidget, 'plant-watering': PlantWateringWidget, + 'day-timeline': DayTimelineWidget, }; diff --git a/apps/manacore/apps/web/src/lib/components/dashboard/widgets/DayTimelineWidget.svelte b/apps/manacore/apps/web/src/lib/components/dashboard/widgets/DayTimelineWidget.svelte new file mode 100644 index 000000000..32809953c --- /dev/null +++ b/apps/manacore/apps/web/src/lib/components/dashboard/widgets/DayTimelineWidget.svelte @@ -0,0 +1,177 @@ + + +
+
+

+ + {$_('dashboard.widgets.day_timeline.title', { default: 'Mein Tag' })} +

+ {#if blocks.length > 0} + + {blocks.length} + + {/if} +
+ + {#if blocksQuery.loading} +
+ {#each Array(4) as _} +
+ {/each} +
+ {:else if blocks.length === 0} +
+
+

+ {$_('dashboard.widgets.day_timeline.empty', { default: 'Noch nichts heute' })} +

+
+ {:else} + + {#if totalMinutes > 0} +
+ {formatDuration(totalMinutes * 60)} erfasst + {#each [...typeCounts().entries()] as [type, count]} + {@const cfg = typeConfig[type]} + {#if cfg} + + + {count} + + {/if} + {/each} +
+ {/if} + + +
+ {#each displayedBlocks as block (block.id)} + {@const cfg = typeConfig[block.type] ?? typeConfig.event} + {@const habitIcon = + block.type === 'habit' && block.icon ? getIconComponent(block.icon) : null} + {@const duration = getBlockDuration(block)} +
+ +
+
+ {#if habitIcon} + + {:else} + + {/if} +
+ + +
+

{block.title}

+
+ {formatBlockTime(block)} + {#if duration > 0} + {formatDuration(duration)} + {/if} + {#if block.isLive} + live + {/if} +
+
+
+ {/each} + + {#if remainingCount > 0} + + +{remainingCount} weitere + + {/if} +
+ {/if} +
diff --git a/apps/manacore/apps/web/src/lib/types/dashboard.ts b/apps/manacore/apps/web/src/lib/types/dashboard.ts index 18b89d53e..a4b904ddd 100644 --- a/apps/manacore/apps/web/src/lib/types/dashboard.ts +++ b/apps/manacore/apps/web/src/lib/types/dashboard.ts @@ -22,12 +22,13 @@ export type WidgetType = | 'cards-progress' // Cards API: learning progress | 'clock-timers' // Clock: active timers and alarms | 'storage-usage' // Storage: file storage stats - | 'mukke-library' // Mukke: music library stats + | 'music-library' // Music: music library stats | 'presi-decks' // Presi: recent presentations | 'context-docs' // Context: recent documents & spaces | 'active-timer' // Times: running timer | 'nutrition-progress' // NutriPhi: today's calorie progress - | 'plant-watering'; // Planta: plants due for watering + | 'plant-watering' // Planta: plants due for watering + | 'day-timeline'; // TimeBlocks: chronological day timeline /** * Widget size - maps to CSS Grid columns @@ -121,7 +122,7 @@ export interface WidgetMeta { | 'picture' | 'cards' | 'storage' - | 'mukke' + | 'music' | 'presi' | 'context' | 'times' @@ -251,13 +252,13 @@ export const WIDGET_REGISTRY: WidgetMeta[] = [ requiredBackend: 'storage', }, { - type: 'mukke-library', - nameKey: 'dashboard.widgets.mukke.title', - descriptionKey: 'dashboard.widgets.mukke.description', + type: 'music-library', + nameKey: 'dashboard.widgets.music.title', + descriptionKey: 'dashboard.widgets.music.description', icon: '🎵', defaultSize: 'medium', allowMultiple: false, - requiredBackend: 'mukke', + requiredBackend: 'music', }, { type: 'presi-decks', @@ -313,6 +314,14 @@ export const WIDGET_REGISTRY: WidgetMeta[] = [ allowMultiple: false, requiredBackend: 'planta', }, + { + type: 'day-timeline', + nameKey: 'dashboard.widgets.day_timeline.title', + descriptionKey: 'dashboard.widgets.day_timeline.description', + icon: '⏱️', + defaultSize: 'medium', + allowMultiple: false, + }, ]; /**