UNPKG

analytica-frontend-lib

Version:

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

1 lines 10.5 kB
{"version":3,"sources":["../../../src/hooks/useRecommendedLessons.ts"],"sourcesContent":["import { useState, useCallback } from 'react';\nimport { z } from 'zod';\nimport dayjs from 'dayjs';\nimport { GoalDisplayStatus } from '../types/recommendedLessons';\nimport type {\n GoalHistoryItem,\n GoalTableItem,\n GoalsHistoryApiResponse,\n GoalHistoryFilters,\n GoalHistoryPagination,\n} from '../types/recommendedLessons';\n\n/**\n * Zod schema for goal history API response validation\n * Based on /recommended-class/history endpoint\n */\nconst goalSubjectSchema = z\n .object({\n id: z.string().uuid(),\n name: z.string(),\n })\n .nullable();\n\nconst goalCreatorSchema = z\n .object({\n id: z.string().uuid(),\n name: z.string(),\n })\n .nullable();\n\nconst goalStatsSchema = z.object({\n totalStudents: z.number(),\n completedCount: z.number(),\n completionPercentage: z.number(),\n});\n\nconst goalBreakdownSchema = z.object({\n classId: z.string().uuid(),\n className: z.string(),\n schoolId: z.string(),\n schoolName: z.string(),\n studentCount: z.number(),\n completedCount: z.number(),\n});\n\nconst goalDataSchema = z.object({\n id: z.string().uuid(),\n title: z.string(),\n startDate: z.string().nullable(),\n finalDate: z.string().nullable(),\n createdAt: z.string(),\n progress: z.number(),\n totalLessons: z.number(),\n});\n\nconst goalHistoryItemSchema = z.object({\n goal: goalDataSchema,\n subject: goalSubjectSchema,\n creator: goalCreatorSchema,\n stats: goalStatsSchema,\n breakdown: z.array(goalBreakdownSchema),\n});\n\nexport const goalsHistoryApiResponseSchema = z.object({\n message: z.string(),\n data: z.object({\n goals: z.array(goalHistoryItemSchema),\n total: z.number(),\n }),\n});\n\n/**\n * Hook state interface\n */\nexport interface UseRecommendedLessonsHistoryState {\n goals: GoalTableItem[];\n loading: boolean;\n error: string | null;\n pagination: GoalHistoryPagination;\n}\n\n/**\n * Hook return type\n */\nexport interface UseRecommendedLessonsHistoryReturn\n extends UseRecommendedLessonsHistoryState {\n fetchGoals: (filters?: GoalHistoryFilters) => Promise<void>;\n}\n\n/**\n * Determine status based on dates and completion\n * @param finalDate - Goal final date\n * @param completionPercentage - Completion percentage\n * @returns Display status for UI\n */\nexport const determineGoalStatus = (\n finalDate: string | null,\n completionPercentage: number\n): GoalDisplayStatus => {\n if (completionPercentage === 100) {\n return GoalDisplayStatus.CONCLUIDA;\n }\n\n if (finalDate) {\n const now = dayjs();\n const deadline = dayjs(finalDate);\n if (deadline.isBefore(now)) {\n return GoalDisplayStatus.VENCIDA;\n }\n }\n\n return GoalDisplayStatus.ATIVA;\n};\n\n/**\n * Transform API response to table item format\n * @param item - Goal history item from API response\n * @returns Formatted goal for table display\n */\nexport const transformGoalToTableItem = (\n item: GoalHistoryItem\n): GoalTableItem => {\n // Get first breakdown for school/class info (or aggregate)\n const firstBreakdown = item.breakdown[0];\n const schoolName = firstBreakdown?.schoolName || '-';\n const className = firstBreakdown?.className || '-';\n\n // If multiple classes, show count\n const classDisplay =\n item.breakdown.length > 1 ? `${item.breakdown.length} turmas` : className;\n\n return {\n id: item.goal.id,\n startDate: item.goal.startDate\n ? dayjs(item.goal.startDate).format('DD/MM')\n : '-',\n deadline: item.goal.finalDate\n ? dayjs(item.goal.finalDate).format('DD/MM')\n : '-',\n title: item.goal.title,\n school: schoolName,\n year: '-', // API doesn't provide year directly\n subject: item.subject?.name || '-',\n class: classDisplay,\n status: determineGoalStatus(\n item.goal.finalDate,\n item.stats.completionPercentage\n ),\n completionPercentage: item.stats.completionPercentage,\n };\n};\n\n/**\n * Handle errors during goal fetch\n * @param error - Error object\n * @returns Error message for UI display\n */\nexport const handleGoalFetchError = (error: unknown): string => {\n if (error instanceof z.ZodError) {\n console.error('Erro ao validar dados de histórico de aulas:', error);\n return 'Erro ao validar dados de histórico de aulas';\n }\n\n console.error('Erro ao carregar histórico de aulas:', error);\n return 'Erro ao carregar histórico de aulas';\n};\n\n/**\n * Factory function to create useRecommendedLessonsHistory hook\n *\n * @param fetchGoalsHistory - Function to fetch goals from API\n * @returns Hook for managing recommended lessons history\n *\n * @example\n * ```tsx\n * // In your app setup\n * const fetchGoalsHistory = async (filters) => {\n * const response = await api.get('/recommended-class/history', { params: filters });\n * return response.data;\n * };\n *\n * const useGoalsHistory = createUseRecommendedLessonsHistory(fetchGoalsHistory);\n *\n * // In your component\n * const { goals, loading, error, pagination, fetchGoals } = useGoalsHistory();\n * ```\n */\nexport const createUseRecommendedLessonsHistory = (\n fetchGoalsHistory: (\n filters?: GoalHistoryFilters\n ) => Promise<GoalsHistoryApiResponse>\n) => {\n return (): UseRecommendedLessonsHistoryReturn => {\n const [state, setState] = useState<UseRecommendedLessonsHistoryState>({\n goals: [],\n loading: false,\n error: null,\n pagination: {\n total: 0,\n page: 1,\n limit: 10,\n totalPages: 0,\n },\n });\n\n /**\n * Fetch goals history from API\n * @param filters - Optional filters for pagination, search, sorting, etc.\n */\n const fetchGoals = useCallback(\n async (filters?: GoalHistoryFilters) => {\n setState((prev) => ({ ...prev, loading: true, error: null }));\n\n try {\n // Fetch data from API\n const responseData = await fetchGoalsHistory(filters);\n\n // Validate response with Zod\n const validatedData =\n goalsHistoryApiResponseSchema.parse(responseData);\n\n // Transform goals to table format\n const tableItems = validatedData.data.goals.map(\n transformGoalToTableItem\n );\n\n // Calculate pagination from total\n const page = filters?.page || 1;\n const limit = filters?.limit || 10;\n const total = validatedData.data.total;\n const totalPages = Math.ceil(total / limit);\n\n // Update state with validated and transformed data\n setState({\n goals: tableItems,\n loading: false,\n error: null,\n pagination: {\n total,\n page,\n limit,\n totalPages,\n },\n });\n } catch (error) {\n const errorMessage = handleGoalFetchError(error);\n setState((prev) => ({\n ...prev,\n loading: false,\n error: errorMessage,\n }));\n }\n },\n [fetchGoalsHistory]\n );\n\n return {\n ...state,\n fetchGoals,\n };\n };\n};\n\n/**\n * Alias for createUseRecommendedLessonsHistory\n */\nexport const createRecommendedLessonsHistoryHook =\n createUseRecommendedLessonsHistory;\n"],"mappings":"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","names":[]}