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 fa4c628aa..60d91e5a8 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 @@ -25,6 +25,12 @@ import MukkeLibraryWidget from './widgets/MukkeLibraryWidget.svelte'; import PresiDecksWidget from './widgets/PresiDecksWidget.svelte'; import ContextDocsWidget from './widgets/ContextDocsWidget.svelte'; +// Phase 4: Unified app widgets (direct Dexie queries, internal routing) +import RecentContactsWidget from '$lib/modules/core/widgets/RecentContactsWidget.svelte'; +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'; + export const widgetComponents: Record = { credits: CreditsWidget, 'quick-actions': QuickActionsWidget, @@ -34,6 +40,7 @@ export const widgetComponents: Record = { 'calendar-events': CalendarEventsWidget, 'chat-recent': ChatRecentWidget, 'contacts-favorites': ContactsFavoritesWidget, + 'contacts-recent': RecentContactsWidget, 'zitare-quote': ZitareQuoteWidget, 'picture-recent': PictureRecentWidget, 'cards-progress': CardsProgressWidget, @@ -42,4 +49,7 @@ export const widgetComponents: Record = { 'mukke-library': MukkeLibraryWidget, 'presi-decks': PresiDecksWidget, 'context-docs': ContextDocsWidget, + 'active-timer': ActiveTimerWidget, + 'nutrition-progress': NutritionProgressWidget, + 'plant-watering': PlantWateringWidget, }; diff --git a/apps/manacore/apps/web/src/lib/i18n/locales/de.json b/apps/manacore/apps/web/src/lib/i18n/locales/de.json index 74c68acb9..e9b7c5d2b 100644 --- a/apps/manacore/apps/web/src/lib/i18n/locales/de.json +++ b/apps/manacore/apps/web/src/lib/i18n/locales/de.json @@ -126,6 +126,22 @@ "documents": "Dokumente", "empty": "Keine Dokumente", "open": "Context öffnen" + }, + "contacts_recent": { + "title": "Letzte Kontakte", + "description": "Kürzlich aktualisierte Kontakte" + }, + "active_timer": { + "title": "Zeiterfassung", + "description": "Laufender Timer" + }, + "nutrition": { + "title": "Ernährung", + "description": "Heutiger Kalorienfortschritt" + }, + "plant_watering": { + "title": "Pflanzenpflege", + "description": "Pflanzen die gegossen werden müssen" } } }, diff --git a/apps/manacore/apps/web/src/lib/i18n/locales/en.json b/apps/manacore/apps/web/src/lib/i18n/locales/en.json index 49eec3c84..2f77ea482 100644 --- a/apps/manacore/apps/web/src/lib/i18n/locales/en.json +++ b/apps/manacore/apps/web/src/lib/i18n/locales/en.json @@ -126,6 +126,22 @@ "documents": "Documents", "empty": "No documents", "open": "Open Context" + }, + "contacts_recent": { + "title": "Recent Contacts", + "description": "Recently updated contacts" + }, + "active_timer": { + "title": "Time Tracking", + "description": "Running timer" + }, + "nutrition": { + "title": "Nutrition", + "description": "Today's calorie progress" + }, + "plant_watering": { + "title": "Plant Care", + "description": "Plants that need watering" } } }, diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/ActiveTimerWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/ActiveTimerWidget.svelte new file mode 100644 index 000000000..186227d62 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/ActiveTimerWidget.svelte @@ -0,0 +1,147 @@ + + +
+
+

Zeiterfassung

