Files
resolutionflow/frontend/src/api/admin.ts
2026-04-02 04:37:23 +00:00

248 lines
11 KiB
TypeScript

import api from './client'
import type {
DashboardMetrics,
ActivityEntry,
AdminUserListResponse,
AdminAccountListResponse,
AdminAccountDetailResponse,
AdminAccountCreate,
AdminAccountUpdate,
AuditLogListResponse,
PlanLimitConfig,
AccountOverrideResponse,
AccountOverrideCreate,
FeatureFlagResponse,
FeatureFlagCreate,
PlanDefaultUpdate,
AccountFeatureOverrideResponse,
AccountFeatureOverrideCreate,
AdminCategory,
GlobalCategoryCreate,
InviteCodeResponse,
InviteCodeCreateRequest,
UserDetailResponse,
AdminUserCreate,
AdminUserCreateResponse,
} from '@/types/admin'
export interface SurveyInviteResponse {
id: string
token: string
recipient_name: string
recipient_email: string | null
status: string
email_sent: boolean
created_at: string
completed_at: string | null
survey_url: string
}
export interface SurveyResponseDetail {
id: string
respondent_name: string | null
responses: Record<string, string | string[]>
source: 'invite' | 'direct'
invite_name: string | null
is_read: boolean
archived_at: string | null
created_at: string
}
export interface SurveyResponseListResponse {
responses: SurveyResponseDetail[]
total: number
this_week: number
unread: number
}
export interface GalleryFlowItem {
id: string
name: string
tree_type: string
is_gallery_featured: boolean
gallery_sort_order: number
visibility: string
}
export interface GalleryScriptItem {
id: string
name: string
is_gallery_featured: boolean
gallery_sort_order: number
is_active: boolean
}
export const adminApi = {
// Dashboard
getDashboardMetrics: () =>
api.get<DashboardMetrics>('/admin/dashboard/metrics').then(r => r.data),
getDashboardActivity: () =>
api.get<ActivityEntry[]>('/admin/dashboard/activity').then(r => r.data),
// Users
createUser: (data: AdminUserCreate) =>
api.post<AdminUserCreateResponse>('/admin/users', data).then(r => r.data),
listUsers: (params?: Record<string, unknown>) =>
api.get<AdminUserListResponse>('/admin/users', { params }).then(r => r.data),
listAccounts: (params?: Record<string, unknown>) =>
api.get<AdminAccountListResponse>('/admin/accounts', { params }).then(r => r.data),
createAccount: (data: AdminAccountCreate) =>
api.post<AdminAccountDetailResponse>('/admin/accounts', data).then(r => r.data),
getAccountDetail: (id: string, params?: Record<string, unknown>) =>
api.get<AdminAccountDetailResponse>(`/admin/accounts/${id}`, { params }).then(r => r.data),
updateAccount: (id: string, data: AdminAccountUpdate) =>
api.put<AdminAccountDetailResponse>(`/admin/accounts/${id}`, data).then(r => r.data),
getUser: (id: string) =>
api.get(`/admin/users/${id}`).then(r => r.data),
updateUserRole: (id: string, role: string) =>
api.put(`/admin/users/${id}/role`, { role }).then(r => r.data),
updateAccountRole: (id: string, account_role: string) =>
api.put(`/admin/users/${id}/account-role`, { account_role }).then(r => r.data),
updateSuperAdminStatus: (id: string, is_super_admin: boolean) =>
api.put(`/admin/users/${id}/super-admin`, { is_super_admin }).then(r => r.data),
deactivateUser: (id: string) =>
api.put(`/admin/users/${id}/deactivate`).then(r => r.data),
activateUser: (id: string) =>
api.put(`/admin/users/${id}/activate`).then(r => r.data),
moveUserAccount: (id: string, display_code: string) =>
api.put(`/admin/users/${id}/move-account`, { display_code }).then(r => r.data),
// Users - archive & delete
archiveUser: (id: string) =>
api.put(`/admin/users/${id}/archive`).then(r => r.data),
restoreUser: (id: string) =>
api.put(`/admin/users/${id}/restore`).then(r => r.data),
hardDeleteCheck: (id: string) =>
api.get<{ can_delete: boolean; blockers: Record<string, number> }>(`/admin/users/${id}/hard-delete-check`).then(r => r.data),
hardDeleteUser: (id: string) =>
api.delete(`/admin/users/${id}/hard-delete`),
// Users - quick invite
createInvite: (data: { email: string; account_display_code: string; role: string }) =>
api.post<{ id: string; email: string; code: string; role: string; account_display_code: string; email_sent: boolean }>('/admin/invites', data).then(r => r.data),
// Users - password reset
adminResetPassword: (id: string, mode: 'email_link' | 'temp_password') =>
api.post<{ message: string; temporary_password?: string; email_sent: boolean }>(`/admin/users/${id}/password-reset`, { mode }).then(r => r.data),
// Users - detail + subscription
getUserDetail: (id: string) =>
api.get<UserDetailResponse>(`/admin/users/${id}`).then(r => r.data),
updateUserSubscriptionPlan: (id: string, plan: string) =>
api.put(`/admin/users/${id}/subscription/plan`, { plan }).then(r => r.data),
extendUserTrial: (id: string, days: number) =>
api.put(`/admin/users/${id}/subscription/extend-trial`, { days }).then(r => r.data),
updateAccountSubscriptionPlan: (id: string, plan: string) =>
api.put(`/admin/accounts/${id}/subscription/plan`, { plan }).then(r => r.data),
extendAccountTrial: (id: string, days: number) =>
api.put(`/admin/accounts/${id}/subscription/extend-trial`, { days }).then(r => r.data),
// Invite Codes
listInviteCodes: (params?: Record<string, unknown>) =>
api.get<InviteCodeResponse[]>('/invites', { params }).then(r => r.data),
createInviteCode: (data: InviteCodeCreateRequest = {}) =>
api.post<InviteCodeResponse>('/invites', data).then(r => r.data),
deleteInviteCode: (code: string) =>
api.delete(`/invites/${code}`),
resendInviteCode: (code: string) =>
api.post<InviteCodeResponse>(`/invites/${code}/resend`).then(r => r.data),
// Audit Logs
listAuditLogs: (params?: Record<string, unknown>) =>
api.get<AuditLogListResponse>('/admin/audit-logs', { params }).then(r => r.data),
exportAuditLogs: (params?: Record<string, string>) =>
api.get('/admin/audit-logs/export', { params, responseType: 'blob' }),
// Plan Limits
listPlanLimits: () =>
api.get<PlanLimitConfig[]>('/admin/plan-limits').then(r => r.data),
updatePlanLimits: (data: PlanLimitConfig) =>
api.put<PlanLimitConfig>('/admin/plan-limits', data).then(r => r.data),
// Account Overrides
listAccountOverrides: () =>
api.get<AccountOverrideResponse[]>('/admin/account-overrides').then(r => r.data),
createAccountOverride: (data: AccountOverrideCreate) =>
api.post<AccountOverrideResponse>('/admin/account-overrides', data).then(r => r.data),
updateAccountOverride: (id: string, data: Partial<AccountOverrideCreate>) =>
api.put<AccountOverrideResponse>(`/admin/account-overrides/${id}`, data).then(r => r.data),
deleteAccountOverride: (id: string) =>
api.delete(`/admin/account-overrides/${id}`),
// Feature Flags
listFeatureFlags: () =>
api.get<FeatureFlagResponse[]>('/admin/feature-flags').then(r => r.data),
createFeatureFlag: (data: FeatureFlagCreate) =>
api.post<FeatureFlagResponse>('/admin/feature-flags', data).then(r => r.data),
updateFeatureFlag: (id: string, data: Partial<FeatureFlagCreate>) =>
api.put<FeatureFlagResponse>(`/admin/feature-flags/${id}`, data).then(r => r.data),
deleteFeatureFlag: (id: string) =>
api.delete(`/admin/feature-flags/${id}`),
updatePlanDefault: (data: PlanDefaultUpdate) =>
api.put('/admin/feature-flags/plan-defaults', data).then(r => r.data),
// Feature Flag Account Overrides
listFeatureFlagOverrides: () =>
api.get<AccountFeatureOverrideResponse[]>('/admin/feature-flags/account-overrides').then(r => r.data),
createFeatureFlagOverride: (data: AccountFeatureOverrideCreate) =>
api.post<AccountFeatureOverrideResponse>('/admin/feature-flags/account-overrides', data).then(r => r.data),
deleteFeatureFlagOverride: (id: string) =>
api.delete(`/admin/feature-flags/account-overrides/${id}`),
// Platform Settings
listSettings: () =>
api.get<{ settings: Record<string, unknown> }>('/admin/settings').then(r => r.data),
updateSettings: (settings: Record<string, unknown>) =>
api.put<{ settings: Record<string, unknown> }>('/admin/settings', { settings }).then(r => r.data),
// Global Categories
listGlobalCategories: () =>
api.get<AdminCategory[]>('/admin/categories/global').then(r => r.data),
createGlobalCategory: (data: GlobalCategoryCreate) =>
api.post<AdminCategory>('/admin/categories/global', data).then(r => r.data),
updateGlobalCategory: (id: string, data: Partial<GlobalCategoryCreate>) =>
api.put<AdminCategory>(`/admin/categories/global/${id}`, data).then(r => r.data),
deleteGlobalCategory: (id: string) =>
api.delete(`/admin/categories/global/${id}`),
// Survey Invites
listSurveyInvites: () =>
api.get<SurveyInviteResponse[]>('/admin/survey-invites').then(r => r.data),
createSurveyInvite: (data: { recipient_name: string; recipient_email?: string; send_email?: boolean }) =>
api.post<SurveyInviteResponse>('/admin/survey-invites', data).then(r => r.data),
// Survey Responses
listSurveyResponses: (includeArchived = false) =>
api.get<SurveyResponseListResponse>('/admin/survey-responses', { params: { include_archived: includeArchived } }).then(r => r.data),
exportSurveyResponsesCsv: () =>
api.get('/admin/survey-responses/export', { responseType: 'blob' }).then(r => r.data),
markResponseRead: (id: string) =>
api.put(`/admin/survey-responses/${id}/read`).then(r => r.data),
markResponseUnread: (id: string) =>
api.put(`/admin/survey-responses/${id}/unread`).then(r => r.data),
archiveResponse: (id: string) =>
api.put(`/admin/survey-responses/${id}/archive`).then(r => r.data),
unarchiveResponse: (id: string) =>
api.put(`/admin/survey-responses/${id}/unarchive`).then(r => r.data),
deleteResponse: (id: string) =>
api.delete(`/admin/survey-responses/${id}`),
bulkActionResponses: (action: string, ids: string[]) =>
api.post('/admin/survey-responses/bulk', { action, ids }).then(r => r.data),
// Gallery Curation
getGalleryFeatured: () =>
api.get<{ flows: GalleryFlowItem[]; scripts: GalleryScriptItem[] }>('/admin/gallery/featured').then(r => r.data),
getGalleryAllItems: () =>
api.get<{ flows: GalleryFlowItem[]; scripts: GalleryScriptItem[] }>('/admin/gallery/items').then(r => r.data),
toggleFlowFeatured: (id: string, is_gallery_featured: boolean) =>
api.patch<GalleryFlowItem>(`/admin/gallery/flows/${id}/feature`, { is_gallery_featured }).then(r => r.data),
updateFlowSortOrder: (id: string, gallery_sort_order: number) =>
api.patch<GalleryFlowItem>(`/admin/gallery/flows/${id}/sort-order`, { gallery_sort_order }).then(r => r.data),
toggleScriptFeatured: (id: string, is_gallery_featured: boolean) =>
api.patch<GalleryScriptItem>(`/admin/gallery/scripts/${id}/feature`, { is_gallery_featured }).then(r => r.data),
updateScriptSortOrder: (id: string, gallery_sort_order: number) =>
api.patch<GalleryScriptItem>(`/admin/gallery/scripts/${id}/sort-order`, { gallery_sort_order }).then(r => r.data),
}
export default adminApi