admin-ui: align with API, add auth, fix integrations
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
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import { signal, computed } from '@preact/signals';
|
||||
import { endpoints } from '../api/client';
|
||||
import type { AuthLoginRequest, AuthLoginResponse, UserProfile } from '../api/types';
|
||||
|
||||
// Types
|
||||
export interface UserPreferences {
|
||||
@@ -10,14 +12,6 @@ export interface UserPreferences {
|
||||
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',
|
||||
@@ -29,16 +23,16 @@ const DEFAULT_PREFERENCES: UserPreferences = {
|
||||
};
|
||||
|
||||
// User State Signals
|
||||
export const user = signal<User | null>(null);
|
||||
export const user = signal<UserProfile | 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 userId = computed(() => user.value?.id ?? 1);
|
||||
export const userName = computed(() => user.value?.display_name ?? user.value?.email ?? 'Guest');
|
||||
export const userInitials = computed(() => {
|
||||
const name = user.value?.name ?? 'Guest';
|
||||
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
||||
const name = user.value?.display_name ?? user.value?.email ?? 'Guest';
|
||||
return name.split(' ').filter(Boolean).map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
||||
});
|
||||
|
||||
// Actions
|
||||
@@ -66,7 +60,7 @@ export function updatePreferences(updates: Partial<UserPreferences>): void {
|
||||
saveUserPreferences();
|
||||
}
|
||||
|
||||
export function setUser(userData: User | null): void {
|
||||
export function setUser(userData: UserProfile | null): void {
|
||||
user.value = userData;
|
||||
}
|
||||
|
||||
@@ -75,6 +69,40 @@ export function logout(): void {
|
||||
localStorage.removeItem('dss-token');
|
||||
}
|
||||
|
||||
export async function refreshUser(): Promise<void> {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const token = localStorage.getItem('dss-token');
|
||||
if (!token) {
|
||||
user.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const profile = await endpoints.auth.me();
|
||||
user.value = profile;
|
||||
} catch {
|
||||
// Token is invalid/expired; clear it.
|
||||
localStorage.removeItem('dss-token');
|
||||
user.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function loginWithAtlassian(credentials: AuthLoginRequest): Promise<AuthLoginResponse> {
|
||||
const response = await endpoints.auth.login(credentials);
|
||||
localStorage.setItem('dss-token', response.token);
|
||||
// Prefer server truth; also supports older login response shapes.
|
||||
user.value = {
|
||||
id: response.user.id,
|
||||
email: response.user.email,
|
||||
display_name: response.user.display_name,
|
||||
atlassian_url: response.user.atlassian_url,
|
||||
atlassian_service: response.user.service,
|
||||
last_login: new Date().toISOString(),
|
||||
};
|
||||
return response;
|
||||
}
|
||||
|
||||
// Keyboard shortcuts state
|
||||
export const keyboardShortcutsEnabled = computed(() =>
|
||||
preferences.value.keyboardShortcutsEnabled
|
||||
|
||||
Reference in New Issue
Block a user