♻️ refactor: centralize AuthGateModal in shared-auth-ui

- Create shared AuthGateModal component in @manacore/shared-auth-ui
- Migrate 4 apps to use shared component: chat, todo, contacts, calendar
- Remove duplicate local AuthGateModal components
- Support for 'save', 'sync', 'feature', 'ai' actions
- Built-in i18n (DE + EN) with custom translation support
- Optional migration info display for session data
- Uses Phosphor icons from @manacore/shared-icons
- Update CONSISTENCY_REPORT.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2026-01-29 15:03:52 +01:00
parent 0d559c99d6
commit 69d405ca84
12 changed files with 363 additions and 698 deletions

View file

@ -1,150 +0,0 @@
<script lang="ts">
import { goto } from '$app/navigation';
interface Props {
visible: boolean;
onClose: () => void;
action?: 'save' | 'sync' | 'feature';
featureName?: string;
}
let { visible, onClose, action = 'save', featureName = '' }: Props = $props();
// Action-specific messages
const messages = {
save: {
title: 'Eigene Termine erstellen',
description:
'Melde dich an, um deine eigenen Termine zu erstellen und auf allen Geräten zu synchronisieren.',
icon: 'cloud',
},
sync: {
title: 'Kostenlos anmelden',
description:
'Mit einem Account werden deine Termine automatisch synchronisiert und bleiben erhalten.',
icon: 'refresh-cw',
},
feature: {
title: `Anmelden für ${featureName}`,
description: `Diese Funktion erfordert ein Konto. Melde dich an, um ${featureName} zu nutzen.`,
icon: 'lock',
},
};
let currentMessage = $derived(messages[action]);
function handleLogin() {
// Store return URL for redirect after login
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}
function handleRegister() {
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}
function handleBackdropClick(e: MouseEvent) {
if (e.target === e.currentTarget) {
onClose();
}
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') {
onClose();
}
}
</script>
<svelte:window onkeydown={handleKeydown} />
{#if visible}
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
onclick={handleBackdropClick}
>
<div
class="bg-card border-border mx-4 w-full max-w-md rounded-xl border p-6 shadow-2xl"
role="dialog"
aria-modal="true"
aria-labelledby="auth-gate-title"
>
<!-- Icon -->
<div
class="bg-primary/10 mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full"
>
{#if currentMessage.icon === 'cloud'}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
/>
</svg>
{:else if currentMessage.icon === 'refresh-cw'}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
{:else}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
{/if}
</div>
<!-- Title -->
<h2 id="auth-gate-title" class="mb-2 text-center text-xl font-semibold">
{currentMessage.title}
</h2>
<!-- Description -->
<p class="text-muted-foreground mb-6 text-center text-sm">
{currentMessage.description}
</p>
<!-- Buttons -->
<div class="flex flex-col gap-3">
<button
onclick={handleLogin}
class="bg-primary text-primary-foreground hover:bg-primary/90 w-full rounded-lg px-4 py-3 font-medium transition-colors"
>
Anmelden
</button>
<button
onclick={handleRegister}
class="bg-secondary text-secondary-foreground hover:bg-secondary/80 w-full rounded-lg px-4 py-3 font-medium transition-colors"
>
Kostenloses Konto erstellen
</button>
<button
onclick={onClose}
class="text-muted-foreground hover:text-foreground w-full py-2 text-sm transition-colors"
>
Später
</button>
</div>
<!-- Info text -->
<p class="text-muted-foreground mt-4 text-center text-xs">
Du kannst im Demo-Modus die Beispiel-Termine ansehen, aber keine eigenen erstellen.
</p>
</div>
</div>
{/if}

View file

@ -64,7 +64,7 @@
import EventContextMenu from '$lib/components/event/EventContextMenu.svelte';
import ViewModePillContextMenu from '$lib/components/calendar/ViewModePillContextMenu.svelte';
import SettingsModal from '$lib/components/settings/SettingsModal.svelte';
import AuthGateModal from '$lib/components/AuthGateModal.svelte';
import { AuthGateModal } from '@manacore/shared-auth-ui';
import VoiceRecordButton from '$lib/components/voice/VoiceRecordButton.svelte';
import VoiceRecordingModal from '$lib/components/voice/VoiceRecordingModal.svelte';
import { voiceRecordingStore } from '$lib/stores/voice-recording.svelte';
@ -864,7 +864,23 @@
<AuthGateModal
visible={showAuthGateModal}
onClose={() => (showAuthGateModal = false)}
onLogin={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}}
onRegister={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}}
action={authGateAction}
locale={currentLocale === 'en' ? 'en' : 'de'}
infoText="Du kannst im Demo-Modus die Beispiel-Termine ansehen, aber keine eigenen erstellen."
/>
<!-- Guest Welcome Modal -->

View file

@ -1,230 +0,0 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { browser } from '$app/environment';
type Props = {
open: boolean;
action?: 'save' | 'sync' | 'ai' | 'feature';
conversationCount?: number;
onClose: () => void;
};
let { open, action = 'ai', conversationCount = 0, onClose }: Props = $props();
// Messages based on action type
const messages = {
save: {
title: 'Unterhaltungen speichern',
description: 'Melde dich an, um deine Unterhaltungen dauerhaft in der Cloud zu speichern.',
},
sync: {
title: 'Unterhaltungen synchronisieren',
description: 'Melde dich an, um deine Unterhaltungen auf allen Geräten zu synchronisieren.',
},
ai: {
title: 'KI-Antworten erhalten',
description:
'Um KI-Antworten zu erhalten, ist eine Anmeldung erforderlich. Dies ermöglicht uns, die Kosten für die KI-Verarbeitung zu verwalten.',
},
feature: {
title: 'Funktion freischalten',
description: 'Diese Funktion ist nur für angemeldete Benutzer verfügbar.',
},
};
const currentMessage = $derived(messages[action] || messages.ai);
function handleLogin() {
if (browser) {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}
function handleRegister() {
if (browser) {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}
</script>
{#if open}
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div class="modal-backdrop" onclick={onClose}>
<div class="modal-content" onclick={(e) => e.stopPropagation()}>
<div class="modal-header">
<h2>{currentMessage.title}</h2>
<button class="close-btn" onclick={onClose} aria-label="Schliessen">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div class="modal-body">
<p>{currentMessage.description}</p>
{#if conversationCount > 0}
<div class="migration-info">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="16" x2="12" y2="12"></line>
<line x1="12" y1="8" x2="12.01" y2="8"></line>
</svg>
<span
>Du hast {conversationCount}
{conversationCount === 1 ? 'Unterhaltung' : 'Unterhaltungen'} in deiner Session. Diese
werden nach der Anmeldung in deinen Account übertragen.</span
>
</div>
{/if}
</div>
<div class="modal-actions">
<button class="btn btn-secondary" onclick={onClose}> Später </button>
<button class="btn btn-primary" onclick={handleLogin}> Anmelden </button>
<button class="btn btn-outline" onclick={handleRegister}> Registrieren </button>
</div>
</div>
</div>
{/if}
<style>
.modal-backdrop {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
padding: 1rem;
}
.modal-content {
background-color: var(--color-background, white);
border-radius: 0.75rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
max-width: 28rem;
width: 100%;
padding: 1.5rem;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
.modal-header h2 {
font-size: 1.25rem;
font-weight: 600;
color: var(--color-foreground, #1f2937);
margin: 0;
}
.close-btn {
background: none;
border: none;
cursor: pointer;
padding: 0.25rem;
color: var(--color-muted-foreground, #6b7280);
border-radius: 0.375rem;
transition: color 0.15s;
}
.close-btn:hover {
color: var(--color-foreground, #1f2937);
}
.modal-body {
margin-bottom: 1.5rem;
}
.modal-body p {
color: var(--color-muted-foreground, #6b7280);
margin: 0 0 1rem 0;
line-height: 1.5;
}
.migration-info {
display: flex;
gap: 0.75rem;
padding: 0.75rem;
background-color: var(--color-primary-50, #eff6ff);
border-radius: 0.5rem;
font-size: 0.875rem;
color: var(--color-primary-700, #1d4ed8);
}
.migration-info svg {
flex-shrink: 0;
margin-top: 0.125rem;
}
.modal-actions {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
}
.btn {
padding: 0.625rem 1rem;
border-radius: 0.5rem;
font-weight: 500;
font-size: 0.875rem;
cursor: pointer;
transition: all 0.15s;
border: 1px solid transparent;
}
.btn-primary {
background-color: var(--color-primary, #3b82f6);
color: white;
flex: 1;
}
.btn-primary:hover {
background-color: var(--color-primary-600, #2563eb);
}
.btn-secondary {
background-color: var(--color-muted, #f3f4f6);
color: var(--color-muted-foreground, #6b7280);
}
.btn-secondary:hover {
background-color: var(--color-muted-200, #e5e7eb);
}
.btn-outline {
background-color: transparent;
border-color: var(--color-border, #e5e7eb);
color: var(--color-foreground, #1f2937);
}
.btn-outline:hover {
background-color: var(--color-muted, #f3f4f6);
}
</style>

View file

@ -24,8 +24,11 @@
import { getPillAppItems } from '@manacore/shared-branding';
import { getLanguageDropdownItems, getCurrentLanguageLabel } from '@manacore/shared-i18n';
import { setLocale, supportedLocales } from '$lib/i18n';
import AuthGateModal from '$lib/components/AuthGateModal.svelte';
import { GuestWelcomeModal, shouldShowGuestWelcome } from '@manacore/shared-auth-ui';
import {
AuthGateModal,
GuestWelcomeModal,
shouldShowGuestWelcome,
} from '@manacore/shared-auth-ui';
import type { LayoutData } from './$types';
// App switcher items
@ -296,10 +299,25 @@
<!-- Auth Gate Modal -->
<AuthGateModal
open={showAuthGateModal}
action={authGateAction}
conversationCount={sessionConversationCount}
visible={showAuthGateModal}
onClose={() => (showAuthGateModal = false)}
onLogin={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}}
onRegister={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}}
action={authGateAction}
migrationCount={sessionConversationCount}
locale={currentLocale === 'en' ? 'en' : 'de'}
/>
<!-- Guest Welcome Modal -->

View file

@ -1,151 +0,0 @@
<script lang="ts">
import { goto } from '$app/navigation';
interface Props {
visible: boolean;
onClose: () => void;
action?: 'save' | 'sync' | 'feature';
featureName?: string;
}
let { visible, onClose, action = 'save', featureName = '' }: Props = $props();
// Action-specific messages
const messages = {
save: {
title: 'Anmelden um zu speichern',
description:
'Im Demo-Modus kannst du die App erkunden. Melde dich an, um eigene Kontakte zu erstellen und zu speichern.',
icon: 'cloud',
},
sync: {
title: 'Anmelden für Cloud-Sync',
description:
'Mit einem Account werden deine Kontakte automatisch synchronisiert und bleiben erhalten.',
icon: 'refresh-cw',
},
feature: {
title: `Anmelden für ${featureName}`,
description: `Diese Funktion erfordert ein Konto. Melde dich an, um ${featureName} zu nutzen.`,
icon: 'lock',
},
};
let currentMessage = $derived(messages[action]);
function handleLogin() {
// Store return URL for redirect after login
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}
function handleRegister() {
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}
function handleBackdropClick(e: MouseEvent) {
if (e.target === e.currentTarget) {
onClose();
}
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') {
onClose();
}
}
</script>
<svelte:window onkeydown={handleKeydown} />
{#if visible}
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
onclick={handleBackdropClick}
>
<div
class="bg-card border-border mx-4 w-full max-w-md rounded-xl border p-6 shadow-2xl"
role="dialog"
aria-modal="true"
aria-labelledby="auth-gate-title"
>
<!-- Icon -->
<div
class="bg-primary/10 mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full"
>
{#if currentMessage.icon === 'cloud'}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
/>
</svg>
{:else if currentMessage.icon === 'refresh-cw'}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
{:else}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
{/if}
</div>
<!-- Title -->
<h2 id="auth-gate-title" class="mb-2 text-center text-xl font-semibold">
{currentMessage.title}
</h2>
<!-- Description -->
<p class="text-muted-foreground mb-6 text-center text-sm">
{currentMessage.description}
</p>
<!-- Buttons -->
<div class="flex flex-col gap-3">
<button
onclick={handleLogin}
class="bg-primary text-primary-foreground hover:bg-primary/90 w-full rounded-lg px-4 py-3 font-medium transition-colors"
>
Anmelden
</button>
<button
onclick={handleRegister}
class="bg-secondary text-secondary-foreground hover:bg-secondary/80 w-full rounded-lg px-4 py-3 font-medium transition-colors"
>
Kostenloses Konto erstellen
</button>
<button
onclick={onClose}
class="text-muted-foreground hover:text-foreground w-full py-2 text-sm transition-colors"
>
Später
</button>
</div>
<!-- Info text -->
<p class="text-muted-foreground mt-4 text-center text-xs">
Im Demo-Modus werden Beispielkontakte angezeigt. Melde dich an, um eigene Kontakte zu
erstellen.
</p>
</div>
</div>
{/if}

View file

@ -46,8 +46,11 @@
formatParsedContactPreview,
} from '$lib/utils/contact-parser';
import ContactsToolbar from '$lib/components/ContactsToolbar.svelte';
import AuthGateModal from '$lib/components/AuthGateModal.svelte';
import { GuestWelcomeModal, shouldShowGuestWelcome } from '@manacore/shared-auth-ui';
import {
AuthGateModal,
GuestWelcomeModal,
shouldShowGuestWelcome,
} from '@manacore/shared-auth-ui';
import { browser } from '$app/environment';
// Tags state for Quick-Create
@ -483,7 +486,23 @@
<AuthGateModal
visible={showAuthGateModal}
onClose={() => (showAuthGateModal = false)}
onLogin={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}}
onRegister={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}}
action={authGateAction}
locale={currentLocale === 'en' ? 'en' : 'de'}
infoText="Im Demo-Modus werden Beispielkontakte angezeigt. Melde dich an, um eigene Kontakte zu erstellen."
/>
<!-- Guest Welcome Modal -->

View file

@ -1,151 +0,0 @@
<script lang="ts">
import { goto } from '$app/navigation';
interface Props {
visible: boolean;
onClose: () => void;
action?: 'save' | 'sync' | 'feature';
featureName?: string;
}
let { visible, onClose, action = 'save', featureName = '' }: Props = $props();
// Action-specific messages
const messages = {
save: {
title: 'Anmelden um zu speichern',
description:
'Im Demo-Modus kannst du die App erkunden. Melde dich an, um eigene Aufgaben zu erstellen und zu speichern.',
icon: 'cloud',
},
sync: {
title: 'Anmelden für Cloud-Sync',
description:
'Mit einem Account werden deine Aufgaben automatisch synchronisiert und bleiben erhalten.',
icon: 'refresh-cw',
},
feature: {
title: `Anmelden für ${featureName}`,
description: `Diese Funktion erfordert ein Konto. Melde dich an, um ${featureName} zu nutzen.`,
icon: 'lock',
},
};
let currentMessage = $derived(messages[action]);
function handleLogin() {
// Store return URL for redirect after login
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}
function handleRegister() {
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}
function handleBackdropClick(e: MouseEvent) {
if (e.target === e.currentTarget) {
onClose();
}
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') {
onClose();
}
}
</script>
<svelte:window onkeydown={handleKeydown} />
{#if visible}
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div
class="fixed inset-0 z-[9995] flex items-center justify-center bg-black/50 backdrop-blur-sm"
onclick={handleBackdropClick}
>
<div
class="bg-card border-border mx-4 w-full max-w-md rounded-xl border p-6 shadow-2xl"
role="dialog"
aria-modal="true"
aria-labelledby="auth-gate-title"
>
<!-- Icon -->
<div
class="bg-primary/10 mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full"
>
{#if currentMessage.icon === 'cloud'}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
/>
</svg>
{:else if currentMessage.icon === 'refresh-cw'}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
{:else}
<svg class="text-primary h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
{/if}
</div>
<!-- Title -->
<h2 id="auth-gate-title" class="mb-2 text-center text-xl font-semibold">
{currentMessage.title}
</h2>
<!-- Description -->
<p class="text-muted-foreground mb-6 text-center text-sm">
{currentMessage.description}
</p>
<!-- Buttons -->
<div class="flex flex-col gap-3">
<button
onclick={handleLogin}
class="bg-primary text-primary-foreground hover:bg-primary/90 w-full rounded-lg px-4 py-3 font-medium transition-colors"
>
Anmelden
</button>
<button
onclick={handleRegister}
class="bg-secondary text-secondary-foreground hover:bg-secondary/80 w-full rounded-lg px-4 py-3 font-medium transition-colors"
>
Kostenloses Konto erstellen
</button>
<button
onclick={onClose}
class="text-muted-foreground hover:text-foreground w-full py-2 text-sm transition-colors"
>
Später
</button>
</div>
<!-- Info text -->
<p class="text-muted-foreground mt-4 text-center text-xs">
Du kannst die Demo-Aufgaben ansehen, aber um eigene Aufgaben zu erstellen benötigst du ein
Konto.
</p>
</div>
</div>
{/if}

View file

@ -39,8 +39,11 @@
import { getPillAppItems } from '@manacore/shared-branding';
import { getTasks } from '$lib/api/tasks';
import { parseTaskInput, resolveTaskIds, formatParsedTaskPreview } from '$lib/utils/task-parser';
import AuthGateModal from '$lib/components/AuthGateModal.svelte';
import { GuestWelcomeModal, shouldShowGuestWelcome } from '@manacore/shared-auth-ui';
import {
AuthGateModal,
GuestWelcomeModal,
shouldShowGuestWelcome,
} from '@manacore/shared-auth-ui';
import { browser } from '$app/environment';
// App switcher items
@ -515,7 +518,23 @@
<AuthGateModal
visible={showAuthGateModal}
onClose={() => (showAuthGateModal = false)}
onLogin={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/login');
}}
onRegister={() => {
showAuthGateModal = false;
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('auth-return-url', window.location.pathname);
}
goto('/register');
}}
action={authGateAction}
locale={currentLocale === 'en' ? 'en' : 'de'}
infoText="Du kannst die Demo-Aufgaben ansehen, aber um eigene Aufgaben zu erstellen benötigst du ein Konto."
/>
<!-- Guest Welcome Modal -->