UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

1 lines 8.57 kB
{"version":3,"sources":["../src/hooks/useExamsHistory.ts"],"sourcesContent":["import { useState, useCallback } from 'react';\nimport dayjs from 'dayjs';\nimport type { BaseApiClient } from '../types/api';\nimport { mapExamStatusToDisplay } from '../types/examsHistory';\nimport type {\n ExamHistoryResponse,\n ExamTableItem,\n ExamsHistoryApiResponse,\n ExamHistoryFilters,\n ExamPagination,\n ExamApiFilterOptions,\n} from '../types/examsHistory';\nimport { createFetchErrorHandler } from '../utils/hookErrorHandler';\nimport {\n mergeFilterOptions,\n extractBreakdownFilterOptions,\n} from '../utils/filterHelpers';\n\n/**\n * Hook state interface\n */\nexport interface UseExamsHistoryState {\n exams: ExamTableItem[];\n loading: boolean;\n error: string | null;\n pagination: ExamPagination;\n apiFilterOptions: ExamApiFilterOptions;\n}\n\n/**\n * Hook return type\n */\nexport interface UseExamsHistoryReturn extends UseExamsHistoryState {\n fetchExams: (filters?: ExamHistoryFilters) => Promise<void>;\n}\n\n/**\n * Default pagination values\n */\nexport const DEFAULT_EXAMS_PAGINATION: ExamPagination = {\n total: 0,\n page: 1,\n limit: 10,\n totalPages: 0,\n};\n\n/**\n * Default API filter options\n */\nexport const DEFAULT_EXAM_FILTER_OPTIONS: ExamApiFilterOptions = {\n schools: [],\n classes: [],\n subjects: [],\n schoolYears: [],\n};\n\n/**\n * Transform API response to table item format\n * @param exam - Exam from API response\n * @returns Formatted exam for table display\n */\nexport const transformExamToTableItem = (\n exam: ExamHistoryResponse\n): ExamTableItem => {\n const firstBreakdown = exam.breakdown?.[0];\n return {\n id: exam.id,\n startDate: exam.startDate\n ? dayjs(exam.startDate).format('DD/MM/YYYY')\n : '-',\n title: exam.title,\n school: firstBreakdown?.school?.name ?? '-',\n class: firstBreakdown?.class?.name ?? '-',\n status: mapExamStatusToDisplay(exam.status),\n questionCount: exam.questionCount,\n createdAt: dayjs(exam.createdAt).format('DD/MM/YYYY'),\n completionPercentage: exam.completionPercentage,\n };\n};\n\n/**\n * Handle errors during exam fetch\n * Uses the generic error handler factory to reduce code duplication\n */\nexport const handleExamFetchError = createFetchErrorHandler(\n 'Erro ao validar dados de historico de provas',\n 'Erro ao carregar historico de provas'\n);\n\n/**\n * Extract unique filter options from exams API response.\n * Delegates to the shared extractBreakdownFilterOptions helper.\n */\nexport const extractExamFilterOptions = (\n exams: ExamHistoryResponse[]\n): ExamApiFilterOptions => extractBreakdownFilterOptions(exams);\n\n/**\n * Build query params from filters\n * Always includes type=PROVA to filter for exams\n */\nconst buildQueryParams = (\n filters?: ExamHistoryFilters\n): Record<string, unknown> => {\n // Always include type=PROVA for exam filtering\n if (!filters) return { type: 'PROVA' };\n\n const params: Record<string, unknown> = { type: 'PROVA' };\n for (const key in filters) {\n const value = filters[key as keyof ExamHistoryFilters];\n if (value !== undefined && value !== null) {\n params[key] = value;\n }\n }\n return params;\n};\n\n/**\n * Hook implementation\n */\nconst useExamsHistoryImpl = (\n apiClient: BaseApiClient\n): UseExamsHistoryReturn => {\n const [state, setState] = useState<UseExamsHistoryState>({\n exams: [],\n loading: false,\n error: null,\n pagination: DEFAULT_EXAMS_PAGINATION,\n apiFilterOptions: DEFAULT_EXAM_FILTER_OPTIONS,\n });\n\n /**\n * Fetch exams history from API\n * @param filters - Optional filters for pagination, search, sorting, etc.\n */\n const fetchExams = useCallback(\n async (filters?: ExamHistoryFilters) => {\n setState((prev) => ({ ...prev, loading: true, error: null }));\n\n try {\n const params = buildQueryParams(filters);\n // Use activities/history endpoint with type=PROVA\n const response = await apiClient.get<ExamsHistoryApiResponse>(\n '/activities/history',\n { params }\n );\n\n const { data } = response.data;\n\n // Transform activities to table format (response uses 'activities' field)\n const tableItems = data.activities.map((exam) =>\n transformExamToTableItem(exam)\n );\n\n // Extract filter options from response\n const extracted = extractExamFilterOptions(data.activities);\n\n // Update state with transformed data\n setState((prev) => ({\n exams: tableItems,\n loading: false,\n error: null,\n pagination: data.pagination,\n apiFilterOptions: {\n schools: mergeFilterOptions(\n prev.apiFilterOptions.schools,\n extracted.schools\n ),\n classes: mergeFilterOptions(\n prev.apiFilterOptions.classes,\n extracted.classes\n ),\n subjects: mergeFilterOptions(\n prev.apiFilterOptions.subjects,\n extracted.subjects\n ),\n schoolYears: mergeFilterOptions(\n prev.apiFilterOptions.schoolYears,\n extracted.schoolYears\n ),\n },\n }));\n } catch (error) {\n const errorMessage = handleExamFetchError(error);\n setState((prev) => ({\n ...prev,\n loading: false,\n error: errorMessage,\n }));\n }\n },\n [apiClient]\n );\n\n return {\n ...state,\n fetchExams,\n };\n};\n\n/**\n * Factory function to create useExamsHistory hook\n *\n * @param apiClient - API client instance (axios, fetch wrapper, etc.)\n * @returns Hook for managing exams history\n *\n * @example\n * ```tsx\n * // In your app setup\n * import { createUseExamsHistory } from 'analytica-frontend-lib';\n * import api from '@/services/apiService';\n *\n * export const useExamsHistory = createUseExamsHistory(api);\n *\n * // In your component\n * const { exams, loading, error, pagination, fetchExams } = useExamsHistory();\n * ```\n */\nexport const createUseExamsHistory = (apiClient: BaseApiClient) => {\n return (): UseExamsHistoryReturn => useExamsHistoryImpl(apiClient);\n};\n\n/**\n * Alias for createUseExamsHistory\n */\nexport const createExamsHistoryHook = createUseExamsHistory;\n"],"mappings":"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","names":[]}