feat(web): add login page, auth store, API client, and route guard
- API client with axios interceptors: JWT attach + 401 auto-refresh - Auth store (Zustand): login/logout/loadFromStorage with localStorage - Login page: gradient background, Ant Design form, error handling - Home page: dashboard with statistics cards - App.tsx: PrivateRoute guard, /login route, auth state restoration - MainLayout: dynamic user display, logout dropdown, menu navigation - Users API service: CRUD with pagination support
This commit is contained in:
56
apps/web/src/api/users.ts
Normal file
56
apps/web/src/api/users.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import client from './client';
|
||||
import type { UserInfo } from './auth';
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
data: T[];
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
total_pages: number;
|
||||
}
|
||||
|
||||
export interface CreateUserRequest {
|
||||
username: string;
|
||||
password: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
display_name?: string;
|
||||
}
|
||||
|
||||
export interface UpdateUserRequest {
|
||||
email?: string;
|
||||
phone?: string;
|
||||
display_name?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export async function listUsers(page = 1, pageSize = 20) {
|
||||
const { data } = await client.get<{ success: boolean; data: PaginatedResponse<UserInfo> }>(
|
||||
'/users',
|
||||
{ params: { page, page_size: pageSize } }
|
||||
);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function getUser(id: string) {
|
||||
const { data } = await client.get<{ success: boolean; data: UserInfo }>(`/users/${id}`);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function createUser(req: CreateUserRequest) {
|
||||
const { data } = await client.post<{ success: boolean; data: UserInfo }>('/users', req);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function updateUser(id: string, req: UpdateUserRequest) {
|
||||
const { data } = await client.put<{ success: boolean; data: UserInfo }>(`/users/${id}`, req);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function deleteUser(id: string) {
|
||||
await client.delete(`/users/${id}`);
|
||||
}
|
||||
|
||||
export async function assignRoles(userId: string, roleIds: string[]) {
|
||||
await client.post(`/users/${userId}/roles`, { role_ids: roleIds });
|
||||
}
|
||||
Reference in New Issue
Block a user