Add LAN deploy scripts and improve admin billing/users UX.
Provide rsync deploy and restart tooling for the 100 server, document the workflow, and add pagination plus user filtering across billing and user management pages. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+59
-11
@@ -156,6 +156,16 @@ export async function logout(): Promise<void> {
|
||||
await fetch('/auth/logout', { method: 'POST' });
|
||||
}
|
||||
|
||||
// ── Pagination helpers ────────────────────────────────
|
||||
|
||||
export type PagedResult<T> = {
|
||||
items: T[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
};
|
||||
|
||||
// ── Admin dashboard ───────────────────────────────────
|
||||
|
||||
export async function getAdminDashboardSummary(): Promise<AdminDashboardSummary> {
|
||||
@@ -163,23 +173,61 @@ export async function getAdminDashboardSummary(): Promise<AdminDashboardSummary>
|
||||
return result.summary;
|
||||
}
|
||||
|
||||
export async function listAdminUsage(userId?: string): Promise<UsageRecord[]> {
|
||||
const query = userId ? `?userId=${encodeURIComponent(userId)}` : '';
|
||||
const result = await portalFetch<{ records: UsageRecord[] }>(`/admin-api/usage${query}`);
|
||||
return result.records ?? [];
|
||||
export async function listAdminUsage(params?: {
|
||||
userId?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}): Promise<PagedResult<UsageRecord>> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.userId) q.set('userId', params.userId);
|
||||
if (params?.page) q.set('page', String(params.page));
|
||||
if (params?.pageSize) q.set('pageSize', String(params.pageSize));
|
||||
const result = await portalFetch<{ records: UsageRecord[]; total: number; page: number; pageSize: number }>(
|
||||
`/admin-api/usage${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
const total = result.total ?? 0;
|
||||
const pageSize = result.pageSize ?? 50;
|
||||
return { items: result.records ?? [], total, page: result.page ?? 1, pageSize, totalPages: Math.ceil(total / pageSize) };
|
||||
}
|
||||
|
||||
export async function listAdminLedger(userId?: string): Promise<LedgerEntry[]> {
|
||||
const query = userId ? `?userId=${encodeURIComponent(userId)}` : '';
|
||||
const result = await portalFetch<{ entries: LedgerEntry[] }>(`/admin-api/ledger${query}`);
|
||||
return result.entries ?? [];
|
||||
export async function listAdminLedger(params?: {
|
||||
userId?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}): Promise<PagedResult<LedgerEntry>> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.userId) q.set('userId', params.userId);
|
||||
if (params?.page) q.set('page', String(params.page));
|
||||
if (params?.pageSize) q.set('pageSize', String(params.pageSize));
|
||||
const result = await portalFetch<{ entries: LedgerEntry[]; total: number; page: number; pageSize: number }>(
|
||||
`/admin-api/ledger${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
const total = result.total ?? 0;
|
||||
const pageSize = result.pageSize ?? 50;
|
||||
return { items: result.entries ?? [], total, page: result.page ?? 1, pageSize, totalPages: Math.ceil(total / pageSize) };
|
||||
}
|
||||
|
||||
// ── Admin users ───────────────────────────────────────
|
||||
|
||||
export async function listAdminUsers(): Promise<AdminUserRow[]> {
|
||||
const result = await portalFetch<{ users: AdminUserRow[] }>('/admin-api/users');
|
||||
return result.users ?? [];
|
||||
export async function listAdminUsers(params?: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
search?: string;
|
||||
role?: string;
|
||||
status?: string;
|
||||
}): Promise<PagedResult<AdminUserRow>> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.page) q.set('page', String(params.page));
|
||||
if (params?.pageSize) q.set('pageSize', String(params.pageSize));
|
||||
if (params?.search) q.set('search', params.search);
|
||||
if (params?.role) q.set('role', params.role);
|
||||
if (params?.status) q.set('status', params.status);
|
||||
const result = await portalFetch<{ users: AdminUserRow[]; total: number; page: number; pageSize: number }>(
|
||||
`/admin-api/users${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
const total = result.total ?? 0;
|
||||
const pageSize = result.pageSize ?? 20;
|
||||
return { items: result.users ?? [], total, page: result.page ?? 1, pageSize, totalPages: Math.ceil(total / pageSize) };
|
||||
}
|
||||
|
||||
export async function createAdminUser(payload: {
|
||||
|
||||
Reference in New Issue
Block a user