feat: implement full admin panel with dashboard, user management, and platform settings
Adds complete super_admin panel with 9 pages and account owner categories page. Backend includes 5 new DB tables, ~25 API endpoints, settings manager with in-memory cache, and 29 integration tests. Frontend includes reusable admin components (DataTable, Pagination, ActionMenu, etc.) with code-split lazy loading. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
108
frontend/src/api/admin.ts
Normal file
108
frontend/src/api/admin.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import api from './client'
|
||||
import type {
|
||||
DashboardMetrics,
|
||||
ActivityEntry,
|
||||
AuditLogListResponse,
|
||||
PlanLimitConfig,
|
||||
AccountOverrideResponse,
|
||||
AccountOverrideCreate,
|
||||
FeatureFlagResponse,
|
||||
FeatureFlagCreate,
|
||||
PlanDefaultUpdate,
|
||||
AccountFeatureOverrideResponse,
|
||||
AccountFeatureOverrideCreate,
|
||||
AdminCategory,
|
||||
GlobalCategoryCreate,
|
||||
} from '@/types/admin'
|
||||
|
||||
export const adminApi = {
|
||||
// Dashboard
|
||||
getDashboardMetrics: () =>
|
||||
api.get<DashboardMetrics>('/api/v1/admin/dashboard/metrics').then(r => r.data),
|
||||
getDashboardActivity: () =>
|
||||
api.get<ActivityEntry[]>('/api/v1/admin/dashboard/activity').then(r => r.data),
|
||||
|
||||
// Users (existing endpoints)
|
||||
listUsers: (params?: Record<string, unknown>) =>
|
||||
api.get('/api/v1/admin/users', { params }).then(r => r.data),
|
||||
getUser: (id: string) =>
|
||||
api.get(`/api/v1/admin/users/${id}`).then(r => r.data),
|
||||
updateUserRole: (id: string, role: string) =>
|
||||
api.put(`/api/v1/admin/users/${id}/role`, { role }).then(r => r.data),
|
||||
updateAccountRole: (id: string, account_role: string) =>
|
||||
api.put(`/api/v1/admin/users/${id}/account-role`, { account_role }).then(r => r.data),
|
||||
deactivateUser: (id: string) =>
|
||||
api.put(`/api/v1/admin/users/${id}/deactivate`).then(r => r.data),
|
||||
activateUser: (id: string) =>
|
||||
api.put(`/api/v1/admin/users/${id}/activate`).then(r => r.data),
|
||||
moveUserAccount: (id: string, display_code: string) =>
|
||||
api.put(`/api/v1/admin/users/${id}/move-account`, { display_code }).then(r => r.data),
|
||||
|
||||
// Invite Codes (existing endpoints)
|
||||
listInviteCodes: (params?: Record<string, unknown>) =>
|
||||
api.get('/api/v1/invite-codes', { params }).then(r => r.data),
|
||||
createInviteCode: (data?: { expires_at?: string }) =>
|
||||
api.post('/api/v1/invite-codes', data || {}).then(r => r.data),
|
||||
deleteInviteCode: (id: string) =>
|
||||
api.delete(`/api/v1/invite-codes/${id}`),
|
||||
|
||||
// Audit Logs
|
||||
listAuditLogs: (params?: Record<string, unknown>) =>
|
||||
api.get<AuditLogListResponse>('/api/v1/admin/audit-logs', { params }).then(r => r.data),
|
||||
exportAuditLogs: (params?: Record<string, string>) =>
|
||||
api.get('/api/v1/admin/audit-logs/export', { params, responseType: 'blob' }),
|
||||
|
||||
// Plan Limits
|
||||
listPlanLimits: () =>
|
||||
api.get<PlanLimitConfig[]>('/api/v1/admin/plan-limits').then(r => r.data),
|
||||
updatePlanLimits: (data: PlanLimitConfig) =>
|
||||
api.put<PlanLimitConfig>('/api/v1/admin/plan-limits', data).then(r => r.data),
|
||||
|
||||
// Account Overrides
|
||||
listAccountOverrides: () =>
|
||||
api.get<AccountOverrideResponse[]>('/api/v1/admin/account-overrides').then(r => r.data),
|
||||
createAccountOverride: (data: AccountOverrideCreate) =>
|
||||
api.post<AccountOverrideResponse>('/api/v1/admin/account-overrides', data).then(r => r.data),
|
||||
updateAccountOverride: (id: string, data: Partial<AccountOverrideCreate>) =>
|
||||
api.put<AccountOverrideResponse>(`/api/v1/admin/account-overrides/${id}`, data).then(r => r.data),
|
||||
deleteAccountOverride: (id: string) =>
|
||||
api.delete(`/api/v1/admin/account-overrides/${id}`),
|
||||
|
||||
// Feature Flags
|
||||
listFeatureFlags: () =>
|
||||
api.get<FeatureFlagResponse[]>('/api/v1/admin/feature-flags').then(r => r.data),
|
||||
createFeatureFlag: (data: FeatureFlagCreate) =>
|
||||
api.post<FeatureFlagResponse>('/api/v1/admin/feature-flags', data).then(r => r.data),
|
||||
updateFeatureFlag: (id: string, data: Partial<FeatureFlagCreate>) =>
|
||||
api.put<FeatureFlagResponse>(`/api/v1/admin/feature-flags/${id}`, data).then(r => r.data),
|
||||
deleteFeatureFlag: (id: string) =>
|
||||
api.delete(`/api/v1/admin/feature-flags/${id}`),
|
||||
updatePlanDefault: (data: PlanDefaultUpdate) =>
|
||||
api.put('/api/v1/admin/feature-flags/plan-defaults', data).then(r => r.data),
|
||||
|
||||
// Feature Flag Account Overrides
|
||||
listFeatureFlagOverrides: () =>
|
||||
api.get<AccountFeatureOverrideResponse[]>('/api/v1/admin/feature-flags/account-overrides').then(r => r.data),
|
||||
createFeatureFlagOverride: (data: AccountFeatureOverrideCreate) =>
|
||||
api.post<AccountFeatureOverrideResponse>('/api/v1/admin/feature-flags/account-overrides', data).then(r => r.data),
|
||||
deleteFeatureFlagOverride: (id: string) =>
|
||||
api.delete(`/api/v1/admin/feature-flags/account-overrides/${id}`),
|
||||
|
||||
// Platform Settings
|
||||
listSettings: () =>
|
||||
api.get<{ settings: Record<string, unknown> }>('/api/v1/admin/settings').then(r => r.data),
|
||||
updateSettings: (settings: Record<string, unknown>) =>
|
||||
api.put<{ settings: Record<string, unknown> }>('/api/v1/admin/settings', { settings }).then(r => r.data),
|
||||
|
||||
// Global Categories
|
||||
listGlobalCategories: () =>
|
||||
api.get<AdminCategory[]>('/api/v1/admin/categories/global').then(r => r.data),
|
||||
createGlobalCategory: (data: GlobalCategoryCreate) =>
|
||||
api.post<AdminCategory>('/api/v1/admin/categories/global', data).then(r => r.data),
|
||||
updateGlobalCategory: (id: string, data: Partial<GlobalCategoryCreate>) =>
|
||||
api.put<AdminCategory>(`/api/v1/admin/categories/global/${id}`, data).then(r => r.data),
|
||||
deleteGlobalCategory: (id: string) =>
|
||||
api.delete(`/api/v1/admin/categories/global/${id}`),
|
||||
}
|
||||
|
||||
export default adminApi
|
||||
@@ -9,3 +9,4 @@ export { default as foldersApi } from './folders'
|
||||
export { default as stepsApi } from './steps'
|
||||
export { default as stepCategoriesApi } from './stepCategories'
|
||||
export { default as accountsApi } from './accounts'
|
||||
export { default as adminApi } from './admin'
|
||||
|
||||
Reference in New Issue
Block a user