feat: Rebuild admin-ui with Preact + Signals
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
Complete rebuild of the admin-ui using Preact + Signals for a lightweight, reactive framework. Features include: - Team-centric workdesks (UI, UX, QA, Admin) - Comprehensive API client with 150+ DSS backend endpoints - Dark mode with system preference detection - Keyboard shortcuts and command palette - AI chat sidebar with Claude integration - Toast notifications system - Export/import functionality for project backup - TypeScript throughout with full type coverage Bundle size: ~66KB main (21KB gzipped), ~5KB framework overhead 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
81
admin-ui/src/state/user.ts
Normal file
81
admin-ui/src/state/user.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { signal, computed } from '@preact/signals';
|
||||
|
||||
// Types
|
||||
export interface UserPreferences {
|
||||
theme: 'light' | 'dark' | 'auto';
|
||||
sidebarCollapsed: boolean;
|
||||
panelHeight: number;
|
||||
defaultTeam: string;
|
||||
keyboardShortcutsEnabled: boolean;
|
||||
notificationsEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
avatar?: string;
|
||||
role: 'admin' | 'developer' | 'viewer';
|
||||
}
|
||||
|
||||
// Default preferences
|
||||
const DEFAULT_PREFERENCES: UserPreferences = {
|
||||
theme: 'auto',
|
||||
sidebarCollapsed: false,
|
||||
panelHeight: 280,
|
||||
defaultTeam: 'ui',
|
||||
keyboardShortcutsEnabled: true,
|
||||
notificationsEnabled: true
|
||||
};
|
||||
|
||||
// User State Signals
|
||||
export const user = signal<User | null>(null);
|
||||
export const preferences = signal<UserPreferences>(DEFAULT_PREFERENCES);
|
||||
|
||||
// Computed Values
|
||||
export const isAuthenticated = computed(() => user.value !== null);
|
||||
export const isAdmin = computed(() => user.value?.role === 'admin');
|
||||
export const userName = computed(() => user.value?.name ?? 'Guest');
|
||||
export const userInitials = computed(() => {
|
||||
const name = user.value?.name ?? 'Guest';
|
||||
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
||||
});
|
||||
|
||||
// Actions
|
||||
export function loadUserPreferences(): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const saved = localStorage.getItem('dss-preferences');
|
||||
if (saved) {
|
||||
try {
|
||||
const parsed = JSON.parse(saved);
|
||||
preferences.value = { ...DEFAULT_PREFERENCES, ...parsed };
|
||||
} catch {
|
||||
preferences.value = DEFAULT_PREFERENCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function saveUserPreferences(): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
localStorage.setItem('dss-preferences', JSON.stringify(preferences.value));
|
||||
}
|
||||
|
||||
export function updatePreferences(updates: Partial<UserPreferences>): void {
|
||||
preferences.value = { ...preferences.value, ...updates };
|
||||
saveUserPreferences();
|
||||
}
|
||||
|
||||
export function setUser(userData: User | null): void {
|
||||
user.value = userData;
|
||||
}
|
||||
|
||||
export function logout(): void {
|
||||
user.value = null;
|
||||
localStorage.removeItem('dss-token');
|
||||
}
|
||||
|
||||
// Keyboard shortcuts state
|
||||
export const keyboardShortcutsEnabled = computed(() =>
|
||||
preferences.value.keyboardShortcutsEnabled
|
||||
);
|
||||
Reference in New Issue
Block a user