analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
292 lines (287 loc) • 10.5 kB
JavaScript
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