UNPKG

analytica-frontend-lib

Version:

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

292 lines (287 loc) 10.5 kB
import { useAuthStore } from "./chunk-TNOKCEMB.mjs"; // src/store/modulesStore.ts import { create } from "zustand"; import { createJSONStorage, persist } from "zustand/middleware"; // src/types/modulesConfig.ts var DEFAULT_SIMULATIONS = { enabled: true, enem: "ENABLED", prova: "ENABLED", simuladao: "ENABLED", vestibular: "ENABLED" }; var DEFAULT_EXAMS = true; var DEFAULT_PERFORMANCE_GRAPHS = { aulas: true, acessos: true, simulados: true, atividades: true, questoes: true, ranking: true }; var DEFAULT_REPORTS = { simulatedReports: true, simulatedGenericReports: false, // New reports default to disabled activitiesReports: true, questionnairesReports: false, // New reports default to disabled lessonsReports: true, essayReports: true }; var DEFAULT_SIMULATED_SCORE = { tri: true, absoluto: true }; var DEFAULT_MODULES = { // Core modules simulator: true, essay: true, forum: true, support: true, chat: true, recommendedLessons: true, activities: true, questionBanks: true, comparator: true, performance: true, dashboard: true, lessons: true, // Tutorial off by default (opt-in per institution, requires a url) tutorial: false, tutorialUrl: "", // Reading-fluency mode off by default (opt-in per institution) readingFluency: false, // Nested configurations exams: DEFAULT_EXAMS, simulations: DEFAULT_SIMULATIONS, performanceGraphs: DEFAULT_PERFORMANCE_GRAPHS, reports: DEFAULT_REPORTS, simulatedScore: DEFAULT_SIMULATED_SCORE, // Legacy flat fields (for backwards compatibility) simulatedReports: true, simulatedGenericReports: false, activitiesReports: true, questionnairesReports: false, lessonsReports: true, essayReports: true, simulatedScoreTri: true, simulatedScoreAbsoluto: true }; var mergeModulesConfig = (version) => { const v = version ?? {}; return { ...DEFAULT_MODULES, ...v, // exams is now a simple boolean, use default if not provided exams: v.exams ?? DEFAULT_EXAMS, simulations: { ...DEFAULT_SIMULATIONS, ...v.simulations }, performanceGraphs: { ...DEFAULT_PERFORMANCE_GRAPHS, ...v.performanceGraphs }, reports: { ...DEFAULT_REPORTS, ...v.reports }, simulatedScore: { ...DEFAULT_SIMULATED_SCORE, ...v.simulatedScore } }; }; // src/store/modulesStore.ts var defaultModules = DEFAULT_MODULES; var latestRequestId = 0; var MAX_RETRIES = 3; var INITIAL_RETRY_DELAY = 1e3; var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); var readLocalStorage = (key) => { try { return localStorage.getItem(key); } catch { return null; } }; var hasCachedModules = (profileType) => { const cached = readLocalStorage("@modules-storage:analytica:v1" /* MODULES_STORAGE */); if (!cached) return false; try { const parsed = JSON.parse(cached); const hasInstitution = Boolean(parsed.state?.ownerInstitutionId); const profileMatches = !profileType || parsed.state?.ownerProfileType === profileType; return hasInstitution && profileMatches; } catch { return false; } }; var isStaleRequest = (requestId) => requestId !== latestRequestId; var fetchWithRetry = async (institutionId, api, requestId, profileType) => { for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { if (attempt > 0) { await delay(INITIAL_RETRY_DELAY * Math.pow(2, attempt - 1)); } if (isStaleRequest(requestId)) return null; try { const endpoint = profileType ? `/featureFlags/institution/${institutionId}/page/MODULES/profile/${profileType}` : `/featureFlags/institution/${institutionId}/page/MODULES`; const response = await api.get(endpoint); if (isStaleRequest(requestId)) return null; return response.data?.data?.featureFlags?.version ?? {}; } catch { } } console.warn("[modulesStore] Failed to fetch modules after retries"); return null; }; var useModulesStore = create()( persist( (set) => ({ modules: defaultModules, loading: false, ownerInstitutionId: null, ownerProfileType: null, /** * Fetch modules configuration from the API * Only fetches if: * 1. No modules data exists in localStorage for this profile * 2. User made a new login (data cleared by auth subscriber) * Implements retry with exponential backoff on failure * * @param institutionId - The institution UUID * @param api - Axios instance for API calls * @param profileType - Optional profile type (STUDENT, TEACHER, etc.) */ fetchModules: async (institutionId, api, profileType) => { if (hasCachedModules(profileType)) return; const requestId = ++latestRequestId; set({ loading: true }); const version = await fetchWithRetry( institutionId, api, requestId, profileType ); if (isStaleRequest(requestId)) return; if (version === null) { set({ modules: defaultModules, loading: false }); } else { set({ modules: mergeModulesConfig(version), ownerInstitutionId: institutionId, ownerProfileType: profileType ?? null, loading: false }); } }, /** * Clear modules data (useful when user/institution/profile changes) * Also invalidates any in-flight requests to prevent stale data overwriting cleared state */ clearModules: () => { latestRequestId++; set({ modules: defaultModules, loading: false, ownerInstitutionId: null, ownerProfileType: null }); } }), { name: "@modules-storage:analytica:v1" /* MODULES_STORAGE */, storage: createJSONStorage(() => localStorage), partialize: (state) => ({ modules: state.modules, ownerInstitutionId: state.ownerInstitutionId, ownerProfileType: state.ownerProfileType }), onRehydrateStorage: () => (rehydrated) => { if (!rehydrated) return; const mergedModules = mergeModulesConfig(rehydrated.modules); useModulesStore.setState({ modules: mergedModules }); const currentInstitutionId = useAuthStore.getState().sessionInfo?.institutionId ?? null; const currentProfile = useAuthStore.getState().sessionInfo?.profileName ?? null; if (rehydrated.ownerInstitutionId && rehydrated.ownerInstitutionId !== currentInstitutionId || rehydrated.ownerProfileType && rehydrated.ownerProfileType !== currentProfile) { useModulesStore.getState().clearModules(); } } } ) ); var lastInstitutionId = useAuthStore.getState().sessionInfo?.institutionId ?? null; var lastProfileType = useAuthStore.getState().sessionInfo?.profileName ?? null; useAuthStore.subscribe((state) => { const nextInstitutionId = state.sessionInfo?.institutionId ?? null; const nextProfileType = state.sessionInfo?.profileName ?? null; if (nextInstitutionId !== lastInstitutionId || nextProfileType !== lastProfileType) { if (lastInstitutionId !== null || lastProfileType !== null) { useModulesStore.getState().clearModules(); } lastInstitutionId = nextInstitutionId; lastProfileType = nextProfileType; } }); // src/hooks/useModules.ts var useModules = () => { const { modules, loading } = useModulesStore(); const simulations = modules.simulations ?? DEFAULT_SIMULATIONS; const performanceGraphs = modules.performanceGraphs ?? DEFAULT_PERFORMANCE_GRAPHS; const reports = modules.reports ?? DEFAULT_REPORTS; const simulatedScore = modules.simulatedScore ?? DEFAULT_SIMULATED_SCORE; const tutorialUrl = (modules.tutorialUrl ?? "").trim(); return { modules, loading, // Core modules hasSimulator: modules.simulator ?? true, hasEssay: modules.essay ?? true, hasForum: modules.forum ?? true, hasSupport: modules.support ?? true, hasChat: modules.chat ?? true, hasRecommendedLessons: modules.recommendedLessons ?? true, hasActivities: modules.activities ?? true, hasQuestionBanks: modules.questionBanks ?? true, hasComparator: modules.comparator ?? true, hasPerformance: modules.performance ?? true, hasDashboard: modules.dashboard ?? true, hasLessons: modules.lessons ?? true, // Tutorial: only show the menu link when enabled AND a url is configured hasTutorial: (modules.tutorial ?? false) && tutorialUrl.length > 0, tutorialUrl, // Reading-fluency mode (opt-in per institution, defaults off) hasReadingFluency: modules.readingFluency ?? false, // Exams (simple boolean, with backwards compatibility for old object format) hasExams: typeof modules.exams === "object" ? modules.exams.enabled ?? true : modules.exams ?? true, // Simulations hasSimulations: simulations.enabled, simulations, // Performance graphs hasPerformanceAulas: performanceGraphs.aulas ?? true, hasPerformanceAcessos: performanceGraphs.acessos ?? true, hasPerformanceSimulados: performanceGraphs.simulados ?? true, hasPerformanceAtividades: performanceGraphs.atividades ?? true, hasPerformanceQuestoes: performanceGraphs.questoes ?? true, hasPerformanceRanking: performanceGraphs.ranking ?? true, performanceGraphs, // Reports (support both nested and flat for backwards compatibility) hasSimulatedReports: reports.simulatedReports ?? modules.simulatedReports ?? true, hasSimulatedGenericReports: reports.simulatedGenericReports ?? modules.simulatedGenericReports ?? false, hasActivitiesReports: reports.activitiesReports ?? modules.activitiesReports ?? true, hasQuestionnairesReports: reports.questionnairesReports ?? modules.questionnairesReports ?? false, hasLessonsReports: reports.lessonsReports ?? modules.lessonsReports ?? true, hasEssayReports: reports.essayReports ?? true, reports, // Score types (support both nested and flat for backwards compatibility) hasSimulatedScoreTri: simulatedScore.tri ?? modules.simulatedScoreTri ?? false, hasSimulatedScoreAbsoluto: simulatedScore.absoluto ?? modules.simulatedScoreAbsoluto ?? false, simulatedScore }; }; export { DEFAULT_SIMULATIONS, DEFAULT_EXAMS, DEFAULT_PERFORMANCE_GRAPHS, DEFAULT_REPORTS, DEFAULT_SIMULATED_SCORE, DEFAULT_MODULES, mergeModulesConfig, useModulesStore, useModules }; //# sourceMappingURL=chunk-KSJOLTXH.mjs.map