mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
🐛 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:
parent
b01153ba87
commit
482509a574
13 changed files with 836 additions and 185 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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()}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
100
apps/contacts/apps/web/src/routes/(app)/settings/+page.svelte
Normal file
100
apps/contacts/apps/web/src/routes/(app)/settings/+page.svelte
Normal 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>
|
||||
100
apps/manadeck/apps/web/src/routes/(app)/settings/+page.svelte
Normal file
100
apps/manadeck/apps/web/src/routes/(app)/settings/+page.svelte
Normal 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>
|
||||
100
apps/picture/apps/web/src/routes/app/settings/+page.svelte
Normal file
100
apps/picture/apps/web/src/routes/app/settings/+page.svelte
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue