Files
source-gamepanel/apps/web/src/stores/auth.ts
T
hibna c9fe2bd9fe fix: resolve frontend routing, API mismatches, and missing UI components
- Add servers list page and missing routes (servers, settings redirect, account security)
- Fix members page .map error (API returns { data } wrapper, not flat array)
- Fix auth store fetchUser expecting flat User but API returns { user } wrapper
- Add node token display dialog after creation
- Add allocation management UI to node detail page
- Add account security page with password change
- Add change-password API endpoint
- Add node servers and stats API endpoints
- Fix config save using PATCH instead of PUT, add api.put method
- Fix audit logs field name mismatch (userName vs username)
- Replace admin nodes page to avoid orgId dependency
- Remove duplicate sidebar nav items

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:07:00 +03:00

70 lines
1.8 KiB
TypeScript

import { create } from 'zustand';
import { api, ApiError } from '@/lib/api';
interface User {
id: string;
email: string;
username: string;
isSuperAdmin: boolean;
avatarUrl: string | null;
}
interface AuthState {
user: User | null;
isLoading: boolean;
isAuthenticated: boolean;
login: (email: string, password: string) => Promise<void>;
register: (email: string, username: string, password: string) => Promise<void>;
logout: () => Promise<void>;
fetchUser: () => Promise<void>;
}
export const useAuthStore = create<AuthState>((set) => ({
user: null,
isLoading: true,
isAuthenticated: false,
login: async (email, password) => {
const data = await api.post<{ accessToken: string; user: User }>('/auth/login', {
email,
password,
});
localStorage.setItem('access_token', data.accessToken);
set({ user: data.user, isAuthenticated: true });
},
register: async (email, username, password) => {
const data = await api.post<{ accessToken: string; user: User }>('/auth/register', {
email,
username,
password,
});
localStorage.setItem('access_token', data.accessToken);
set({ user: data.user, isAuthenticated: true });
},
logout: async () => {
try {
await api.post('/auth/logout');
} catch {
// ignore
}
localStorage.removeItem('access_token');
set({ user: null, isAuthenticated: false });
},
fetchUser: async () => {
try {
const data = await api.get<{ user: User }>('/auth/me');
set({ user: data.user, isAuthenticated: true, isLoading: false });
} catch (err) {
if (err instanceof ApiError && err.status === 401) {
set({ user: null, isAuthenticated: false, isLoading: false });
} else {
set({ isLoading: false });
}
}
},
}));