+
+ + {#if loading} +
+ {:else if !runningEntry} +
+
+

Kein Timer aktiv.

+ + Timer starten + +
+ {:else} + +
+ {#if runningEntry.projectColor} +
+ {/if} +
+ {#if runningEntry.projectName} +

+ {runningEntry.projectName} +

+ {/if} +

+ {runningEntry.description || 'Ohne Beschreibung'} +

+
+
+ +
+
+
+ {elapsed} +
+
+
+ {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/NutritionProgressWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/NutritionProgressWidget.svelte new file mode 100644 index 000000000..11166f356 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/NutritionProgressWidget.svelte @@ -0,0 +1,176 @@ + + +
+
+

Ernährung heute

+
+ + {#if loading} +
+
+
+ {:else if mealCount === 0} +
+
🍴
+

Noch keine Mahlzeiten erfasst.

+ + Mahlzeit erfassen + +
+ {:else} + + +
+
+ + + + +
+ {percentage}% +
+
+
+ + +
+

+ {totalCalories} / {targetCalories} kcal +

+

+ {mealCount} Mahlzeit{mealCount !== 1 ? 'en' : ''} +

+
+ + +
+
+

{totalProtein}g

+

Protein

+
+
+

{totalCarbs}g

+

Carbs

+
+
+

{totalFat}g

+

Fett

+
+
+
+ {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/PlantWateringWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/PlantWateringWidget.svelte new file mode 100644 index 000000000..cdd283c12 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/PlantWateringWidget.svelte @@ -0,0 +1,164 @@ + + +
+
+

Pflanzenpflege

+ {#if plantsToWater.length > 0} + + {plantsToWater.length} + + {/if} +
+ + {#if loading} +
+ {#each Array(3) as _} +
+ {/each} +
+ {:else if totalActive === 0} +
+
🌱
+

Noch keine Pflanzen angelegt.

+ + Pflanze hinzufügen + +
+ {:else if plantsToWater.length === 0} +
+
💧
+

Alle Pflanzen sind versorgt!

+

{totalActive} aktive Pflanzen

+
+ {:else} + + + + Alle Pflanzen anzeigen + + {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/QuickActionsWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/QuickActionsWidget.svelte new file mode 100644 index 000000000..cad049539 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/QuickActionsWidget.svelte @@ -0,0 +1,61 @@ + + +
+
+

Schnellzugriff

+
+ + +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/QuoteOfTheDayWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/QuoteOfTheDayWidget.svelte new file mode 100644 index 000000000..e5995c6f2 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/QuoteOfTheDayWidget.svelte @@ -0,0 +1,85 @@ + + +
+
+

Zitat des Tages

+
+ + {#if loading} +
+ {:else if !favorite} +
+
💡
+

Noch keine Lieblingszitate gespeichert.

+ + Zitate entdecken + +
+ {:else} + +

+ Favorit #{favorite.quoteId} +

+

+ {totalFavorites} Lieblingszitate gespeichert +

+
+ {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/RecentChatsWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/RecentChatsWidget.svelte new file mode 100644 index 000000000..957118963 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/RecentChatsWidget.svelte @@ -0,0 +1,112 @@ + + +
+
+

Chats

+
+ + {#if loading} +
+ {#each Array(3) as _} +
+ {/each} +
+ {:else if conversations.length === 0} +
+
💬
+

Noch keine Unterhaltungen.

+ + Chat starten + +
+ {:else} + + + + Alle Chats anzeigen + + {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/RecentContactsWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/RecentContactsWidget.svelte new file mode 100644 index 000000000..038ff97bd --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/RecentContactsWidget.svelte @@ -0,0 +1,108 @@ + + +
+
+

Kontakte

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

Noch keine Kontakte vorhanden.

+ + Kontakt hinzufügen + +
+ {:else} + + + + Alle Kontakte anzeigen + + {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/TasksTodayWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/TasksTodayWidget.svelte new file mode 100644 index 000000000..4ed622f9f --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/TasksTodayWidget.svelte @@ -0,0 +1,151 @@ + + +
+
+

Aufgaben heute

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

Keine Aufgaben fällig — alles erledigt!

+
+ {:else} + + {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/UpcomingEventsWidget.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/UpcomingEventsWidget.svelte new file mode 100644 index 000000000..0037522e4 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/UpcomingEventsWidget.svelte @@ -0,0 +1,152 @@ + + +
+
+

Termine

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

Keine Termine in den nächsten 7 Tagen.

+
+ {:else} + + {/if} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/WidgetGrid.svelte b/apps/manacore/apps/web/src/lib/modules/core/widgets/WidgetGrid.svelte new file mode 100644 index 000000000..8f52813eb --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/WidgetGrid.svelte @@ -0,0 +1,55 @@ + + +
+ {#each widgets as widget (widget.id)} +
+ + + {#snippet failed(error, reset)} +
+
⚠️
+

+ {(error as Error)?.message || 'Widget-Fehler'} +

+ +
+ {/snippet} +
+
+ {/each} +
diff --git a/apps/manacore/apps/web/src/lib/modules/core/widgets/index.ts b/apps/manacore/apps/web/src/lib/modules/core/widgets/index.ts new file mode 100644 index 000000000..5dfa6d8d7 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/modules/core/widgets/index.ts @@ -0,0 +1,18 @@ +/** + * Core Dashboard Widgets — Phase 4 Cross-App Widgets + * + * Self-contained Svelte 5 components that query the unified IndexedDB + * database directly via Dexie liveQuery. No cross-origin hacks needed + * since all apps share one database in the unified ManaCore app. + */ + +export { default as TasksTodayWidget } from './TasksTodayWidget.svelte'; +export { default as UpcomingEventsWidget } from './UpcomingEventsWidget.svelte'; +export { default as RecentContactsWidget } from './RecentContactsWidget.svelte'; +export { default as QuoteOfTheDayWidget } from './QuoteOfTheDayWidget.svelte'; +export { default as ActiveTimerWidget } from './ActiveTimerWidget.svelte'; +export { default as RecentChatsWidget } from './RecentChatsWidget.svelte'; +export { default as NutritionProgressWidget } from './NutritionProgressWidget.svelte'; +export { default as PlantWateringWidget } from './PlantWateringWidget.svelte'; +export { default as QuickActionsWidget } from './QuickActionsWidget.svelte'; +export { default as WidgetGrid } from './WidgetGrid.svelte'; diff --git a/apps/manacore/apps/web/src/lib/types/dashboard.ts b/apps/manacore/apps/web/src/lib/types/dashboard.ts index 0a64d8c45..fbc850ab7 100644 --- a/apps/manacore/apps/web/src/lib/types/dashboard.ts +++ b/apps/manacore/apps/web/src/lib/types/dashboard.ts @@ -16,6 +16,7 @@ export type WidgetType = | 'calendar-events' // Calendar API: upcoming events | 'chat-recent' // Chat API: recent conversations | 'contacts-favorites' // Contacts API: favorite contacts + | 'contacts-recent' // Contacts: recently updated | 'zitare-quote' // Zitare API: daily inspiration quote | 'picture-recent' // Picture API: recent generations | 'cards-progress' // Cards API: learning progress @@ -23,7 +24,10 @@ export type WidgetType = | 'storage-usage' // Storage: file storage stats | 'mukke-library' // Mukke: music library stats | 'presi-decks' // Presi: recent presentations - | 'context-docs'; // Context: recent documents & spaces + | '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 /** * Widget size - maps to CSS Grid columns @@ -121,6 +125,9 @@ export interface WidgetMeta { | 'mukke' | 'presi' | 'context' + | 'times' + | 'nutriphi' + | 'planta' | 'mana-core-auth'; } @@ -271,6 +278,42 @@ export const WIDGET_REGISTRY: WidgetMeta[] = [ allowMultiple: false, requiredBackend: 'context', }, + { + type: 'contacts-recent', + nameKey: 'dashboard.widgets.contacts_recent.title', + descriptionKey: 'dashboard.widgets.contacts_recent.description', + icon: '👤', + defaultSize: 'medium', + allowMultiple: false, + requiredBackend: 'contacts', + }, + { + type: 'active-timer', + nameKey: 'dashboard.widgets.active_timer.title', + descriptionKey: 'dashboard.widgets.active_timer.description', + icon: '⏱️', + defaultSize: 'small', + allowMultiple: false, + requiredBackend: 'times', + }, + { + type: 'nutrition-progress', + nameKey: 'dashboard.widgets.nutrition.title', + descriptionKey: 'dashboard.widgets.nutrition.description', + icon: '🍽️', + defaultSize: 'small', + allowMultiple: false, + requiredBackend: 'nutriphi', + }, + { + type: 'plant-watering', + nameKey: 'dashboard.widgets.plant_watering.title', + descriptionKey: 'dashboard.widgets.plant_watering.description', + icon: '🌱', + defaultSize: 'small', + allowMultiple: false, + requiredBackend: 'planta', + }, ]; /**