🐛 fix(theme): add ShadCN-style CSS variable aliases for shared components

- Add aliases without color- prefix (--background, --foreground, --primary, etc.)
- Fix Mana/Subscription page styling across all apps
- Remove conflicting legacy aliases from contacts app.css
- Update contacts mana page to use toast instead of alert

🤖 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-03 00:20:49 +01:00
parent b01153ba87
commit 482509a574
13 changed files with 836 additions and 185 deletions

View file

@ -4,20 +4,23 @@
import { _ } from 'svelte-i18n';
import { authStore } from '$lib/stores/auth.svelte';
import { theme } from '$lib/stores/theme';
import { settingsStore, type WeekStartDay, type TimeFormat } from '$lib/stores/settings.svelte';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { settingsStore, type WeekStartDay, type TimeFormat, type AllDayDisplayMode } from '$lib/stores/settings.svelte';
import { setLocale, supportedLocales, type SupportedLocale } from '$lib/i18n';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import { GlobalSettingsSection } from '@manacore/shared-ui';
import type { CalendarViewType } from '@calendar/shared';
// Get current locale from svelte-i18n
import { locale } from 'svelte-i18n';
onMount(() => {
onMount(async () => {
if (!authStore.isAuthenticated) {
goto('/login');
return;
}
settingsStore.initialize();
await userSettings.load();
});
function handleThemeChange(mode: 'light' | 'dark' | 'system') {
@ -275,6 +278,85 @@
</div>
</label>
</div>
<div class="setting-item">
<label class="toggle-setting">
<input
type="checkbox"
checked={settingsStore.filterHoursEnabled}
onchange={() => settingsStore.set('filterHoursEnabled', !settingsStore.filterHoursEnabled)}
/>
<div class="toggle-info">
<span class="setting-label">Stunden filtern</span>
<span class="setting-description">Nur bestimmte Stunden in der Tages-/Wochenansicht anzeigen</span>
</div>
</label>
</div>
{#if settingsStore.filterHoursEnabled}
<div class="setting-item hour-range-setting">
<div class="setting-info">
<span class="setting-label">Sichtbare Stunden</span>
<span class="setting-description">Zeitbereich der in der Kalenderansicht angezeigt wird</span>
</div>
<div class="hour-range-inputs">
<div class="hour-input-group">
<label for="start-hour">Von</label>
<select
id="start-hour"
class="select-input hour-select"
value={settingsStore.dayStartHour}
onchange={(e) => settingsStore.set('dayStartHour', Number(e.currentTarget.value))}
>
{#each Array.from({ length: 24 }, (_, i) => i) as hour}
{#if hour < settingsStore.dayEndHour}
<option value={hour}>{hour.toString().padStart(2, '0')}:00</option>
{/if}
{/each}
</select>
</div>
<span class="hour-separator"></span>
<div class="hour-input-group">
<label for="end-hour">Bis</label>
<select
id="end-hour"
class="select-input hour-select"
value={settingsStore.dayEndHour}
onchange={(e) => settingsStore.set('dayEndHour', Number(e.currentTarget.value))}
>
{#each Array.from({ length: 24 }, (_, i) => i + 1) as hour}
{#if hour > settingsStore.dayStartHour}
<option value={hour}>{hour.toString().padStart(2, '0')}:00</option>
{/if}
{/each}
</select>
</div>
</div>
</div>
{/if}
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">Ganztägige Termine</span>
<span class="setting-description">Wie sollen ganztägige Termine angezeigt werden?</span>
</div>
<div class="button-group">
<button
class="group-button"
class:active={settingsStore.allDayDisplayMode === 'header'}
onclick={() => settingsStore.set('allDayDisplayMode', 'header' as AllDayDisplayMode)}
>
In Kopfzeile
</button>
<button
class="group-button"
class:active={settingsStore.allDayDisplayMode === 'block'}
onclick={() => settingsStore.set('allDayDisplayMode', 'block' as AllDayDisplayMode)}
>
Als Tagesblock
</button>
</div>
</div>
</section>
<!-- Termin-Einstellungen -->
@ -316,6 +398,11 @@
</div>
</section>
<!-- Global App Settings -->
<section class="settings-section">
<GlobalSettingsSection {userSettings} />
</section>
<!-- Konto -->
<section class="settings-section card">
<h2>Konto</h2>
@ -577,4 +664,38 @@
.text-destructive {
color: hsl(var(--color-error));
}
/* Hour range settings */
.hour-range-setting {
padding-left: 2rem;
border-left: 2px solid hsl(var(--color-primary) / 0.3);
margin-left: 0.5rem;
}
.hour-range-inputs {
display: flex;
align-items: center;
gap: 0.75rem;
}
.hour-input-group {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.hour-input-group label {
font-size: 0.75rem;
color: hsl(var(--color-muted-foreground));
}
.hour-select {
width: 100px;
}
.hour-separator {
font-size: 1.25rem;
color: hsl(var(--color-muted-foreground));
margin-top: 1.25rem;
}
</style>

View file

@ -1,5 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { theme } from '$lib/stores/theme';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { THEME_DEFINITIONS, type ThemeVariant } from '@manacore/shared-theme';
import {
SettingsPage,
@ -9,6 +11,7 @@
SettingsToggle,
SettingsDangerZone,
SettingsDangerButton,
GlobalSettingsSection,
} from '@manacore/shared-ui';
// Available theme variants
@ -26,6 +29,10 @@
// TODO: Implement chat history deletion
alert('Diese Funktion wird bald verfügbar sein.');
}
onMount(async () => {
await userSettings.load();
});
</script>
<svelte:head>
@ -208,6 +215,9 @@
</SettingsDangerZone>
</SettingsSection>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<!-- About Section -->
<SettingsSection title="Über die App">
{#snippet icon()}

View file

@ -124,24 +124,9 @@
}
}
/* Legacy color variable compatibility */
/* Shadow variables */
@layer base {
:root {
--color-primary: var(--primary);
--color-background: var(--background);
--color-surface: var(--card);
--color-surface-elevated: var(--card);
--color-text-primary: var(--foreground);
--color-text-secondary: var(--muted-foreground);
--color-text-tertiary: var(--muted-foreground);
--color-border: var(--border);
--color-border-hover: var(--border);
--color-success: 142 76% 36%;
--color-warning: 38 92% 50%;
--color-error: 0 84% 60%;
--color-info: 217 91% 60%;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);

View file

@ -1,14 +1,15 @@
<script lang="ts">
import { SubscriptionPage } from '@manacore/shared-subscription-ui';
import { toasts } from '$lib/stores/toast';
function handleSubscribe(planId: string) {
console.log('Subscribe to plan:', planId);
alert(`Abo "${planId}" ausgewählt. Bezahlsystem wird noch integriert.`);
toasts.info(`Abo "${planId}" ausgewählt. Bezahlsystem wird noch integriert.`);
}
function handleBuyPackage(packageId: string) {
console.log('Buy package:', packageId);
alert(`Paket "${packageId}" ausgewählt. Bezahlsystem wird noch integriert.`);
toasts.info(`Paket "${packageId}" ausgewählt. Bezahlsystem wird noch integriert.`);
}
</script>
@ -34,6 +35,6 @@
min-height: 100%;
width: 100%;
overflow-x: hidden;
background-color: hsl(var(--color-background));
background-color: hsl(var(--background));
}
</style>

View file

@ -0,0 +1,100 @@
<script lang="ts">
import { onMount } from 'svelte';
import { theme } from '$lib/stores/theme';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import {
SettingsPage,
SettingsSection,
SettingsCard,
SettingsRow,
GlobalSettingsSection,
} from '@manacore/shared-ui';
onMount(async () => {
await userSettings.load();
});
</script>
<svelte:head>
<title>Einstellungen - Kontakte</title>
</svelte:head>
<SettingsPage title="Einstellungen" subtitle="Passe die App an deine Vorlieben an.">
<!-- Appearance Section -->
<SettingsSection title="Darstellung">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"
/>
</svg>
{/snippet}
<SettingsCard>
<div class="px-5 py-4">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Farbmodus</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">
Wähle zwischen Hell, Dunkel oder System
</p>
<div class="flex gap-2">
{#each ['light', 'dark', 'system'] as mode}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.mode ===
mode
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setMode(mode as 'light' | 'dark' | 'system')}
>
{mode === 'light' ? 'Hell' : mode === 'dark' ? 'Dunkel' : 'System'}
</button>
{/each}
</div>
</div>
<div class="px-5 py-4 border-t border-[hsl(var(--border))]">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Theme</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">Wähle eine Farbpalette</p>
<div class="flex gap-2 flex-wrap">
{#each theme.variants as variant}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.variant ===
variant
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setVariant(variant)}
>
{THEME_DEFINITIONS[variant].label}
</button>
{/each}
</div>
</div>
</SettingsCard>
</SettingsSection>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<!-- About Section -->
<SettingsSection title="Über">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{/snippet}
<SettingsCard>
<SettingsRow label="Version" border={false}>
<span class="text-[hsl(var(--muted-foreground))]">1.0.0</span>
</SettingsRow>
</SettingsCard>
</SettingsSection>
</SettingsPage>

View file

@ -0,0 +1,100 @@
<script lang="ts">
import { onMount } from 'svelte';
import { theme } from '$lib/stores/theme';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import {
SettingsPage,
SettingsSection,
SettingsCard,
SettingsRow,
GlobalSettingsSection,
} from '@manacore/shared-ui';
onMount(async () => {
await userSettings.load();
});
</script>
<svelte:head>
<title>Einstellungen - ManaDeck</title>
</svelte:head>
<SettingsPage title="Einstellungen" subtitle="Passe die App an deine Vorlieben an.">
<!-- Appearance Section -->
<SettingsSection title="Darstellung">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"
/>
</svg>
{/snippet}
<SettingsCard>
<div class="px-5 py-4">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Farbmodus</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">
Wähle zwischen Hell, Dunkel oder System
</p>
<div class="flex gap-2">
{#each ['light', 'dark', 'system'] as mode}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.mode ===
mode
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setMode(mode as 'light' | 'dark' | 'system')}
>
{mode === 'light' ? 'Hell' : mode === 'dark' ? 'Dunkel' : 'System'}
</button>
{/each}
</div>
</div>
<div class="px-5 py-4 border-t border-[hsl(var(--border))]">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Theme</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">Wähle eine Farbpalette</p>
<div class="flex gap-2 flex-wrap">
{#each theme.variants as variant}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.variant ===
variant
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setVariant(variant)}
>
{THEME_DEFINITIONS[variant].label}
</button>
{/each}
</div>
</div>
</SettingsCard>
</SettingsSection>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<!-- About Section -->
<SettingsSection title="Über">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{/snippet}
<SettingsCard>
<SettingsRow label="Version" border={false}>
<span class="text-[hsl(var(--muted-foreground))]">1.0.0</span>
</SettingsRow>
</SettingsCard>
</SettingsSection>
</SettingsPage>

View file

@ -0,0 +1,100 @@
<script lang="ts">
import { onMount } from 'svelte';
import { theme } from '$lib/stores/theme';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import {
SettingsPage,
SettingsSection,
SettingsCard,
SettingsRow,
GlobalSettingsSection,
} from '@manacore/shared-ui';
onMount(async () => {
await userSettings.load();
});
</script>
<svelte:head>
<title>Einstellungen - Picture</title>
</svelte:head>
<SettingsPage title="Einstellungen" subtitle="Passe die App an deine Vorlieben an.">
<!-- Appearance Section -->
<SettingsSection title="Darstellung">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"
/>
</svg>
{/snippet}
<SettingsCard>
<div class="px-5 py-4">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Farbmodus</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">
Wähle zwischen Hell, Dunkel oder System
</p>
<div class="flex gap-2">
{#each ['light', 'dark', 'system'] as mode}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.mode ===
mode
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setMode(mode as 'light' | 'dark' | 'system')}
>
{mode === 'light' ? 'Hell' : mode === 'dark' ? 'Dunkel' : 'System'}
</button>
{/each}
</div>
</div>
<div class="px-5 py-4 border-t border-[hsl(var(--border))]">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Theme</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">Wähle eine Farbpalette</p>
<div class="flex gap-2 flex-wrap">
{#each theme.variants as variant}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.variant ===
variant
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setVariant(variant)}
>
{THEME_DEFINITIONS[variant].label}
</button>
{/each}
</div>
</div>
</SettingsCard>
</SettingsSection>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<!-- About Section -->
<SettingsSection title="Über">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{/snippet}
<SettingsCard>
<SettingsRow label="Version" border={false}>
<span class="text-[hsl(var(--muted-foreground))]">1.0.0</span>
</SettingsRow>
</SettingsCard>
</SettingsSection>
</SettingsPage>

View file

@ -1,7 +1,9 @@
<script lang="ts">
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import { auth } from '$lib/stores/auth.svelte';
import { theme } from '$lib/stores/theme';
import { userSettings } from '$lib/stores/user-settings.svelte';
import {
SettingsPage,
SettingsSection,
@ -10,6 +12,7 @@
SettingsToggle,
SettingsDangerZone,
SettingsDangerButton,
GlobalSettingsSection,
} from '@manacore/shared-ui';
function handleLogout() {
@ -20,6 +23,10 @@
function setThemeMode(mode: 'light' | 'dark' | 'system') {
theme.setMode(mode);
}
onMount(async () => {
await userSettings.load();
});
</script>
<svelte:head>
@ -160,6 +167,9 @@
</SettingsCard>
</SettingsSection>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<!-- Danger Zone -->
<SettingsDangerZone title="Danger Zone">
<SettingsDangerButton

View file

@ -1,181 +1,125 @@
<script lang="ts">
import { Settings } from 'lucide-svelte';
import { onMount } from 'svelte';
import { theme } from '$lib/stores/theme.svelte';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import {
SettingsPage,
SettingsSection,
SettingsCard,
SettingsRow,
GlobalSettingsSection,
} from '@manacore/shared-ui';
onMount(async () => {
await userSettings.load();
});
</script>
<svelte:head>
<title>Einstellungen - Storage</title>
</svelte:head>
<div class="settings-page">
<div class="page-header">
<h1>
<Settings size={24} />
Einstellungen
</h1>
</div>
<SettingsPage title="Einstellungen" subtitle="Passe die App an deine Vorlieben an.">
<!-- Appearance Section -->
<SettingsSection title="Darstellung">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"
/>
</svg>
{/snippet}
<div class="settings-section">
<h2>Darstellung</h2>
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">Farbmodus</span>
<span class="setting-description">Wähle zwischen Hell, Dunkel oder System</span>
</div>
<div class="setting-control">
<select value={theme.mode} onchange={(e) => theme.setMode((e.target as HTMLSelectElement).value as any)}>
<option value="light">Hell</option>
<option value="dark">Dunkel</option>
<option value="system">System</option>
</select>
</div>
</div>
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">Theme</span>
<span class="setting-description">Wähle eine Farbpalette</span>
</div>
<div class="setting-control">
<select value={theme.variant} onchange={(e) => theme.setVariant((e.target as HTMLSelectElement).value as any)}>
{#each theme.variants as variant}
<option value={variant}>{THEME_DEFINITIONS[variant].label}</option>
<SettingsCard>
<div class="px-5 py-4">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Farbmodus</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">
Wähle zwischen Hell, Dunkel oder System
</p>
<div class="flex gap-2">
{#each ['light', 'dark', 'system'] as mode}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.mode ===
mode
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setMode(mode as 'light' | 'dark' | 'system')}
>
{mode === 'light' ? 'Hell' : mode === 'dark' ? 'Dunkel' : 'System'}
</button>
{/each}
</select>
</div>
</div>
</div>
</div>
<div class="settings-section">
<h2>Speicher</h2>
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">Speicherplatz</span>
<span class="setting-description">Dein genutzter Speicherplatz</span>
<div class="px-5 py-4 border-t border-[hsl(var(--border))]">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Theme</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">Wähle eine Farbpalette</p>
<div class="flex gap-2 flex-wrap">
{#each theme.variants as variant}
<button
class="px-4 py-2 text-sm font-medium rounded-lg transition-colors {theme.variant ===
variant
? 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]'
: 'bg-[hsl(var(--muted))] hover:bg-[hsl(var(--muted))]/80 text-[hsl(var(--foreground))]'}"
onclick={() => theme.setVariant(variant)}
>
{THEME_DEFINITIONS[variant].label}
</button>
{/each}
</div>
</div>
<div class="storage-bar">
<div class="storage-used" style="width: 25%"></div>
</SettingsCard>
</SettingsSection>
<!-- Storage Section -->
<SettingsSection title="Speicher">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"
/>
</svg>
{/snippet}
<SettingsCard>
<div class="px-5 py-4">
<p class="font-medium text-[hsl(var(--foreground))] mb-2">Speicherplatz</p>
<p class="text-sm text-[hsl(var(--muted-foreground))] mb-4">Dein genutzter Speicherplatz</p>
<div class="w-full h-2 bg-[hsl(var(--muted))] rounded-full overflow-hidden mb-2">
<div class="h-full bg-[hsl(var(--primary))] rounded-full" style="width: 25%"></div>
</div>
<p class="text-sm text-[hsl(var(--muted-foreground))]">2.5 GB von 10 GB verwendet</p>
</div>
<span class="storage-text">2.5 GB von 10 GB verwendet</span>
</div>
</div>
</SettingsCard>
</SettingsSection>
<div class="settings-section">
<h2>Über</h2>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">Version</span>
<span class="setting-description">Storage App v1.0.0</span>
</div>
</div>
</div>
</div>
<!-- About Section -->
<SettingsSection title="Über">
{#snippet icon()}
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{/snippet}
<style>
.settings-page {
min-height: 100%;
max-width: 600px;
}
.page-header {
margin-bottom: 2rem;
}
.page-header h1 {
display: flex;
align-items: center;
gap: 0.75rem;
margin: 0;
font-size: 1.5rem;
font-weight: 600;
color: rgb(var(--color-text-primary));
}
.settings-section {
margin-bottom: 2rem;
padding: 1.5rem;
background: rgb(var(--color-surface-elevated));
border: 1px solid rgb(var(--color-border));
border-radius: var(--radius-xl);
}
.settings-section h2 {
margin: 0 0 1.5rem 0;
font-size: 1rem;
font-weight: 600;
color: rgb(var(--color-text-primary));
}
.setting-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 1rem 0;
border-bottom: 1px solid rgb(var(--color-border));
}
.setting-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.setting-item:first-of-type {
padding-top: 0;
}
.setting-info {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.setting-label {
font-size: 0.875rem;
font-weight: 500;
color: rgb(var(--color-text-primary));
}
.setting-description {
font-size: 0.75rem;
color: rgb(var(--color-text-secondary));
}
.setting-control select {
padding: 0.5rem 0.75rem;
background: rgb(var(--color-surface));
border: 1px solid rgb(var(--color-border));
border-radius: var(--radius-md);
font-size: 0.875rem;
color: rgb(var(--color-text-primary));
cursor: pointer;
}
.setting-control select:focus {
outline: none;
border-color: rgb(var(--color-primary));
}
.storage-bar {
width: 100%;
height: 8px;
background: rgb(var(--color-surface));
border-radius: 4px;
overflow: hidden;
margin-top: 0.5rem;
}
.storage-used {
height: 100%;
background: rgb(var(--color-primary));
border-radius: 4px;
}
.storage-text {
font-size: 0.75rem;
color: rgb(var(--color-text-secondary));
}
</style>
<SettingsCard>
<SettingsRow label="Version" border={false}>
<span class="text-[hsl(var(--muted-foreground))]">1.0.0</span>
</SettingsRow>
</SettingsCard>
</SettingsSection>
</SettingsPage>

View file

@ -2,6 +2,7 @@
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import { theme } from '$lib/stores/theme';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
import { ThemeColorPreview } from '@manacore/shared-theme-ui';
import {
@ -12,6 +13,7 @@
SettingsToggle,
SettingsDangerZone,
SettingsDangerButton,
GlobalSettingsSection,
} from '@manacore/shared-ui';
// Settings state
@ -19,12 +21,15 @@
let userName = $state('');
// Load settings from localStorage on mount
onMount(() => {
onMount(async () => {
const savedLanguage = localStorage.getItem('language');
const savedUserName = localStorage.getItem('userName');
if (savedLanguage) language = savedLanguage as 'de' | 'en';
if (savedUserName) userName = savedUserName;
// Load user settings from server
await userSettings.load();
});
// Save settings to localStorage
@ -227,6 +232,9 @@
</SettingsCard>
</SettingsSection>
<!-- Global Settings Section -->
<GlobalSettingsSection {userSettings} />
<!-- Data Section -->
<SettingsDangerZone title="Daten">
<SettingsDangerButton