Add admin portal
This commit is contained in:
@@ -17,6 +17,7 @@ export class ApiClientError extends Error {
|
||||
|
||||
export type ErrorHandlers = {
|
||||
onForbidden?: (error: ApiClientError) => void | Promise<void>;
|
||||
onUnauthorized?: (error: ApiClientError) => void | Promise<void>;
|
||||
onError?: (error: ApiClientError) => void | Promise<void>;
|
||||
};
|
||||
|
||||
@@ -28,6 +29,7 @@ export const apiBaseUrl =
|
||||
|
||||
export function configureApiClient(nextHandlers: ErrorHandlers) {
|
||||
handlers.onForbidden = nextHandlers.onForbidden;
|
||||
handlers.onUnauthorized = nextHandlers.onUnauthorized;
|
||||
handlers.onError = nextHandlers.onError;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,10 @@ http.interceptors.response.use(
|
||||
async (error: AxiosError) => {
|
||||
const normalized = normalizeError(error);
|
||||
|
||||
if (normalized.status === 401 && handlers.onUnauthorized) {
|
||||
await handlers.onUnauthorized(normalized);
|
||||
}
|
||||
|
||||
if (normalized.status === 403 && handlers.onForbidden) {
|
||||
await handlers.onForbidden(normalized);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ export * as courts from './resources/courts';
|
||||
export * as user from './resources/user';
|
||||
export * as sports from './resources/sports';
|
||||
export * as plans from './resources/plans';
|
||||
export * as admin from './resources/admin';
|
||||
|
||||
export {
|
||||
cancelPublic,
|
||||
|
||||
88
apps/frontend/src/lib/api/resources/admin.ts
Normal file
88
apps/frontend/src/lib/api/resources/admin.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import type {
|
||||
AdminBlockUserInput,
|
||||
AdminComplexListItem,
|
||||
AdminCreatePlanInput,
|
||||
AdminGlobalStats,
|
||||
AdminUpdatePlanInput,
|
||||
AdminUser,
|
||||
AdminUserSession,
|
||||
} from '@repo/api-contract';
|
||||
import { http } from '../http';
|
||||
|
||||
type AdminPlan = {
|
||||
code: string;
|
||||
name: string;
|
||||
price: number;
|
||||
rules: unknown;
|
||||
lastUpdatedAt: string;
|
||||
complexCount: number;
|
||||
};
|
||||
|
||||
export async function listComplexes() {
|
||||
const response = await http.get<AdminComplexListItem[]>('/api/admin/complexes');
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function listPlans() {
|
||||
const response = await http.get<AdminPlan[]>('/api/admin/plans');
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function createPlan(data: AdminCreatePlanInput) {
|
||||
const response = await http.post<{ code: string; name: string; price: number }>(
|
||||
'/api/admin/plans',
|
||||
JSON.stringify(data),
|
||||
{ headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function updatePlan(code: string, data: AdminUpdatePlanInput) {
|
||||
const response = await http.patch<{ code: string; name: string; price: number }>(
|
||||
`/api/admin/plans/${code}`,
|
||||
JSON.stringify(data),
|
||||
{ headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function deletePlan(code: string) {
|
||||
const response = await http.delete<{ message: string }>(`/api/admin/plans/${code}`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function listUsers() {
|
||||
const response = await http.get<AdminUser[]>('/api/admin/users');
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function blockUser(userId: string, data?: AdminBlockUserInput) {
|
||||
const response = await http.post<{ message: string }>(
|
||||
`/api/admin/users/${userId}/block`,
|
||||
JSON.stringify(data ?? {}),
|
||||
{ headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function unblockUser(userId: string) {
|
||||
const response = await http.post<{ message: string }>(`/api/admin/users/${userId}/unblock`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getGlobalStats() {
|
||||
const response = await http.get<AdminGlobalStats>('/api/admin/stats');
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getUserSessions(userId: string) {
|
||||
const response = await http.get<AdminUserSession[]>(`/api/admin/users/${userId}/sessions`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function revokeAllSessions(userId: string) {
|
||||
const response = await http.post<{ message: string }>(
|
||||
`/api/admin/users/${userId}/sessions/revoke-all`
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
Reference in New Issue
Block a user