import { adminApiClient } from './client' import type { EditCardPackDto, CardPackPreviewDto, PaginatedResponse } from '@/types/models' import type { AxiosError } from 'axios' export interface PacksApiError { message: string statusCode?: number field?: string originalError?: unknown name: 'PacksApiError' } export function createPacksApiError( message: string, statusCode?: number, field?: string, originalError?: unknown ): PacksApiError { return { message, statusCode, field, originalError, name: 'PacksApiError', } } export function isPacksApiError(error: unknown): error is PacksApiError { return ( typeof error === 'object' && error !== null && 'name' in error && error.name === 'PacksApiError' ) } export const packsApi = { // Get all packs with pagination and search getPacks: async (params?: { page?: number limit?: number search?: string showDisabled?: boolean }): Promise> => { try { const response = await adminApiClient.get('/api/admin/packs', { params: { page: params?.page || 1, limit: params?.limit || 20, search: params?.search, isPublic: params?.showDisabled === false ? true : undefined, }, }) // Transform backend response to match frontend PaginatedResponse const backendData = response.data return { items: backendData.packs.map((pack: any) => ({ id: pack.id, title: pack.name, cards: pack.questionCount, enabled: pack.isPublic, })), total: backendData.total, page: backendData.page, limit: backendData.limit, totalPages: backendData.totalPages, } } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string; field?: string }> // Check for validation errors (limit too high, etc.) if (axiosError.response?.status === 400) { const errorData = axiosError.response.data if (errorData?.message?.includes('Limit')) { throw createPacksApiError( `Invalid limit: ${errorData.message}. Maximum allowed limit is 100.`, axiosError.response.status, 'limit', error ) } } throw createPacksApiError( axiosError.response?.data?.message || axiosError.response?.data?.error || 'Failed to load packs', axiosError.response?.status, axiosError.response?.data?.field, error ) } }, // Get pack details by ID for editing getPack: async (packId: string): Promise => { try { const response = await adminApiClient.get(`/api/admin/packs/${packId}`) const pack = response.data // Transform backend response to match EditCardPackDto return { id: pack.id, name: pack.name, description: pack.description, category: pack.category, isPublic: pack.isPublic, questions: pack.questions, } } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string }> if (axiosError.response?.status === 404) { throw createPacksApiError( `Pack not found: The pack with ID "${packId}" does not exist or has been deleted.`, axiosError.response.status, undefined, error ) } throw createPacksApiError( axiosError.response?.data?.message || axiosError.response?.data?.error || `Failed to load pack ${packId}`, axiosError.response?.status, undefined, error ) } }, // Create or update pack upsertPack: async (pack: EditCardPackDto): Promise<{ success: boolean; pack: EditCardPackDto }> => { try { const isUpdate = pack.id && pack.id.length > 0 const url = isUpdate ? `/api/admin/packs/${pack.id}` : '/api/admin/packs' const method = isUpdate ? 'patch' : 'post' const response = await adminApiClient[method](url, { name: pack.name, description: pack.description, category: pack.category, isPublic: pack.isPublic, questions: pack.questions, }) return { success: true, pack: response.data, } } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string; field?: string; details?: string }> const isUpdate = pack.id && pack.id.length > 0 const operation = isUpdate ? 'update pack' : 'create pack' const baseMessage = axiosError.response?.data?.message || axiosError.response?.data?.error || `Failed to ${operation}` let fullMessage = baseMessage if (axiosError.response?.data?.details) { fullMessage += `. ${axiosError.response.data.details}` } // Special handling for common errors if (axiosError.response?.status === 404 && isUpdate) { fullMessage = `Pack not found: The pack you're trying to update (ID: ${pack.id}) does not exist.` } if (axiosError.response?.data?.field) { fullMessage += ` (Field: ${axiosError.response.data.field})` } throw createPacksApiError( fullMessage, axiosError.response?.status, axiosError.response?.data?.field, error ) } }, // Delete pack deletePack: async (packId: string): Promise<{ success: boolean; message: string }> => { try { const response = await adminApiClient.delete(`/api/admin/packs/${packId}`) return response.data } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string }> if (axiosError.response?.status === 404) { throw createPacksApiError( `Pack not found: The pack with ID "${packId}" does not exist and cannot be deleted.`, axiosError.response.status, undefined, error ) } throw createPacksApiError( axiosError.response?.data?.message || axiosError.response?.data?.error || `Failed to delete pack ${packId}`, axiosError.response?.status, undefined, error ) } }, // Get empty template for import getTemplate: async (): Promise<{ templateVersion: string instructions: string questions: Array<{ question: string; answers: Array<{ text: string; points: number }> }> }> => { try { const response = await adminApiClient.get('/api/admin/packs/export/template') return response.data } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string }> throw createPacksApiError( axiosError.response?.data?.message || axiosError.response?.data?.error || 'Failed to get template', axiosError.response?.status, undefined, error ) } }, // Export pack to JSON exportPack: async (packId: string): Promise<{ templateVersion: string exportedAt: string packInfo: { name: string description: string category: string isPublic: boolean } questions: Array<{ question: string; answers: Array<{ text: string; points: number }> }> }> => { try { const response = await adminApiClient.get(`/api/admin/packs/${packId}/export`) return response.data } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string }> if (axiosError.response?.status === 404) { throw createPacksApiError( `Pack not found: The pack with ID "${packId}" does not exist.`, axiosError.response.status, undefined, error ) } throw createPacksApiError( axiosError.response?.data?.message || axiosError.response?.data?.error || `Failed to export pack ${packId}`, axiosError.response?.status, undefined, error ) } }, // Import pack from JSON importPack: async (data: { name: string description: string category: string isPublic: boolean questions: Array<{ question: string; answers: Array<{ text: string; points: number }> }> }): Promise => { try { const response = await adminApiClient.post('/api/admin/packs/import', data) return response.data } catch (error) { const axiosError = error as AxiosError<{ error?: string; message?: string }> throw createPacksApiError( axiosError.response?.data?.message || axiosError.response?.data?.error || 'Failed to import pack', axiosError.response?.status, undefined, error ) } }, }