Move personal display preferences into My account

This commit is contained in:
2026-10-05 18:57:54 -04:00
parent a5f9956615
commit b926d46616
2 changed files with 24 additions and 20 deletions
+21 -1
View File
@@ -1,4 +1,10 @@
<script lang="ts">
import { onMount } from 'svelte';
import { timeFormat, timeZone, timeZonePersistenceError } from '$ui/stores/time-zone.js';
import { availableTimeZones, DEFAULT_TIME_ZONE } from '$lib/time-zone.js';
let exampleDate = $state<Date | null>(null);
const zones = $derived([...new Set([...availableTimeZones(), $timeZone])].sort());
onMount(() => { exampleDate = new Date(); });
import { page } from '$app/stores';
import { invalidateAll } from '$app/navigation';
import Button from '$ui/components/primitives/Button.svelte';
@@ -30,7 +36,7 @@
</script>
<svelte:head><title>My account · Electric Cherry</title></svelte:head>
<section class="page"><SectionHeader title="My account" subtitle="Manage your password and current session." />
<section class="page"><SectionHeader title="My account" subtitle="Manage your password, display preferences, and current session." />
{#if user}
<section class="panel identity"><div><h2>{user.displayName}</h2><p>@{user.username} · <span class="role">{user.role}</span></p></div><Button disabled={busy || signingOut} loading={signingOut} onclick={logout}>Sign out</Button></section>
{#if user.mustChangePassword}<p class="required" role="status">Your account uses a temporary password. Choose a new password before continuing to Electric Cherry.</p>{/if}
@@ -45,10 +51,24 @@
<div><Button type="submit" variant="primary" loading={busy} disabled={busy || signingOut}>{user.mustChangePassword ? 'Save password and continue' : 'Change password'}</Button></div>
</fieldset></form>
</section>
<section class="panel" aria-labelledby="display-heading">
<h2 id="display-heading">Display preferences</h2>
<label class="timezone">Timezone
<select bind:value={$timeZone} aria-describedby="timezone-help">
{#each zones as zone}<option value={zone}>{zone.replaceAll('_', ' ')}{zone === DEFAULT_TIME_ZONE ? ' (default)' : ''}</option>{/each}
</select>
</label>
<p id="timezone-help">Dates and times throughout the app use this timezone, including daylight saving changes. Saved automatically in this browser.</p>
{#if exampleDate}<p>Example: {$timeFormat.dateTime(exampleDate)}</p>{/if}
{#if $timeZonePersistenceError}<p role="status">Browser storage is unavailable. Your timezone applies for this visit but cannot be saved.</p>{/if}
</section>
{/if}
</section>
<style>
.timezone { display: grid; gap: 8px; margin-top: 16px; font-size: var(--text-sm); max-width: 420px; }
.timezone select { width: 100%; padding: 10px 12px; font: inherit; color: var(--text-primary); background: var(--surface-sunken); border: 1px solid var(--border-control); border-radius: var(--radius-sm); }
.timezone ~ p { font-size:var(--text-sm); color:var(--text-secondary); }
.page { max-width:760px; display:grid; gap:24px; } .panel { padding:24px; background:var(--surface); border:1px solid var(--border-strong); border-radius:var(--radius-md); } h2 { font-size:var(--text-md); margin:0; } .identity { display:flex; align-items:center; justify-content:space-between; gap:20px; } .identity p { margin:8px 0 0; color:var(--text-secondary); font-size:var(--text-sm); } .role { text-transform:capitalize; }
.required { padding:16px; margin:0; color:var(--text-primary); background:var(--surface-raised); border-left:3px solid var(--accent-primary); font-size:var(--text-sm); line-height:1.6; }
form { margin-top:24px; max-width:460px; } fieldset { border:0; margin:0; padding:0; display:grid; gap:18px; min-width:0; } label { display:grid; gap:8px; font-size:var(--text-sm); } input { width:100%; padding:12px; color:var(--text-primary); background:var(--surface-sunken); border:1px solid var(--border-control); border-radius:var(--radius-md); font:inherit; } .password-username { position:absolute; width:1px; height:1px; clip-path:inset(50%); overflow:hidden; padding:0; border:0; } .hint { margin:-8px 0 0; color:var(--text-secondary); font-size:var(--text-xs); line-height:1.6; } .error { color:var(--state-danger); font-size:var(--text-sm); } .notice { color:var(--state-online); font-size:var(--text-sm); }