From a893b07b70859864bc62d11c9246dd59efdf7c4a Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 31 Mar 2026 21:16:16 +0200 Subject: [PATCH] =?UTF-8?q?feat(guides):=20complete=20Phase=201=20?= =?UTF-8?q?=E2=80=94=20auth=20routes,=20i18n,=20collection=20detail,=20imp?= =?UTF-8?q?ort=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add auth routes: login, register, forgot-password, reset-password (teal branding) - Add i18n setup with de/en locales - Add version.ts and theme store - Add collections/[id] detail page with path progress and per-guide actions - Fix import naming conflict (guidesStore → dbStore alias in app layout) - Fix BaseRecord inline imports → top-level imports in stores and components - Fix authStore.getAccessToken() → getValidToken() - Fix theme import to use local store wrapper - Update plan doc: Phase 1 complete Co-Authored-By: Claude Sonnet 4.6 --- .claude/plans/mana-guides.md | 9 +- .../src/lib/components/GuideEditModal.svelte | 3 +- apps/guides/apps/web/src/lib/i18n/index.ts | 23 +++ .../apps/web/src/lib/i18n/locales/de.json | 22 +++ .../apps/web/src/lib/i18n/locales/en.json | 22 +++ .../apps/web/src/lib/stores/guides.svelte.ts | 9 +- apps/guides/apps/web/src/lib/stores/theme.ts | 3 + apps/guides/apps/web/src/lib/version.ts | 4 + .../apps/web/src/routes/(app)/+layout.svelte | 7 +- .../(app)/collections/[id]/+page.svelte | 174 ++++++++++++++++++ .../(auth)/forgot-password/+page.svelte | 29 +++ .../web/src/routes/(auth)/login/+page.svelte | 56 ++++++ .../src/routes/(auth)/register/+page.svelte | 39 ++++ .../routes/(auth)/reset-password/+page.svelte | 91 +++++++++ .../guides/apps/web/src/routes/+layout.svelte | 2 +- 15 files changed, 480 insertions(+), 13 deletions(-) create mode 100644 apps/guides/apps/web/src/lib/i18n/index.ts create mode 100644 apps/guides/apps/web/src/lib/i18n/locales/de.json create mode 100644 apps/guides/apps/web/src/lib/i18n/locales/en.json create mode 100644 apps/guides/apps/web/src/lib/stores/theme.ts create mode 100644 apps/guides/apps/web/src/lib/version.ts create mode 100644 apps/guides/apps/web/src/routes/(app)/collections/[id]/+page.svelte create mode 100644 apps/guides/apps/web/src/routes/(auth)/forgot-password/+page.svelte create mode 100644 apps/guides/apps/web/src/routes/(auth)/login/+page.svelte create mode 100644 apps/guides/apps/web/src/routes/(auth)/register/+page.svelte create mode 100644 apps/guides/apps/web/src/routes/(auth)/reset-password/+page.svelte diff --git a/.claude/plans/mana-guides.md b/.claude/plans/mana-guides.md index e4feec321..6443faae3 100644 --- a/.claude/plans/mana-guides.md +++ b/.claude/plans/mana-guides.md @@ -133,19 +133,22 @@ apps/guides/apps/web/src/routes/ ## Phasen -### Phase 1 — MVP (jetzt implementiert) ✓ +### Phase 1 — MVP ✅ Abgeschlossen - [x] Monorepo-Skelett (package.json, config-files) - [x] Local-Store (5 Collections) - [x] Guest-Seed (3 Demo-Guides) +- [x] i18n Setup (de + en) +- [x] version.ts +- [x] theme Store - [x] Root-Layout + Auth-Layout +- [x] Auth-Routes (login, register, forgot-password, reset-password) - [x] Bibliothek-View (+page.svelte) - [x] Guide-Detail-View - [x] Run-Modus (Scroll + Fokus) -- [x] Collections-View +- [x] Collections-View + Collections-Detail [id] - [x] Verlauf-View - [x] GuideCard-Komponente - [x] GuideEditModal -- [x] RunView-Komponente - [x] Registrierung in mana-apps.ts + app-icons.ts ### Phase 2 — Web-Import & Sharing diff --git a/apps/guides/apps/web/src/lib/components/GuideEditModal.svelte b/apps/guides/apps/web/src/lib/components/GuideEditModal.svelte index 7c48d41be..588f4feb6 100644 --- a/apps/guides/apps/web/src/lib/components/GuideEditModal.svelte +++ b/apps/guides/apps/web/src/lib/components/GuideEditModal.svelte @@ -1,7 +1,8 @@ diff --git a/apps/guides/apps/web/src/routes/(app)/collections/[id]/+page.svelte b/apps/guides/apps/web/src/routes/(app)/collections/[id]/+page.svelte new file mode 100644 index 000000000..452cf5f39 --- /dev/null +++ b/apps/guides/apps/web/src/routes/(app)/collections/[id]/+page.svelte @@ -0,0 +1,174 @@ + + +{#if !collection} +
+

Sammlung nicht gefunden.

+
+{:else} +
+ + ← Sammlungen + + + +
+
+ {collection.coverEmoji ?? (collection.type === 'path' ? '🗺' : '📚')} +
+
+

{collection.title}

+ + {collection.type === 'path' ? 'Lernpfad' : 'Bibliothek'} + +
+ {#if collection.description} +

{collection.description}

+ {/if} +
{guides.length} Anleitungen
+
+
+ + {#if collection.type === 'path'} +
+
+ {completedCount} von {guides.length} abgeschlossen + {progress}% +
+
+
+
+
+ {/if} +
+ + +
+ {#each guides as guide, i (guide.id)} + {@const completed = isGuideCompleted(guide.id)} + {@const lastRun = getLastRunDate(guide.id)} +
+ + {#if collection.type === 'path'} +
+ {completed ? '✓' : i + 1} +
+ {:else} + {guide.coverEmoji ?? '📖'} + {/if} + + +
+ + {guide.title} + +
+ {difficultyConfig[guide.difficulty].label} + {#if guide.estimatedMinutes} + · {guide.estimatedMinutes}min + {/if} + {#if lastRun} + · ✓ {lastRun} + {/if} +
+
+ + + +
+ {/each} +
+ + {#if guides.length === 0} +
+

Diese Sammlung enthält noch keine Anleitungen.

+
+ {/if} +
+{/if} diff --git a/apps/guides/apps/web/src/routes/(auth)/forgot-password/+page.svelte b/apps/guides/apps/web/src/routes/(auth)/forgot-password/+page.svelte new file mode 100644 index 000000000..40b5d7eda --- /dev/null +++ b/apps/guides/apps/web/src/routes/(auth)/forgot-password/+page.svelte @@ -0,0 +1,29 @@ + + + diff --git a/apps/guides/apps/web/src/routes/(auth)/login/+page.svelte b/apps/guides/apps/web/src/routes/(auth)/login/+page.svelte new file mode 100644 index 000000000..7e2ed6881 --- /dev/null +++ b/apps/guides/apps/web/src/routes/(auth)/login/+page.svelte @@ -0,0 +1,56 @@ + + + + {translations.title} | Guides + + + authStore.signIn(email, password)} + onResendVerification={(email) => authStore.resendVerificationEmail(email)} + passkeyAvailable={authStore.isPasskeyAvailable()} + onSignInWithPasskey={() => authStore.signInWithPasskey()} + onVerifyTwoFactor={(code, trust) => authStore.verifyTwoFactor(code, trust)} + onVerifyBackupCode={(code) => authStore.verifyBackupCode(code)} + onSendMagicLink={(email) => authStore.sendMagicLink(email)} + {goto} + successRedirect={redirectTo} + registerPath="/register" + forgotPasswordPath="/forgot-password" + lightBackground="#f0fdfa" + darkBackground="#042f2e" + {translations} + {verified} + {initialEmail} + version={APP_VERSION} + buildTime={BUILD_TIME} +/> diff --git a/apps/guides/apps/web/src/routes/(auth)/register/+page.svelte b/apps/guides/apps/web/src/routes/(auth)/register/+page.svelte new file mode 100644 index 000000000..531581b4f --- /dev/null +++ b/apps/guides/apps/web/src/routes/(auth)/register/+page.svelte @@ -0,0 +1,39 @@ + + + + {translations.title} | Guides + + + authStore.signUp(email, password)} + onResendVerification={(email) => authStore.resendVerificationEmail(email)} + {goto} + successRedirect={redirectTo} + loginPath="/login" + lightBackground="#f0fdfa" + darkBackground="#042f2e" + {translations} +/> diff --git a/apps/guides/apps/web/src/routes/(auth)/reset-password/+page.svelte b/apps/guides/apps/web/src/routes/(auth)/reset-password/+page.svelte new file mode 100644 index 000000000..241cf15c7 --- /dev/null +++ b/apps/guides/apps/web/src/routes/(auth)/reset-password/+page.svelte @@ -0,0 +1,91 @@ + + + + Passwort zurücksetzen | Guides + + +
+
+ 📖 Guides +
+ +
+
+

Passwort zurücksetzen

+ + {#if success} +
+
+

Passwort erfolgreich geändert. Du wirst weitergeleitet...

+ Zum Login +
+ {:else if hasToken} +
+
+ {#if error} +
{error}
+ {/if} +
+ + +
+
+ + +
+ +
+
+ {:else} +
+
⚠️
+

Dieser Link ist ungültig oder abgelaufen.

+ + Neuen Link anfordern + +
+ {/if} +
+
+
diff --git a/apps/guides/apps/web/src/routes/+layout.svelte b/apps/guides/apps/web/src/routes/+layout.svelte index 524379b18..b3e97d5dc 100644 --- a/apps/guides/apps/web/src/routes/+layout.svelte +++ b/apps/guides/apps/web/src/routes/+layout.svelte @@ -3,7 +3,7 @@ import '$lib/i18n'; import { onMount } from 'svelte'; import { isLoading as i18nLoading } from 'svelte-i18n'; - import { theme } from '@manacore/shared-theme'; + import { theme } from '$lib/stores/theme'; import { authStore } from '$lib/stores/auth.svelte'; let { children } = $props();