UNPKG

analytica-frontend-lib

Version:

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

1 lines 26.1 kB
{"version":3,"sources":["../src/store/modulesStore.ts","../src/types/modulesConfig.ts","../src/hooks/useModules.ts"],"sourcesContent":["import { create } from 'zustand';\nimport { createJSONStorage, persist } from 'zustand/middleware';\nimport { KEYS } from '../utils/keys';\nimport { useAuthStore } from './authStore';\nimport type { AxiosInstance } from 'axios';\nimport {\n type ModulesConfig,\n DEFAULT_MODULES,\n mergeModulesConfig,\n} from '../types/modulesConfig';\n\n/**\n * Default modules configuration - all enabled\n */\nconst defaultModules = DEFAULT_MODULES;\n\n/**\n * Interface defining the modules state\n */\nexport interface ModulesState {\n modules: ModulesConfig;\n loading: boolean;\n ownerInstitutionId: string | null;\n ownerProfileType: string | null;\n\n /**\n * Fetch modules configuration from the API\n * @param institutionId - The institution UUID\n * @param api - Axios instance for API calls\n * @param profileType - Optional profile type (STUDENT, TEACHER, UNIT_MANAGER, etc.)\n */\n fetchModules: (\n institutionId: string,\n api: AxiosInstance,\n profileType?: string\n ) => Promise<void>;\n clearModules: () => void;\n}\n\n/**\n * API response structure for modules feature flag\n */\ninterface ModulesFeatureFlagResponse {\n data: {\n featureFlags: {\n institutionId: string;\n page: string;\n profileType?: string | null;\n version: Partial<ModulesConfig>;\n isDefault?: boolean;\n isProfileSpecific?: boolean;\n };\n } | null;\n}\n\n// Guard against stale async responses\nlet latestRequestId = 0;\n\n// Retry configuration\nconst MAX_RETRIES = 3;\nconst INITIAL_RETRY_DELAY = 1000; // 1 second\n\n/**\n * Delay helper for retry backoff\n */\nconst delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Read a key from localStorage, tolerating environments where access is\n * denied. Reading `localStorage` throws `SecurityError` (DOMException 18) in\n * privacy mode, with blocked cookies, or in sandboxed/cross-origin iframes;\n * treat that as \"no cached value\" instead of letting it crash app boot.\n */\nconst readLocalStorage = (key: string): string | null => {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n};\n\n/**\n * Check if modules are already cached in localStorage for the given profile\n */\nconst hasCachedModules = (profileType?: string): boolean => {\n const cached = readLocalStorage(KEYS.MODULES_STORAGE);\n if (!cached) return false;\n\n try {\n const parsed = JSON.parse(cached);\n // Check both institution and profile match\n const hasInstitution = Boolean(parsed.state?.ownerInstitutionId);\n const profileMatches =\n !profileType || parsed.state?.ownerProfileType === profileType;\n return hasInstitution && profileMatches;\n } catch {\n return false;\n }\n};\n\n/**\n * Check if this request has been superseded by a newer one\n */\nconst isStaleRequest = (requestId: number): boolean =>\n requestId !== latestRequestId;\n\n/**\n * Attempt to fetch modules from API with retry logic\n * Returns the modules config on success, null on failure\n */\nconst fetchWithRetry = async (\n institutionId: string,\n api: AxiosInstance,\n requestId: number,\n profileType?: string\n): Promise<Partial<ModulesConfig> | null> => {\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n if (attempt > 0) {\n await delay(INITIAL_RETRY_DELAY * Math.pow(2, attempt - 1));\n }\n\n if (isStaleRequest(requestId)) return null;\n\n try {\n // Use the new profile-specific endpoint if profileType is provided\n const endpoint = profileType\n ? `/featureFlags/institution/${institutionId}/page/MODULES/profile/${profileType}`\n : `/featureFlags/institution/${institutionId}/page/MODULES`;\n\n const response = await api.get<ModulesFeatureFlagResponse>(endpoint);\n\n if (isStaleRequest(requestId)) return null;\n\n return response.data?.data?.featureFlags?.version ?? {};\n } catch {\n // Continue to next retry attempt\n }\n }\n\n console.warn('[modulesStore] Failed to fetch modules after retries');\n return null;\n};\n\n/**\n * Zustand store for managing modules visibility with persistence\n * Works with all frontends (student, professor, gestor)\n * Supports profile-specific feature flags\n */\nexport const useModulesStore = create<ModulesState>()(\n persist(\n (set) => ({\n modules: defaultModules,\n loading: false,\n ownerInstitutionId: null,\n ownerProfileType: null,\n\n /**\n * Fetch modules configuration from the API\n * Only fetches if:\n * 1. No modules data exists in localStorage for this profile\n * 2. User made a new login (data cleared by auth subscriber)\n * Implements retry with exponential backoff on failure\n *\n * @param institutionId - The institution UUID\n * @param api - Axios instance for API calls\n * @param profileType - Optional profile type (STUDENT, TEACHER, etc.)\n */\n fetchModules: async (\n institutionId: string,\n api: AxiosInstance,\n profileType?: string\n ): Promise<void> => {\n if (hasCachedModules(profileType)) return;\n\n const requestId = ++latestRequestId;\n set({ loading: true });\n\n const version = await fetchWithRetry(\n institutionId,\n api,\n requestId,\n profileType\n );\n\n if (isStaleRequest(requestId)) return;\n\n if (version === null) {\n set({ modules: defaultModules, loading: false });\n } else {\n set({\n modules: mergeModulesConfig(version),\n ownerInstitutionId: institutionId,\n ownerProfileType: profileType ?? null,\n loading: false,\n });\n }\n },\n\n /**\n * Clear modules data (useful when user/institution/profile changes)\n * Also invalidates any in-flight requests to prevent stale data overwriting cleared state\n */\n clearModules: (): void => {\n latestRequestId++;\n set({\n modules: defaultModules,\n loading: false,\n ownerInstitutionId: null,\n ownerProfileType: null,\n });\n },\n }),\n {\n name: KEYS.MODULES_STORAGE,\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => ({\n modules: state.modules,\n ownerInstitutionId: state.ownerInstitutionId,\n ownerProfileType: state.ownerProfileType,\n }),\n onRehydrateStorage: () => (rehydrated) => {\n if (!rehydrated) return;\n\n // Merge with defaultModules to ensure new fields have proper defaults\n // when loading old localStorage data that may be missing new fields\n const mergedModules = mergeModulesConfig(rehydrated.modules);\n useModulesStore.setState({ modules: mergedModules });\n\n const currentInstitutionId =\n useAuthStore.getState().sessionInfo?.institutionId ?? null;\n // Use sessionInfo.profileName to match what useAppContent passes to fetchModules\n const currentProfile =\n (useAuthStore.getState().sessionInfo as { profileName?: string })\n ?.profileName ?? null;\n\n // Clear if institution or profile changed\n if (\n (rehydrated.ownerInstitutionId &&\n rehydrated.ownerInstitutionId !== currentInstitutionId) ||\n (rehydrated.ownerProfileType &&\n rehydrated.ownerProfileType !== currentProfile)\n ) {\n useModulesStore.getState().clearModules();\n }\n },\n }\n )\n);\n\n// Clear modules whenever institution or profile changes (same-tab user switch)\n// Only clear when institution/profile actually CHANGES (not on initial hydration)\n// Use sessionInfo.profileName to match what useAppContent passes to fetchModules\nlet lastInstitutionId: string | null =\n useAuthStore.getState().sessionInfo?.institutionId ?? null;\nlet lastProfileType: string | null =\n (useAuthStore.getState().sessionInfo as { profileName?: string })\n ?.profileName ?? null;\n\nuseAuthStore.subscribe((state) => {\n const nextInstitutionId = state.sessionInfo?.institutionId ?? null;\n const nextProfileType =\n (state.sessionInfo as { profileName?: string })?.profileName ?? null;\n\n if (\n nextInstitutionId !== lastInstitutionId ||\n nextProfileType !== lastProfileType\n ) {\n // Only clear modules if there was a previous value (actual change, not initial load)\n // NOTE: Don't set ownerInstitutionId/ownerProfileType here - let fetchModules set them\n // after a successful fetch. Setting them here would cause hasCachedModules to return\n // true even though we only have DEFAULT_MODULES, skipping the necessary fetch.\n if (lastInstitutionId !== null || lastProfileType !== null) {\n useModulesStore.getState().clearModules();\n }\n lastInstitutionId = nextInstitutionId;\n lastProfileType = nextProfileType;\n }\n});\n","/**\n * Visibility state of a single module/feature.\n * - ENABLED: shown and functional\n * - COMING_SOON: shown but disabled, with an \"Em breve\" badge\n * - HIDDEN: not shown at all\n */\nexport type FeatureVisibility = 'ENABLED' | 'COMING_SOON' | 'HIDDEN';\n\n/**\n * Per-institution configuration of the Simulados module.\n * `enabled` is the master toggle (gates the whole module/menu); the remaining\n * keys map 1:1 to each simulado type's `backgroundColor` (the card catalog).\n */\nexport interface SimulationsConfig {\n enabled: boolean;\n enem: FeatureVisibility;\n prova: FeatureVisibility;\n simuladao: FeatureVisibility;\n vestibular: FeatureVisibility;\n}\n\n/**\n * Configuration for Performance screen graphs\n */\nexport interface PerformanceGraphsConfig {\n aulas: boolean; // Lessons graph\n acessos: boolean; // Access graph\n simulados: boolean; // Simulations graph\n atividades: boolean; // Activities graph\n questoes: boolean; // Questions graph\n ranking: boolean; // Ranking graph\n}\n\n/**\n * Configuration for Reports\n */\nexport interface ReportsConfig {\n simulatedReports: boolean; // Simulados Enem (existing)\n simulatedGenericReports: boolean; // Simulados (new version)\n activitiesReports: boolean;\n questionnairesReports: boolean; // Questionários\n lessonsReports: boolean;\n essayReports: boolean;\n}\n\n/**\n * Score display options for simulations\n */\nexport interface SimulatedScoreConfig {\n tri: boolean;\n absoluto: boolean;\n}\n\n/**\n * Default simulados configuration - module on, all types enabled\n */\nexport const DEFAULT_SIMULATIONS: SimulationsConfig = {\n enabled: true,\n enem: 'ENABLED',\n prova: 'ENABLED',\n simuladao: 'ENABLED',\n vestibular: 'ENABLED',\n};\n\n/**\n * Default exams configuration\n */\nexport const DEFAULT_EXAMS: boolean = true;\n\n/**\n * Default performance graphs configuration\n */\nexport const DEFAULT_PERFORMANCE_GRAPHS: PerformanceGraphsConfig = {\n aulas: true,\n acessos: true,\n simulados: true,\n atividades: true,\n questoes: true,\n ranking: true,\n};\n\n/**\n * Default reports configuration\n */\nexport const DEFAULT_REPORTS: ReportsConfig = {\n simulatedReports: true,\n simulatedGenericReports: false, // New reports default to disabled\n activitiesReports: true,\n questionnairesReports: false, // New reports default to disabled\n lessonsReports: true,\n essayReports: true,\n};\n\n/**\n * Default simulated score configuration\n */\nexport const DEFAULT_SIMULATED_SCORE: SimulatedScoreConfig = {\n tri: true,\n absoluto: true,\n};\n\n/**\n * Utility type that recursively makes all properties optional.\n * Used for API payloads and test data where only a subset of fields are provided.\n */\nexport type DeepPartial<T> = T extends object\n ? { [P in keyof T]?: DeepPartial<T[P]> }\n : T;\n\n/**\n * Complete modules configuration interface\n * All modules that can be controlled via feature flags\n */\nexport interface ModulesConfig {\n // Core modules\n simulator: boolean;\n essay: boolean;\n forum: boolean;\n support: boolean;\n chat: boolean;\n recommendedLessons: boolean;\n activities: boolean;\n questionBanks: boolean;\n comparator: boolean;\n performance: boolean;\n dashboard: boolean;\n lessons: boolean;\n\n // Tutorial menu link (off by default; also needs a non-empty tutorialUrl)\n tutorial: boolean;\n tutorialUrl: string;\n\n /**\n * Reading-fluency mode (opt-in per institution, off by default).\n * When `true`, the platform switches to the reading-fluency-only experience:\n * the professor app hides the navigation menu and exposes only the\n * \"Teste de fluência\" page. Consumed via `useModules().hasReadingFluency`.\n */\n readingFluency: boolean;\n\n // Nested configurations\n exams: boolean;\n simulations: SimulationsConfig;\n performanceGraphs: PerformanceGraphsConfig;\n reports: ReportsConfig;\n simulatedScore: SimulatedScoreConfig;\n\n // Legacy flat fields (for backwards compatibility)\n simulatedReports: boolean;\n simulatedGenericReports: boolean;\n activitiesReports: boolean;\n questionnairesReports: boolean;\n lessonsReports: boolean;\n essayReports: boolean;\n simulatedScoreTri: boolean;\n simulatedScoreAbsoluto: boolean;\n}\n\n/**\n * Default modules configuration - all enabled (permissive default pattern)\n */\nexport const DEFAULT_MODULES: ModulesConfig = {\n // Core modules\n simulator: true,\n essay: true,\n forum: true,\n support: true,\n chat: true,\n recommendedLessons: true,\n activities: true,\n questionBanks: true,\n comparator: true,\n performance: true,\n dashboard: true,\n lessons: true,\n\n // Tutorial off by default (opt-in per institution, requires a url)\n tutorial: false,\n tutorialUrl: '',\n\n // Reading-fluency mode off by default (opt-in per institution)\n readingFluency: false,\n\n // Nested configurations\n exams: DEFAULT_EXAMS,\n simulations: DEFAULT_SIMULATIONS,\n performanceGraphs: DEFAULT_PERFORMANCE_GRAPHS,\n reports: DEFAULT_REPORTS,\n simulatedScore: DEFAULT_SIMULATED_SCORE,\n\n // Legacy flat fields (for backwards compatibility)\n simulatedReports: true,\n simulatedGenericReports: false,\n activitiesReports: true,\n questionnairesReports: false,\n lessonsReports: true,\n essayReports: true,\n simulatedScoreTri: true,\n simulatedScoreAbsoluto: true,\n};\n\n/**\n * Deep merge a partial config onto defaults.\n * Handles nested objects (simulations, performanceGraphs, reports, simulatedScore).\n */\nexport const mergeModulesConfig = (\n version?: DeepPartial<ModulesConfig> | null\n): ModulesConfig => {\n const v = version ?? {};\n return {\n ...DEFAULT_MODULES,\n ...v,\n // exams is now a simple boolean, use default if not provided\n exams: v.exams ?? DEFAULT_EXAMS,\n simulations: { ...DEFAULT_SIMULATIONS, ...v.simulations },\n performanceGraphs: {\n ...DEFAULT_PERFORMANCE_GRAPHS,\n ...v.performanceGraphs,\n },\n reports: { ...DEFAULT_REPORTS, ...v.reports },\n simulatedScore: { ...DEFAULT_SIMULATED_SCORE, ...v.simulatedScore },\n };\n};\n","import { useModulesStore } from '../store/modulesStore';\nimport {\n DEFAULT_SIMULATIONS,\n DEFAULT_PERFORMANCE_GRAPHS,\n DEFAULT_REPORTS,\n DEFAULT_SIMULATED_SCORE,\n type ModulesConfig,\n type SimulationsConfig,\n type PerformanceGraphsConfig,\n type ReportsConfig,\n type SimulatedScoreConfig,\n} from '../types/modulesConfig';\n\nexport interface UseModulesReturn {\n modules: ModulesConfig;\n loading: boolean;\n\n // Core modules\n hasSimulator: boolean;\n hasEssay: boolean;\n hasForum: boolean;\n hasSupport: boolean;\n hasChat: boolean;\n hasRecommendedLessons: boolean;\n hasActivities: boolean;\n hasQuestionBanks: boolean;\n hasComparator: boolean;\n hasPerformance: boolean;\n hasDashboard: boolean;\n hasLessons: boolean;\n\n // Tutorial menu link (true only when enabled AND tutorialUrl is non-empty)\n hasTutorial: boolean;\n tutorialUrl: string;\n\n // Reading-fluency mode (institution-wide; switches the app to the\n // fluency-only experience). Off by default.\n hasReadingFluency: boolean;\n\n // Exams\n hasExams: boolean;\n\n // Simulations\n hasSimulations: boolean;\n simulations: SimulationsConfig;\n\n // Performance graphs\n hasPerformanceAulas: boolean;\n hasPerformanceAcessos: boolean;\n hasPerformanceSimulados: boolean;\n hasPerformanceAtividades: boolean;\n hasPerformanceQuestoes: boolean;\n hasPerformanceRanking: boolean;\n performanceGraphs: PerformanceGraphsConfig;\n\n // Reports\n hasSimulatedReports: boolean;\n hasSimulatedGenericReports: boolean;\n hasActivitiesReports: boolean;\n hasQuestionnairesReports: boolean;\n hasLessonsReports: boolean;\n hasEssayReports: boolean;\n reports: ReportsConfig;\n\n // Score types\n hasSimulatedScoreTri: boolean;\n hasSimulatedScoreAbsoluto: boolean;\n simulatedScore: SimulatedScoreConfig;\n}\n\n/**\n * Hook to access modules configuration\n * Provides both the raw modules object and convenience boolean helpers\n *\n * @returns {UseModulesReturn} Modules state with helper properties\n *\n * @example\n * ```tsx\n * const {\n * hasEssay,\n * hasForum,\n * hasSupport,\n * hasSimulator,\n * hasPerformanceAulas,\n * hasExams,\n * } = useModules();\n *\n * return (\n * <>\n * {hasEssay && <EssayMenuItem />}\n * {hasForum && <ForumMenuItem />}\n * {hasPerformanceAulas && <AulasGraph />}\n * </>\n * );\n * ```\n */\nexport const useModules = (): UseModulesReturn => {\n const { modules, loading } = useModulesStore();\n\n // Defensive fallbacks for nested objects - handles older persisted state\n const simulations = modules.simulations ?? DEFAULT_SIMULATIONS;\n const performanceGraphs =\n modules.performanceGraphs ?? DEFAULT_PERFORMANCE_GRAPHS;\n const reports = modules.reports ?? DEFAULT_REPORTS;\n const simulatedScore = modules.simulatedScore ?? DEFAULT_SIMULATED_SCORE;\n const tutorialUrl = (modules.tutorialUrl ?? '').trim();\n\n return {\n modules,\n loading,\n\n // Core modules\n hasSimulator: modules.simulator ?? true,\n hasEssay: modules.essay ?? true,\n hasForum: modules.forum ?? true,\n hasSupport: modules.support ?? true,\n hasChat: modules.chat ?? true,\n hasRecommendedLessons: modules.recommendedLessons ?? true,\n hasActivities: modules.activities ?? true,\n hasQuestionBanks: modules.questionBanks ?? true,\n hasComparator: modules.comparator ?? true,\n hasPerformance: modules.performance ?? true,\n hasDashboard: modules.dashboard ?? true,\n hasLessons: modules.lessons ?? true,\n\n // Tutorial: only show the menu link when enabled AND a url is configured\n hasTutorial: (modules.tutorial ?? false) && tutorialUrl.length > 0,\n tutorialUrl,\n\n // Reading-fluency mode (opt-in per institution, defaults off)\n hasReadingFluency: modules.readingFluency ?? false,\n\n // Exams (simple boolean, with backwards compatibility for old object format)\n hasExams:\n typeof modules.exams === 'object'\n ? ((modules.exams as { enabled?: boolean }).enabled ?? true)\n : (modules.exams ?? true),\n\n // Simulations\n hasSimulations: simulations.enabled,\n simulations,\n\n // Performance graphs\n hasPerformanceAulas: performanceGraphs.aulas ?? true,\n hasPerformanceAcessos: performanceGraphs.acessos ?? true,\n hasPerformanceSimulados: performanceGraphs.simulados ?? true,\n hasPerformanceAtividades: performanceGraphs.atividades ?? true,\n hasPerformanceQuestoes: performanceGraphs.questoes ?? true,\n hasPerformanceRanking: performanceGraphs.ranking ?? true,\n performanceGraphs,\n\n // Reports (support both nested and flat for backwards compatibility)\n hasSimulatedReports:\n reports.simulatedReports ?? modules.simulatedReports ?? true,\n hasSimulatedGenericReports:\n reports.simulatedGenericReports ??\n modules.simulatedGenericReports ??\n false,\n hasActivitiesReports:\n reports.activitiesReports ?? modules.activitiesReports ?? true,\n hasQuestionnairesReports:\n reports.questionnairesReports ?? modules.questionnairesReports ?? false,\n hasLessonsReports: reports.lessonsReports ?? modules.lessonsReports ?? true,\n hasEssayReports: reports.essayReports ?? true,\n reports,\n\n // Score types (support both nested and flat for backwards compatibility)\n hasSimulatedScoreTri:\n simulatedScore.tri ?? modules.simulatedScoreTri ?? false,\n hasSimulatedScoreAbsoluto:\n simulatedScore.absoluto ?? modules.simulatedScoreAbsoluto ?? false,\n simulatedScore,\n };\n};\n"],"mappings":"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","names":[]}