diff --git a/apps/todo/apps/web/package.json b/apps/todo/apps/web/package.json index ee58b549e..26b0f224a 100644 --- a/apps/todo/apps/web/package.json +++ b/apps/todo/apps/web/package.json @@ -40,6 +40,7 @@ }, "dependencies": { "@manacore/shared-api-client": "workspace:*", + "@manacore/shared-app-onboarding": "workspace:*", "@manacore/shared-auth": "workspace:*", "@manacore/shared-auth-ui": "workspace:*", "@manacore/shared-branding": "workspace:*", diff --git a/apps/todo/apps/web/src/lib/stores/app-onboarding.svelte.ts b/apps/todo/apps/web/src/lib/stores/app-onboarding.svelte.ts new file mode 100644 index 000000000..f7b0950ef --- /dev/null +++ b/apps/todo/apps/web/src/lib/stores/app-onboarding.svelte.ts @@ -0,0 +1,99 @@ +import { createAppOnboardingStore, type AppOnboardingStep } from '@manacore/shared-app-onboarding'; +import { userSettings } from './user-settings.svelte'; +import { todoSettings } from './settings.svelte'; + +/** + * Todo-specific onboarding steps + */ +const todoOnboardingSteps: AppOnboardingStep[] = [ + { + id: 'defaultView', + type: 'select', + question: 'Wo möchtest du starten?', + description: 'Du kannst die Ansicht jederzeit wechseln.', + emoji: '📋', + gradient: { from: 'blue-500', to: 'blue-700' }, + options: [ + { + id: 'today', + label: 'Heute', + description: 'Tagesübersicht mit Fälligkeiten (Empfohlen)', + emoji: '☀️', + }, + { + id: 'inbox', + label: 'Eingang', + description: 'Alle unsortierten Aufgaben', + emoji: '📥', + }, + { + id: 'kanban', + label: 'Kanban Board', + description: 'Spalten-basierte Aufgabenverwaltung', + emoji: '📊', + }, + ], + defaultValue: 'today', + }, + { + id: 'compactMode', + type: 'select', + question: 'Wie detailliert sollen Aufgaben angezeigt werden?', + description: 'Bestimmt die Informationsdichte in der Aufgabenliste.', + emoji: '👁️', + gradient: { from: 'indigo-500', to: 'indigo-700' }, + options: [ + { + id: 'normal', + label: 'Normal', + description: 'Mit Projekt, Labels und Fälligkeit', + emoji: '📝', + }, + { + id: 'compact', + label: 'Kompakt', + description: 'Nur Titel und Priorität', + emoji: '📄', + }, + ], + defaultValue: 'normal', + }, + { + id: 'welcome', + type: 'info', + question: 'Bereit für produktive Tage!', + description: 'Hier sind einige Tipps für den Start:', + emoji: '🎉', + gradient: { from: 'primary', to: 'primary/70' }, + bullets: [ + 'Schnelleingabe: "Meeting morgen 14 Uhr !hoch @Arbeit #wichtig"', + 'Nutze @Projekt und #Label direkt beim Erstellen', + 'Drücke "F" für den Fokus-Modus ohne Ablenkungen', + 'Erstelle Projekte, um Aufgaben zu organisieren', + ], + }, +]; + +/** + * Todo app onboarding store + */ +export const todoOnboarding = createAppOnboardingStore({ + appId: 'todo', + steps: todoOnboardingSteps, + userSettings, + onComplete: async (preferences) => { + // Apply default view + const view = preferences.defaultView as string; + if (view === 'today' || view === 'inbox' || view === 'kanban') { + todoSettings.set('defaultView', view); + } + + // Apply compact mode + if (preferences.compactMode === 'compact') { + todoSettings.set('compactMode', true); + } + }, + onSkip: async () => { + // Defaults are sensible, nothing to do + }, +}); diff --git a/apps/todo/apps/web/src/routes/(app)/+layout.svelte b/apps/todo/apps/web/src/routes/(app)/+layout.svelte index 40816c441..3ef9dc01c 100644 --- a/apps/todo/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/todo/apps/web/src/routes/(app)/+layout.svelte @@ -34,6 +34,8 @@ import { getPillAppItems } from '@manacore/shared-branding'; import { getTasks } from '$lib/api/tasks'; import { parseTaskInput, resolveTaskIds, formatParsedTaskPreview } from '$lib/utils/task-parser'; + import { todoOnboarding } from '$lib/stores/app-onboarding.svelte'; + import { MiniOnboardingModal } from '@manacore/shared-app-onboarding'; // App switcher items const appItems = getPillAppItems('todo'); @@ -422,6 +424,10 @@ {@render children()} + + {#if todoOnboarding.shouldShow} + + {/if} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8624afb63..427c0ef66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5065,9 +5065,15 @@ importers: '@nestjs/schematics': specifier: ^10.2.3 version: 10.2.3(chokidar@3.6.0)(typescript@5.9.3) + '@nestjs/testing': + specifier: ^10.4.15 + version: 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.20)(@nestjs/platform-express@10.4.20) '@types/express': specifier: ^5.0.0 version: 5.0.5 + '@types/jest': + specifier: ^29.5.0 + version: 29.5.14 '@types/multer': specifier: ^1.4.12 version: 1.4.13 @@ -5089,12 +5095,18 @@ importers: eslint-plugin-prettier: specifier: ^5.2.1 version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@9.1.2(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2) + jest: + specifier: ^30.2.0 + version: 30.3.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) prettier: specifier: ^3.4.2 version: 3.6.2 source-map-support: specifier: ^0.5.21 version: 0.5.21 + ts-jest: + specifier: ^29.4.0 + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.3.0)(@jest/types@30.3.0)(babel-jest@30.3.0(@babel/core@7.28.5))(esbuild@0.27.0)(jest-util@30.3.0)(jest@30.3.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.1 version: 9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.27.0)) @@ -5180,12 +5192,18 @@ importers: '@tailwindcss/vite': specifier: ^4.1.7 version: 4.1.17(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)) + '@testing-library/svelte': + specifier: ^5.2.0 + version: 5.3.1(svelte@5.44.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4) '@types/node': specifier: ^20.0.0 version: 20.19.25 '@vite-pwa/sveltekit': specifier: ^1.1.0 version: 1.1.0(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.44.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)))(svelte@5.44.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)))(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(workbox-build@7.4.0(@types/babel__core@7.20.5))(workbox-window@7.4.0) + jsdom: + specifier: ^26.1.0 + version: 26.1.0 prettier: specifier: ^3.1.1 version: 3.6.2 @@ -5210,6 +5228,9 @@ importers: vite: specifier: ^6.0.0 version: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + vitest: + specifier: ^3.2.1 + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) apps/storage/packages/shared: devDependencies: @@ -5383,6 +5404,9 @@ importers: '@manacore/shared-api-client': specifier: workspace:* version: link:../../../../packages/shared-api-client + '@manacore/shared-app-onboarding': + specifier: workspace:* + version: link:../../../../packages/shared-app-onboarding '@manacore/shared-auth': specifier: workspace:* version: link:../../../../packages/shared-auth @@ -21249,6 +21273,15 @@ packages: canvas: optional: true + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsdom@27.2.0: resolution: {integrity: sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -39094,6 +39127,15 @@ snapshots: vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) vitest: 2.1.9(@types/node@20.19.25)(jsdom@25.0.1)(lightningcss@1.30.2)(terser@5.44.1) + '@testing-library/svelte@5.3.1(svelte@5.44.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/svelte-core': 1.0.0(svelte@5.44.0) + svelte: 5.44.0 + optionalDependencies: + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + '@testing-library/svelte@5.3.1(svelte@5.44.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@20.19.25)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))': dependencies: '@testing-library/dom': 10.4.1 @@ -40512,11 +40554,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/browser@3.2.4(playwright@1.57.0)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4)': + '@vitest/browser@3.2.4(playwright@1.57.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4)': dependencies: '@testing-library/dom': 10.4.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)) + '@vitest/utils': 3.2.4 + magic-string: 0.30.21 + sirv: 3.0.2 + tinyrainbow: 2.0.0 + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + ws: 8.18.3 + optionalDependencies: + playwright: 1.57.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + + '@vitest/browser@3.2.4(playwright@1.57.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/mocker': 3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)) '@vitest/utils': 3.2.4 magic-string: 0.30.21 sirv: 3.0.2 @@ -40613,6 +40675,14 @@ snapshots: optionalDependencies: vite: 5.4.21(@types/node@24.10.1)(lightningcss@1.30.2)(terser@5.44.1) + '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 @@ -40621,6 +40691,15 @@ snapshots: optionalDependencies: vite: 6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + '@vitest/mocker@3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + optional: true + '@vitest/mocker@4.0.14(vite@6.4.1(@types/node@22.19.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 4.0.14 @@ -40769,7 +40848,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) optional: true '@vitest/ui@4.0.14(vitest@4.0.14)': @@ -50241,6 +50320,33 @@ snapshots: - supports-color - utf-8-validate + jsdom@26.1.0: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.18.3 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsdom@27.2.0: dependencies: '@acemir/cssom': 0.9.24 @@ -58085,6 +58191,27 @@ snapshots: - supports-color - terser + vite-node@3.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vite-node@3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: cac: 6.7.14 @@ -58439,6 +58566,51 @@ snapshots: - supports-color - terser + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.25)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.2.2 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 20.19.25 + '@vitest/browser': 3.2.4(playwright@1.57.0)(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4) + '@vitest/ui': 3.2.4(vitest@3.2.4) + jsdom: 26.1.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: '@types/chai': 5.2.3 @@ -58467,7 +58639,7 @@ snapshots: optionalDependencies: '@types/debug': 4.1.12 '@types/node': 24.10.1 - '@vitest/browser': 3.2.4(playwright@1.57.0)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4) + '@vitest/browser': 3.2.4(playwright@1.57.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1))(vitest@3.2.4) '@vitest/ui': 3.2.4(vitest@3.2.4) jsdom: 27.2.0 transitivePeerDependencies: