From 82da95b855fa68ad41e1a84d12c8e26e2d499187 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Fri, 30 Jan 2026 17:07:17 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20remove(calendar-web):=20remove?= =?UTF-8?q?=20demo=20mode,=20enforce=20login?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove demo events and related data files - Redirect unauthenticated users to /login - Remove AuthGateModal, GuestWelcomeModal - Remove demo banner and related CSS - Simplify events store (no more demo checks) Co-Authored-By: Claude Opus 4.5 --- .../apps/web/src/lib/data/demo-events.ts | 117 --------------- .../apps/web/src/lib/stores/events.svelte.ts | 55 ------- .../apps/web/src/routes/(app)/+layout.svelte | 141 ++---------------- .../apps/web/src/routes/(app)/+page.svelte | 26 ---- 4 files changed, 10 insertions(+), 329 deletions(-) delete mode 100644 apps/calendar/apps/web/src/lib/data/demo-events.ts diff --git a/apps/calendar/apps/web/src/lib/data/demo-events.ts b/apps/calendar/apps/web/src/lib/data/demo-events.ts deleted file mode 100644 index 7ea6c61f5..000000000 --- a/apps/calendar/apps/web/src/lib/data/demo-events.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Demo Events - Static sample events for unauthenticated users - * - * Shows a realistic calendar with various event types to demonstrate - * the app's capabilities without requiring login. - */ - -import type { CalendarEvent } from '@calendar/shared'; -import { addDays, setHours, setMinutes, startOfWeek } from 'date-fns'; - -// Get browser timezone or default to Europe/Berlin -const timezone = - typeof Intl !== 'undefined' ? Intl.DateTimeFormat().resolvedOptions().timeZone : 'Europe/Berlin'; - -/** - * Create a demo event with common defaults - */ -function createDemoEvent( - id: string, - title: string, - dayOffset: number, - startHour: number, - startMinute: number, - endHour: number, - endMinute: number, - color: string, - options: { - description?: string; - location?: string; - isAllDay?: boolean; - } = {} -): CalendarEvent { - const now = new Date(); - const weekStart = startOfWeek(now, { weekStartsOn: 1 }); - const eventDay = addDays(weekStart, dayOffset); - - return { - id: `demo_${id}`, - calendarId: 'demo-calendar', - userId: 'demo', - title, - description: options.description, - location: options.location, - startTime: setMinutes(setHours(eventDay, startHour), startMinute).toISOString(), - endTime: setMinutes(setHours(eventDay, endHour), endMinute).toISOString(), - isAllDay: options.isAllDay ?? false, - timezone, - color, - status: 'confirmed', - createdAt: now.toISOString(), - updatedAt: now.toISOString(), - }; -} - -/** - * Generate demo events relative to the current date - * Events are spread across the current week to always look relevant - */ -export function generateDemoEvents(): CalendarEvent[] { - return [ - // Monday - Work meeting - createDemoEvent('1', 'Team Standup', 0, 9, 0, 9, 30, '#3b82f6', { - description: 'Tägliches Standup Meeting mit dem Entwicklungsteam', - location: 'Meeting Room A', - }), - // Monday - Lunch - createDemoEvent('2', 'Mittagessen mit Lisa', 0, 12, 30, 13, 30, '#10b981', { - location: 'Café Central', - }), - // Tuesday - All day event - createDemoEvent('3', 'Projektabgabe', 1, 0, 0, 23, 59, '#f59e0b', { - description: 'Deadline für das Q1 Projekt', - isAllDay: true, - }), - // Tuesday - Client call - createDemoEvent('4', 'Kundengespräch', 1, 14, 0, 15, 0, '#8b5cf6', { - description: 'Quartals-Review mit Kunde XYZ', - location: 'Zoom', - }), - // Wednesday - Workout - createDemoEvent('5', 'Fitness', 2, 7, 0, 8, 30, '#ef4444', { - description: 'Krafttraining', - location: 'FitGym', - }), - // Wednesday - Long meeting - createDemoEvent('6', 'Sprint Planning', 2, 10, 0, 12, 0, '#3b82f6', { - description: 'Planung für den nächsten Sprint', - location: 'Großer Konferenzraum', - }), - // Thursday - Doctor appointment - createDemoEvent('7', 'Arzttermin', 3, 11, 0, 12, 0, '#ec4899', { - description: 'Jährliche Vorsorgeuntersuchung', - location: 'Dr. Müller, Hauptstraße 15', - }), - // Friday - Team event - createDemoEvent('8', 'Team-Event: Escape Room', 4, 16, 0, 19, 0, '#10b981', { - description: 'Teambuilding Aktivität', - location: 'Escape Berlin', - }), - // Saturday - Weekend activity - createDemoEvent('9', 'Brunch mit Familie', 5, 11, 0, 14, 0, '#f59e0b', { - location: 'Bei Oma', - }), - // Sunday - Relaxation - createDemoEvent('10', 'Yoga-Kurs', 6, 10, 0, 11, 30, '#8b5cf6', { - description: 'Sonntags-Entspannung', - location: 'Yoga Studio Harmony', - }), - ]; -} - -/** - * Check if an event ID is a demo event - */ -export function isDemoEvent(id: string): boolean { - return id.startsWith('demo_'); -} diff --git a/apps/calendar/apps/web/src/lib/stores/events.svelte.ts b/apps/calendar/apps/web/src/lib/stores/events.svelte.ts index 872fc0bd0..8e34815c4 100644 --- a/apps/calendar/apps/web/src/lib/stores/events.svelte.ts +++ b/apps/calendar/apps/web/src/lib/stores/events.svelte.ts @@ -1,7 +1,5 @@ /** * Events Store - Manages calendar events using Svelte 5 runes - * Authenticated users: events from API - * Demo mode: static sample events to showcase the app */ import type { CalendarEvent, CreateEventInput, UpdateEventInput } from '@calendar/shared'; @@ -9,8 +7,6 @@ import * as api from '$lib/api/events'; import { format, isWithinInterval, isSameDay } from 'date-fns'; import { toDate } from '$lib/utils/eventDateHelpers'; import { toastStore } from '@manacore/shared-ui'; -import { authStore } from './auth.svelte'; -import { generateDemoEvents, isDemoEvent } from '$lib/data/demo-events'; // State let events = $state([]); @@ -38,31 +34,11 @@ export const eventsStore = { /** * Fetch events for a date range - * Demo mode: shows static sample events - * Authenticated: fetches from API */ async fetchEvents(startDate: Date, endDate: Date, calendarIds?: string[]) { loading = true; error = null; - // Demo mode: load demo events - if (!authStore.isAuthenticated) { - const demoEvents = generateDemoEvents(); - - // Filter demo events by date range - const filteredEvents = demoEvents.filter((event) => { - const eventStart = toDate(event.startTime); - const eventEnd = toDate(event.endTime); - return eventStart <= endDate && eventEnd >= startDate; - }); - - events = filteredEvents; - loadedRange = { start: startDate, end: endDate }; - loading = false; - return { data: filteredEvents, error: null }; - } - - // Authenticated: fetch from API const result = await api.getEvents({ startDate: format(startDate, "yyyy-MM-dd'T'HH:mm:ss"), endDate: format(endDate, "yyyy-MM-dd'T'HH:mm:ss"), @@ -137,16 +113,8 @@ export const eventsStore = { /** * Create a new event - * Demo mode: returns auth_required error - * Authenticated: creates via API */ async createEvent(data: CreateEventInput) { - // Demo mode: require authentication - if (!authStore.isAuthenticated) { - return { data: null, error: { code: 'auth_required', message: 'Anmeldung erforderlich' } }; - } - - // Authenticated: create via API const result = await api.createEvent(data); if (result.data) { @@ -158,16 +126,8 @@ export const eventsStore = { /** * Update an event - * Demo mode: returns auth_required error - * Authenticated: updates via API */ async updateEvent(id: string, data: UpdateEventInput) { - // Demo event: require authentication - if (isDemoEvent(id) || !authStore.isAuthenticated) { - return { data: null, error: { code: 'auth_required', message: 'Anmeldung erforderlich' } }; - } - - // Cloud event: update via API const result = await api.updateEvent(id, data); if (result.error) { @@ -181,16 +141,8 @@ export const eventsStore = { /** * Delete an event (optimistic update) - * Demo mode: returns auth_required error - * Authenticated: deletes via API */ async deleteEvent(id: string) { - // Demo event: require authentication - if (isDemoEvent(id) || !authStore.isAuthenticated) { - return { data: null, error: { code: 'auth_required', message: 'Anmeldung erforderlich' } }; - } - - // Cloud event: delete via API // Optimistic: remove event immediately const eventToDelete = events.find((e) => e.id === id); events = events.filter((e) => e.id !== id); @@ -282,11 +234,4 @@ export const eventsStore = { isDraftEvent(eventId: string) { return eventId === '__draft__'; }, - - /** - * Check if an event is a demo event - */ - isDemoEvent(eventId: string) { - return isDemoEvent(eventId); - }, }; diff --git a/apps/calendar/apps/web/src/routes/(app)/+layout.svelte b/apps/calendar/apps/web/src/routes/(app)/+layout.svelte index 34a1ac942..c7a7d382d 100644 --- a/apps/calendar/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/calendar/apps/web/src/routes/(app)/+layout.svelte @@ -64,12 +64,10 @@ 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 '@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'; import { eventContextMenuStore } from '$lib/stores/eventContextMenu.svelte'; - import { GuestWelcomeModal, shouldShowGuestWelcome } from '@manacore/shared-auth-ui'; import type { CalendarViewType } from '@calendar/shared'; // App switcher items @@ -539,31 +537,6 @@ } }); - // Auth gate modal state - let showAuthGateModal = $state(false); - let authGateAction = $state<'save' | 'sync' | 'feature'>('save'); - - // Guest welcome modal state - let showGuestWelcome = $state(false); - - // Show auth gate modal (can be called from child components) - function showAuthGate(action: 'save' | 'sync' | 'feature' = 'save') { - authGateAction = action; - showAuthGateModal = true; - } - - // Listen for show-auth-gate events from child components - $effect(() => { - if (browser) { - const handler = (e: Event) => { - const customEvent = e as CustomEvent<{ action?: 'save' | 'sync' | 'feature' }>; - showAuthGate(customEvent.detail?.action || 'save'); - }; - window.addEventListener('show-auth-gate', handler); - return () => window.removeEventListener('show-auth-gate', handler); - } - }); - // Voice recording result handler function handleVoiceResult(transcription: string) { if (!browser) return; @@ -593,25 +566,24 @@ // Initialize auth state from stored tokens await authStore.initialize(); + // Redirect to login if not authenticated + if (!authStore.isAuthenticated) { + goto('/login'); + return; + } + // Initialize split-panel from URL/localStorage splitPanel.initialize(); // Initialize view state viewStore.initialize(); - // Show guest welcome modal for unauthenticated users - if (!authStore.isAuthenticated && shouldShowGuestWelcome('calendar')) { - showGuestWelcome = true; - } - - // Load calendars and tags (works in both guest and authenticated mode) + // Load calendars and tags await calendarsStore.fetchCalendars(); - // Only fetch tags and user settings if authenticated - if (authStore.isAuthenticated) { - await eventTagsStore.fetchTags(); - await userSettings.load(); - } + // Fetch tags and user settings + await eventTagsStore.fetchTags(); + await userSettings.load(); // Note: Birthdays are loaded via reactive $effect when showBirthdays is enabled @@ -653,41 +625,6 @@
- - {#if !authStore.isAuthenticated} -
-
- - - - - - Demo-Modus - - -
- -
- {/if} {#if !settingsStore.immersiveModeEnabled} - - (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." -/> - - - (showGuestWelcome = false)} - onLogin={() => { - showGuestWelcome = false; - goto('/login'); - }} - onRegister={() => { - showGuestWelcome = false; - goto('/register'); - }} - helpHref="/help" - locale={currentLocale === 'en' ? 'en' : 'de'} -/>