Files
tessera-ctl/apps/web/src/lib/stores/auth-store.ts
T
schalli 0aaa15240d feat(260928-ujj): Dashboard-Hintergrund pro Benutzer in der Datenbank
- Spalte User.dashboardBackground (JSONB) samt Migration
- PATCH /users/me/dashboard-background, geprueft mit parseDashboardBackground aus @tessera/shared (Allowlist, UUID-Bildkennung)
- getMe liefert dashboardBackground normalisiert neben accentColor
- Web liest die Wahl aus dem Auth-Store, speichert ueber die Server-Aktion, alte localStorage-Wahl wird einmalig uebernommen
- Hinweistext: gilt auf jedem Geraet

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:13:49 +02:00

61 lines
2.1 KiB
TypeScript

import type { DashboardBackground } from '@tessera/shared';
import { create } from 'zustand';
import { readableOnAccent } from '@/lib/color';
export interface AuthUser {
id: string;
username: string;
displayName: string | null;
role: 'SUPER_ADMIN' | 'ADMIN' | 'USER';
tenantId: string;
hasAvatar?: boolean;
accentColor?: string | null;
/** quick-260928-ujj: Dashboard-Hintergrund aus der Sitzungsantwort; null = nie gewaehlt. */
dashboardBackground?: DashboardBackground | null;
}
interface AuthState {
user: AuthUser | null;
avatarVersion: number;
setUser: (user: AuthUser) => void;
clearUser: () => void;
bumpAvatarVersion: () => void;
}
function applyAccentColor(color: string | null | undefined) {
if (typeof document === 'undefined') return;
const root = document.documentElement;
// Design „Mosaik“: die persoenliche Akzentfarbe setzt nur noch `--primary`
// (Hauptknoepfe, Auswahlpille der Seitenleiste, Reiter-Unterstrich, Logo).
// Fokusring und Auswahlflaeche der Seitenleiste bleiben neutral — eine
// helle Akzentfarbe (Standard Gelb) waere als Fokusring auf Weiss kaum
// sichtbar (1,3:1). Alte Werte frueherer Fassungen werden entfernt.
root.style.removeProperty('--ring');
root.style.removeProperty('--sidebar-accent');
root.style.removeProperty('--sidebar-accent-foreground');
if (color) {
root.style.setProperty('--primary', color);
// Schrift auf der Akzentflaeche: hell oder dunkel, je nach Kontrast.
root.style.setProperty('--primary-foreground', readableOnAccent(color));
} else {
root.style.removeProperty('--primary');
root.style.removeProperty('--primary-foreground');
}
}
/**
* Zustand store for client-side auth state.
* No persist middleware -- user state comes from API, not localStorage.
* Populated on portal load via fetchCurrentUser().
*/
export const useAuthStore = create<AuthState>()((set) => ({
user: null,
avatarVersion: 0,
setUser: (user) => {
applyAccentColor(user.accentColor);
set({ user });
},
clearUser: () => set({ user: null }),
bumpAvatarVersion: () => set((s) => ({ avatarVersion: s.avatarVersion + 1 })),
}));