feat: add global start page setting across all apps

- Add GeneralSettings types (startPages, weekStartsOn, soundsEnabled)
- Create app-routes.ts with available routes for 12 apps
- Extend UserSettingsStore with general settings support
- Update GlobalSettingsSection with start page selector UI
- Add start page redirect logic to all app layouts:
  - Clock, Calendar, Todo, Zitare, Picture
  - Manadeck, Presi, Chat, Manacore
- Create user-settings stores for Clock and Todo apps

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-04 16:31:04 +01:00
parent 5b3c5ff4fb
commit bbe540c3f1
16 changed files with 602 additions and 22 deletions

View file

@ -148,6 +148,12 @@
if (authStore.isAuthenticated) {
await calendarsStore.fetchCalendars();
await userSettings.load();
// Redirect to start page if on root and a custom start page is set
const currentPath = window.location.pathname;
if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
goto(userSettings.startPage, { replaceState: true });
}
}
// Initialize sidebar mode from localStorage
@ -225,7 +231,10 @@
class:sidebar-mode={isSidebarMode && !isCollapsed}
class:floating-mode={!isSidebarMode && !isCollapsed}
>
<div class="content-wrapper" class:calendar-expanded={settingsStore.sidebarCollapsed && $page.url.pathname === '/'}>
<div
class="content-wrapper"
class:calendar-expanded={settingsStore.sidebarCollapsed && $page.url.pathname === '/'}
>
{@render children()}
</div>
</main>

View file

@ -160,6 +160,12 @@
// Load user settings
await userSettings.load();
// Redirect to start page if on /chat and a custom start page is set
const currentPath = window.location.pathname;
if (currentPath === '/chat' && userSettings.startPage && userSettings.startPage !== '/chat') {
goto(userSettings.startPage, { replaceState: true });
}
isChecking = false;
});
</script>

View file

@ -0,0 +1,19 @@
/**
* User Settings Store for Clock
*
* This store syncs settings with mana-core-auth and provides:
* - Global settings that apply to all apps
* - Per-app overrides for customization
* - localStorage caching for offline support
*/
import { createUserSettingsStore } from '@manacore/shared-theme';
import { authStore } from './auth.svelte';
const MANA_AUTH_URL = 'http://localhost:3001';
export const userSettings = createUserSettingsStore({
appId: 'clock',
authUrl: MANA_AUTH_URL,
getAccessToken: () => authStore.getAccessToken(),
});

View file

@ -1,8 +1,10 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { theme } from '$lib/stores/theme.svelte';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { setLocale, supportedLocales } from '$lib/i18n';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import { GlobalSettingsSection } from '@manacore/shared-ui';
// Settings state
let clockFormat = $state<'24h' | '12h'>('24h');
@ -29,6 +31,11 @@
es: 'Español',
it: 'Italiano',
};
// Translation function for GlobalSettingsSection
function translate(key: string): string {
return $_?.(key) ?? key;
}
</script>
<div class="mx-auto max-w-2xl space-y-6">
@ -160,4 +167,17 @@
Töne können für einzelne Wecker und Timer in deren Einstellungen angepasst werden.
</p>
</div>
<!-- Global Settings Section -->
<GlobalSettingsSection
{userSettings}
appId="clock"
showNavigation={false}
showTheme={false}
showLanguage={false}
showGeneral={true}
title="Globale Einstellungen"
description="Diese Einstellungen gelten für alle Mana Apps"
t={translate}
/>
</div>

View file

@ -148,6 +148,16 @@
// Load user settings from server
if (authStore.isAuthenticated) {
await userSettings.load();
// Redirect to start page if on /dashboard and a custom start page is set
const currentPath = window.location.pathname;
if (
currentPath === '/dashboard' &&
userSettings.startPage &&
userSettings.startPage !== '/dashboard'
) {
goto(userSettings.startPage, { replaceState: true });
}
}
loading = false;

View file

@ -139,6 +139,12 @@
// Load user settings
await userSettings.load();
// Redirect to start page if on root and a custom start page is set
const currentPath = window.location.pathname;
if (currentPath === '/decks' && userSettings.startPage && userSettings.startPage !== '/decks') {
goto(userSettings.startPage, { replaceState: true });
}
// Initialize sidebar mode from localStorage
const savedSidebar = localStorage.getItem('manadeck-nav-sidebar');
if (savedSidebar === 'true') {

View file

@ -68,7 +68,22 @@
// Load user settings when authenticated
$effect(() => {
if (authStore.initialized && authStore.user) {
userSettings.load();
userSettings.load().then(() => {
// Redirect to start page if on /app and a custom start page is set
const currentPath = window.location.pathname;
if (
currentPath === '/app' &&
userSettings.startPage &&
userSettings.startPage !== '/' &&
userSettings.startPage !== '/app'
) {
// Prepend /app if the start page doesn't include it
const targetPath = userSettings.startPage.startsWith('/app')
? userSettings.startPage
: `/app${userSettings.startPage}`;
goto(targetPath, { replaceState: true });
}
});
}
});

View file

@ -136,6 +136,12 @@
// Load user settings
await userSettings.load();
// Redirect to start page if on root and a custom start page is set
const currentPath = window.location.pathname;
if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
goto(userSettings.startPage, { replaceState: true });
}
// Initialize theme
const cleanup = theme.initialize();

View file

@ -0,0 +1,10 @@
import { createUserSettingsStore } from '@manacore/shared-theme';
import { authStore } from './auth.svelte';
const MANA_AUTH_URL = import.meta.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
export const userSettings = createUserSettingsStore({
appId: 'todo',
authUrl: MANA_AUTH_URL,
getAccessToken: () => authStore.getAccessToken(),
});

View file

@ -6,6 +6,7 @@
import { PillNavigation } from '@manacore/shared-ui';
import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui';
import { authStore } from '$lib/stores/auth.svelte';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { projectsStore } from '$lib/stores/projects.svelte';
import { labelsStore } from '$lib/stores/labels.svelte';
import { theme } from '$lib/stores/theme';
@ -137,7 +138,17 @@
// Load data if authenticated
if (authStore.isAuthenticated) {
await Promise.all([projectsStore.fetchProjects(), labelsStore.fetchLabels()]);
await Promise.all([
projectsStore.fetchProjects(),
labelsStore.fetchLabels(),
userSettings.load(),
]);
// Redirect to start page if on root and a custom start page is set
const currentPath = window.location.pathname;
if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
goto(userSettings.startPage, { replaceState: true });
}
}
// Initialize sidebar mode from localStorage
@ -183,7 +194,7 @@
onModeChange={handleModeChange}
{isCollapsed}
onCollapsedChange={handleCollapsedChange}
desktopPosition="bottom"
desktopPosition={userSettings.nav.desktopPosition}
showThemeToggle={true}
showThemeVariants={true}
{themeVariantItems}

View file

@ -145,6 +145,12 @@
// Load user settings if authenticated
if (authStore.isAuthenticated) {
await userSettings.load();
// Redirect to start page if on root and a custom start page is set
const currentPath = window.location.pathname;
if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
goto(userSettings.startPage, { replaceState: true });
}
}
// Initialize sidebar mode from localStorage