analytica-frontend-lib 1.5.76 → 1.5.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/ActivitiesHistory/index.js +6 -6
  2. package/dist/ActivitiesHistory/index.mjs +5 -5
  3. package/dist/ActivityCardQuestionBanks/index.js +6 -6
  4. package/dist/ActivityCardQuestionBanks/index.mjs +5 -5
  5. package/dist/ActivityCardQuestionPreview/index.js +6 -6
  6. package/dist/ActivityCardQuestionPreview/index.mjs +5 -5
  7. package/dist/ActivityCreate/index.js +6 -6
  8. package/dist/ActivityCreate/index.mjs +5 -5
  9. package/dist/ActivityDetails/index.js +6 -6
  10. package/dist/ActivityDetails/index.mjs +5 -5
  11. package/dist/ActivityFilters/index.js +6 -6
  12. package/dist/ActivityFilters/index.mjs +5 -5
  13. package/dist/ActivityPageLayout/index.js +6 -6
  14. package/dist/ActivityPageLayout/index.mjs +5 -5
  15. package/dist/ActivityPreview/index.js +6 -6
  16. package/dist/ActivityPreview/index.mjs +5 -5
  17. package/dist/AlertManager/index.js +6 -6
  18. package/dist/AlertManager/index.mjs +5 -5
  19. package/dist/CheckBoxGroup/index.js +6 -6
  20. package/dist/CheckBoxGroup/index.mjs +5 -5
  21. package/dist/ExamDetailsLayout/ExamDetailsPage/index.js +6 -6
  22. package/dist/ExamDetailsLayout/ExamDetailsPage/index.mjs +5 -5
  23. package/dist/ExamPageLayout/index.js +6 -6
  24. package/dist/ExamPageLayout/index.mjs +5 -5
  25. package/dist/ModuleProtectedRoute/index.js +3 -3
  26. package/dist/ModuleProtectedRoute/index.mjs +2 -2
  27. package/dist/PrintableUsersTable/index.js +6 -6
  28. package/dist/PrintableUsersTable/index.mjs +5 -5
  29. package/dist/RecommendedLessonCreate/index.js +6 -6
  30. package/dist/RecommendedLessonCreate/index.mjs +5 -5
  31. package/dist/RecommendedLessonsHistory/index.js +6 -6
  32. package/dist/RecommendedLessonsHistory/index.mjs +5 -5
  33. package/dist/SendActivityModal/SendActivityModal.d.ts +1 -1
  34. package/dist/SendActivityModal/SendActivityModal.d.ts.map +1 -1
  35. package/dist/SendActivityModal/SendActivityModal.js +6 -6
  36. package/dist/SendActivityModal/SendActivityModal.mjs +5 -5
  37. package/dist/SendActivityModal/hooks/useSendActivityModal.js +1 -1
  38. package/dist/SendActivityModal/hooks/useSendActivityModal.mjs +1 -1
  39. package/dist/SendActivityModal/index.js +6 -6
  40. package/dist/SendActivityModal/index.mjs +5 -5
  41. package/dist/SendActivityModal/types.d.ts +6 -0
  42. package/dist/SendActivityModal/types.d.ts.map +1 -1
  43. package/dist/SendActivityModal/types.js +2 -2
  44. package/dist/SendActivityModal/types.mjs +1 -1
  45. package/dist/SendActivityModal/validation.js +1 -1
  46. package/dist/SendActivityModal/validation.mjs +1 -1
  47. package/dist/SendLessonModal/index.d.ts +1 -1
  48. package/dist/SendLessonModal/index.d.ts.map +1 -1
  49. package/dist/SendLessonModal/index.js +6 -6
  50. package/dist/SendLessonModal/index.mjs +5 -5
  51. package/dist/SimulatedPerformance/SimulatedPerformanceView/index.js +6 -6
  52. package/dist/SimulatedPerformance/SimulatedPerformanceView/index.mjs +5 -5
  53. package/dist/SimulationsPage/index.js +6 -6
  54. package/dist/SimulationsPage/index.mjs +5 -5
  55. package/dist/TableProvider/index.js +6 -6
  56. package/dist/TableProvider/index.mjs +5 -5
  57. package/dist/TypeSelector/index.js +3 -3
  58. package/dist/TypeSelector/index.mjs +2 -2
  59. package/dist/UnifiedDraftModelPage/index.js +6 -6
  60. package/dist/UnifiedDraftModelPage/index.mjs +5 -5
  61. package/dist/UnifiedHistoryPage/index.js +6 -6
  62. package/dist/UnifiedHistoryPage/index.mjs +5 -5
  63. package/dist/{chunk-BRTWWTU3.js → chunk-3BKXXQXP.js} +3 -3
  64. package/dist/{chunk-BRTWWTU3.js.map → chunk-3BKXXQXP.js.map} +1 -1
  65. package/dist/{chunk-NCVAMXYV.mjs → chunk-6PH3QFMW.mjs} +8 -2
  66. package/dist/chunk-6PH3QFMW.mjs.map +1 -0
  67. package/dist/{chunk-5JF47R7V.mjs → chunk-BYHXD3DU.mjs} +2 -2
  68. package/dist/{chunk-T4UIREXS.js → chunk-IT5VCURL.js} +396 -381
  69. package/dist/chunk-IT5VCURL.js.map +1 -0
  70. package/dist/{chunk-VUGO7VUR.js → chunk-KFF223EV.js} +1 -1
  71. package/dist/{chunk-VUGO7VUR.js.map → chunk-KFF223EV.js.map} +1 -1
  72. package/dist/{chunk-Y457NXR3.js → chunk-PJIV7QPK.js} +8 -2
  73. package/dist/chunk-PJIV7QPK.js.map +1 -0
  74. package/dist/{chunk-6EWQZUPA.mjs → chunk-PKH5SHBS.mjs} +2 -2
  75. package/dist/{chunk-LJDMRQIG.js → chunk-QFIPNJ46.js} +3 -3
  76. package/dist/{chunk-LJDMRQIG.js.map → chunk-QFIPNJ46.js.map} +1 -1
  77. package/dist/{chunk-42I5KRYG.mjs → chunk-TCTKQUSW.mjs} +21 -6
  78. package/dist/chunk-TCTKQUSW.mjs.map +1 -0
  79. package/dist/{chunk-GMYYB6A2.mjs → chunk-UI6YZ56K.mjs} +1 -1
  80. package/dist/{chunk-GMYYB6A2.mjs.map → chunk-UI6YZ56K.mjs.map} +1 -1
  81. package/dist/components/SendLessonModal/types.d.ts +6 -0
  82. package/dist/components/SendLessonModal/types.d.ts.map +1 -1
  83. package/dist/components/shared/SendModalBase/components/RecipientStep.d.ts +7 -0
  84. package/dist/components/shared/SendModalBase/components/RecipientStep.d.ts.map +1 -1
  85. package/dist/hooks/useAppContent/index.js +6 -6
  86. package/dist/hooks/useAppContent/index.mjs +5 -5
  87. package/dist/hooks/useModules/index.d.ts +3 -0
  88. package/dist/hooks/useModules/index.d.ts.map +1 -1
  89. package/dist/hooks/useModules/index.js +2 -2
  90. package/dist/hooks/useModules/index.mjs +1 -1
  91. package/dist/hooks/useModules.d.ts +3 -0
  92. package/dist/hooks/useModules.d.ts.map +1 -1
  93. package/dist/hooks/useSendActivity/index.js +1 -1
  94. package/dist/hooks/useSendActivity/index.mjs +1 -1
  95. package/dist/index.js +6 -6
  96. package/dist/index.mjs +5 -5
  97. package/dist/types/modulesConfig.d.ts +6 -0
  98. package/dist/types/modulesConfig.d.ts.map +1 -1
  99. package/package.json +1 -1
  100. package/dist/chunk-42I5KRYG.mjs.map +0 -1
  101. package/dist/chunk-NCVAMXYV.mjs.map +0 -1
  102. package/dist/chunk-T4UIREXS.js.map +0 -1
  103. package/dist/chunk-Y457NXR3.js.map +0 -1
  104. /package/dist/{chunk-5JF47R7V.mjs.map → chunk-BYHXD3DU.mjs.map} +0 -0
  105. /package/dist/{chunk-6EWQZUPA.mjs.map → chunk-PKH5SHBS.mjs.map} +0 -0
@@ -26,4 +26,4 @@ var ACTIVITY_TYPE_OPTIONS = [
26
26
 
27
27
 
28
28
  exports.ActivitySubtype = ActivitySubtype; exports.ActivityMode = ActivityMode; exports.ACTIVITY_MODE_OPTIONS = ACTIVITY_MODE_OPTIONS; exports.ACTIVITY_TYPE_OPTIONS = ACTIVITY_TYPE_OPTIONS;
29
- //# sourceMappingURL=chunk-VUGO7VUR.js.map
29
+ //# sourceMappingURL=chunk-KFF223EV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-VUGO7VUR.js","../src/components/SendActivityModal/types.ts"],"names":["ActivitySubtype","ActivityMode"],"mappings":"AAAA;ACQO,IAAK,gBAAA,kBAAL,CAAA,CAAKA,gBAAAA,EAAAA,GAAL;AACL,EAAAA,gBAAAA,CAAA,QAAA,EAAA,EAAS,QAAA;AACT,EAAAA,gBAAAA,CAAA,UAAA,EAAA,EAAW,UAAA;AACX,EAAAA,gBAAAA,CAAA,OAAA,EAAA,EAAQ,OAAA;AAHE,EAAA,OAAAA,gBAAAA;AAAA,CAAA,CAAA,CAAA,gBAAA,GAAA,CAAA,CAAA,CAAA;AASL,IAAK,aAAA,kBAAL,CAAA,CAAKC,aAAAA,EAAAA,GAAL;AACL,EAAAA,aAAAA,CAAA,QAAA,EAAA,EAAS,QAAA;AACT,EAAAA,aAAAA,CAAA,YAAA,EAAA,EAAa,YAAA;AAFH,EAAA,OAAAA,aAAAA;AAAA,CAAA,CAAA,CAAA,aAAA,GAAA,CAAA,CAAA,CAAA;AAQL,IAAM,sBAAA,EAGR;AAAA,EACH,EAAE,KAAA,EAAO,qBAAA,EAAqB,KAAA,EAAO,SAAS,CAAA;AAAA,EAC9C,EAAE,KAAA,EAAO,6BAAA,EAAyB,KAAA,EAAO,aAAa;AACxD,CAAA;AAKO,IAAM,sBAAA,EAGR;AAAA,EACH,EAAE,KAAA,EAAO,qBAAA,EAAwB,KAAA,EAAO,SAAS,CAAA;AAAA,EACjD,EAAE,KAAA,EAAO,yBAAA,EAA0B,KAAA,EAAO,WAAW,CAAA;AAAA,EACrD,EAAE,KAAA,EAAO,mBAAA,EAAuB,KAAA,EAAO,QAAQ;AACjD,CAAA;ADtBA;AACA;AACE;AACA;AACA;AACA;AACF,6LAAC","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-VUGO7VUR.js","sourcesContent":[null,"import type { CategoryConfig } from '../CheckBoxGroup/CheckBoxGroup';\n\n// Re-export types from CheckboxGroup for easier imports\nexport type { CategoryConfig, Item } from '../CheckBoxGroup/CheckBoxGroup';\n\n/**\n * Activity subtype matching backend SIMULATION_SUBTYPE\n */\nexport enum ActivitySubtype {\n TAREFA = 'TAREFA',\n TRABALHO = 'TRABALHO',\n PROVA = 'PROVA',\n}\n\n/**\n * Activity mode for presencial exams\n */\nexport enum ActivityMode {\n ONLINE = 'ONLINE',\n PRESENCIAL = 'PRESENCIAL',\n}\n\n/**\n * Activity mode options for UI selection\n */\nexport const ACTIVITY_MODE_OPTIONS: ReadonlyArray<{\n value: ActivityMode;\n label: string;\n}> = [\n { value: ActivityMode.ONLINE, label: 'Online' },\n { value: ActivityMode.PRESENCIAL, label: 'Presencial' },\n] as const;\n\n/**\n * Activity type options for UI selection\n */\nexport const ACTIVITY_TYPE_OPTIONS: ReadonlyArray<{\n value: ActivitySubtype;\n label: string;\n}> = [\n { value: ActivitySubtype.TAREFA, label: 'Tarefa' },\n { value: ActivitySubtype.TRABALHO, label: 'Trabalho' },\n { value: ActivitySubtype.PROVA, label: 'Prova' },\n] as const;\n\n/**\n * Form data structure for sending activity\n */\nexport interface SendActivityFormData {\n /** Activity subtype (Step 1) */\n subtype: ActivitySubtype;\n /** Activity mode for presencial exams (Step 1, required when subtype is PROVA and enableExamMode is true) */\n mode?: ActivityMode;\n /** Activity title (Step 1) */\n title: string;\n /** Notification message (Step 1) */\n notification?: string;\n /** Array of students to send activity to (Step 2) */\n students: Array<{\n studentId: string;\n userInstitutionId: string;\n }>;\n /** Start date in YYYY-MM-DD format (Step 3) */\n startDate: string;\n /** Start time in HH:MM format (Step 3) */\n startTime: string;\n /** End date in YYYY-MM-DD format (Step 3) */\n finalDate: string;\n /** End time in HH:MM format (Step 3) */\n finalTime: string;\n /** Allow retry flag (Step 3) */\n canRetry: boolean;\n}\n\n/**\n * Initial data for pre-filling the modal form\n */\nexport interface SendActivityModalInitialData {\n /** Pre-filled activity title */\n title?: string;\n /** Pre-filled activity subtype */\n subtype?: ActivitySubtype;\n /** Pre-filled notification message */\n notification?: string;\n}\n\n/**\n * Modal props\n */\nexport interface SendActivityModalProps {\n /** Controls modal visibility */\n isOpen: boolean;\n /** Callback when modal is closed */\n onClose: () => void;\n /** Callback when activity is submitted */\n onSubmit: (data: SendActivityFormData) => Promise<void>;\n /** Recipient categories configuration (same format as CheckboxGroup) */\n categories: CategoryConfig[];\n /** Callback when categories change (optional - for controlled state) */\n onCategoriesChange?: (categories: CategoryConfig[]) => void;\n /** Loading state for submit button */\n isLoading?: boolean;\n /** Callback when submission fails (optional - if not provided, error propagates) */\n onError?: (error: unknown) => void;\n /** Initial data to pre-fill the form */\n initialData?: SendActivityModalInitialData;\n /** Enable \"Modo de prova\" field (Online/Presencial), required when subtype is PROVA */\n enableExamMode?: boolean;\n /** Force in-person exam mode: auto-selects PROVA subtype and PRESENCIAL mode */\n isInPersonExam?: boolean;\n}\n\n/**\n * Step validation errors\n */\nexport interface StepErrors {\n subtype?: string;\n mode?: string;\n title?: string;\n students?: string;\n startDate?: string;\n startTime?: string;\n finalDate?: string;\n finalTime?: string;\n}\n\n/**\n * Step state for stepper\n */\nexport type StepState = 'pending' | 'current' | 'completed';\n\n/**\n * Step configuration\n */\nexport interface StepConfig {\n label: string;\n state: StepState;\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-KFF223EV.js","../src/components/SendActivityModal/types.ts"],"names":["ActivitySubtype","ActivityMode"],"mappings":"AAAA;ACQO,IAAK,gBAAA,kBAAL,CAAA,CAAKA,gBAAAA,EAAAA,GAAL;AACL,EAAAA,gBAAAA,CAAA,QAAA,EAAA,EAAS,QAAA;AACT,EAAAA,gBAAAA,CAAA,UAAA,EAAA,EAAW,UAAA;AACX,EAAAA,gBAAAA,CAAA,OAAA,EAAA,EAAQ,OAAA;AAHE,EAAA,OAAAA,gBAAAA;AAAA,CAAA,CAAA,CAAA,gBAAA,GAAA,CAAA,CAAA,CAAA;AASL,IAAK,aAAA,kBAAL,CAAA,CAAKC,aAAAA,EAAAA,GAAL;AACL,EAAAA,aAAAA,CAAA,QAAA,EAAA,EAAS,QAAA;AACT,EAAAA,aAAAA,CAAA,YAAA,EAAA,EAAa,YAAA;AAFH,EAAA,OAAAA,aAAAA;AAAA,CAAA,CAAA,CAAA,aAAA,GAAA,CAAA,CAAA,CAAA;AAQL,IAAM,sBAAA,EAGR;AAAA,EACH,EAAE,KAAA,EAAO,qBAAA,EAAqB,KAAA,EAAO,SAAS,CAAA;AAAA,EAC9C,EAAE,KAAA,EAAO,6BAAA,EAAyB,KAAA,EAAO,aAAa;AACxD,CAAA;AAKO,IAAM,sBAAA,EAGR;AAAA,EACH,EAAE,KAAA,EAAO,qBAAA,EAAwB,KAAA,EAAO,SAAS,CAAA;AAAA,EACjD,EAAE,KAAA,EAAO,yBAAA,EAA0B,KAAA,EAAO,WAAW,CAAA;AAAA,EACrD,EAAE,KAAA,EAAO,mBAAA,EAAuB,KAAA,EAAO,QAAQ;AACjD,CAAA;ADtBA;AACA;AACE;AACA;AACA;AACA;AACF,6LAAC","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-KFF223EV.js","sourcesContent":[null,"import type { CategoryConfig } from '../CheckBoxGroup/CheckBoxGroup';\n\n// Re-export types from CheckboxGroup for easier imports\nexport type { CategoryConfig, Item } from '../CheckBoxGroup/CheckBoxGroup';\n\n/**\n * Activity subtype matching backend SIMULATION_SUBTYPE\n */\nexport enum ActivitySubtype {\n TAREFA = 'TAREFA',\n TRABALHO = 'TRABALHO',\n PROVA = 'PROVA',\n}\n\n/**\n * Activity mode for presencial exams\n */\nexport enum ActivityMode {\n ONLINE = 'ONLINE',\n PRESENCIAL = 'PRESENCIAL',\n}\n\n/**\n * Activity mode options for UI selection\n */\nexport const ACTIVITY_MODE_OPTIONS: ReadonlyArray<{\n value: ActivityMode;\n label: string;\n}> = [\n { value: ActivityMode.ONLINE, label: 'Online' },\n { value: ActivityMode.PRESENCIAL, label: 'Presencial' },\n] as const;\n\n/**\n * Activity type options for UI selection\n */\nexport const ACTIVITY_TYPE_OPTIONS: ReadonlyArray<{\n value: ActivitySubtype;\n label: string;\n}> = [\n { value: ActivitySubtype.TAREFA, label: 'Tarefa' },\n { value: ActivitySubtype.TRABALHO, label: 'Trabalho' },\n { value: ActivitySubtype.PROVA, label: 'Prova' },\n] as const;\n\n/**\n * Form data structure for sending activity\n */\nexport interface SendActivityFormData {\n /** Activity subtype (Step 1) */\n subtype: ActivitySubtype;\n /** Activity mode for presencial exams (Step 1, required when subtype is PROVA and enableExamMode is true) */\n mode?: ActivityMode;\n /** Activity title (Step 1) */\n title: string;\n /** Notification message (Step 1) */\n notification?: string;\n /** Array of students to send activity to (Step 2) */\n students: Array<{\n studentId: string;\n userInstitutionId: string;\n }>;\n /** Start date in YYYY-MM-DD format (Step 3) */\n startDate: string;\n /** Start time in HH:MM format (Step 3) */\n startTime: string;\n /** End date in YYYY-MM-DD format (Step 3) */\n finalDate: string;\n /** End time in HH:MM format (Step 3) */\n finalTime: string;\n /** Allow retry flag (Step 3) */\n canRetry: boolean;\n}\n\n/**\n * Initial data for pre-filling the modal form\n */\nexport interface SendActivityModalInitialData {\n /** Pre-filled activity title */\n title?: string;\n /** Pre-filled activity subtype */\n subtype?: ActivitySubtype;\n /** Pre-filled notification message */\n notification?: string;\n}\n\n/**\n * Modal props\n */\nexport interface SendActivityModalProps {\n /** Controls modal visibility */\n isOpen: boolean;\n /** Callback when modal is closed */\n onClose: () => void;\n /** Callback when activity is submitted */\n onSubmit: (data: SendActivityFormData) => Promise<void>;\n /** Recipient categories configuration (same format as CheckboxGroup) */\n categories: CategoryConfig[];\n /** Callback when categories change (optional - for controlled state) */\n onCategoriesChange?: (categories: CategoryConfig[]) => void;\n /** Loading state for submit button */\n isLoading?: boolean;\n /** Callback when submission fails (optional - if not provided, error propagates) */\n onError?: (error: unknown) => void;\n /** Initial data to pre-fill the form */\n initialData?: SendActivityModalInitialData;\n /** Enable \"Modo de prova\" field (Online/Presencial), required when subtype is PROVA */\n enableExamMode?: boolean;\n /** Force in-person exam mode: auto-selects PROVA subtype and PRESENCIAL mode */\n isInPersonExam?: boolean;\n /**\n * Aviso por instituição exibido no passo Destinatário (ex.: estudantes\n * matriculados em mais de uma turma). O texto chega pronto do app, que o lê\n * de uma feature flag — vazio/ausente => nenhum alerta é renderizado.\n */\n recipientWarning?: string;\n}\n\n/**\n * Step validation errors\n */\nexport interface StepErrors {\n subtype?: string;\n mode?: string;\n title?: string;\n students?: string;\n startDate?: string;\n startTime?: string;\n finalDate?: string;\n finalTime?: string;\n}\n\n/**\n * Step state for stepper\n */\nexport type StepState = 'pending' | 'current' | 'completed';\n\n/**\n * Step configuration\n */\nexport interface StepConfig {\n label: string;\n state: StepState;\n}\n"]}
@@ -7,12 +7,14 @@ var _zustand = require('zustand');
7
7
  var _middleware = require('zustand/middleware');
8
8
 
9
9
  // src/types/modulesConfig.ts
10
+ var DEFAULT_PROVA_QUESTIONS = 10;
10
11
  var DEFAULT_SIMULATIONS = {
11
12
  enabled: true,
12
13
  enem: "ENABLED",
13
14
  prova: "ENABLED",
14
15
  simuladao: "ENABLED",
15
- vestibular: "ENABLED"
16
+ vestibular: "ENABLED",
17
+ provaQuestions: DEFAULT_PROVA_QUESTIONS
16
18
  };
17
19
  var DEFAULT_EXAMS = true;
18
20
  var DEFAULT_PERFORMANCE_GRAPHS = {
@@ -312,6 +314,10 @@ var useModules = () => {
312
314
  // Simulations
313
315
  hasSimulations: simulations.enabled,
314
316
  simulations,
317
+ // Number of questions a generated PROVA has. Anything that is not a
318
+ // positive integer (unset, blank from the backoffice form) reads as the
319
+ // default 10 — mirrors `resolveProvaQuestionsQuantity` on the backend.
320
+ provaQuestions: Number.isInteger(simulations.provaQuestions) && simulations.provaQuestions > 0 ? simulations.provaQuestions : DEFAULT_PROVA_QUESTIONS,
315
321
  // Performance graphs
316
322
  hasPerformanceAulas: _nullishCoalesce(performanceGraphs.aulas, () => ( true)),
317
323
  hasPerformanceAcessos: _nullishCoalesce(performanceGraphs.acessos, () => ( true)),
@@ -346,4 +352,4 @@ var useModules = () => {
346
352
 
347
353
 
348
354
  exports.DEFAULT_SIMULATIONS = DEFAULT_SIMULATIONS; exports.DEFAULT_EXAMS = DEFAULT_EXAMS; exports.DEFAULT_PERFORMANCE_GRAPHS = DEFAULT_PERFORMANCE_GRAPHS; exports.DEFAULT_REPORTS = DEFAULT_REPORTS; exports.DEFAULT_SIMULATED_SCORE = DEFAULT_SIMULATED_SCORE; exports.DEFAULT_MODULES = DEFAULT_MODULES; exports.mergeModulesConfig = mergeModulesConfig; exports.useModulesStore = useModulesStore; exports.useModules = useModules;
349
- //# sourceMappingURL=chunk-Y457NXR3.js.map
355
+ //# sourceMappingURL=chunk-PJIV7QPK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-PJIV7QPK.js","../src/store/modulesStore.ts","../src/types/modulesConfig.ts","../src/hooks/useModules.ts"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-PJIV7QPK.js","sourcesContent":[null,"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 ActivePlan {\n code: string;\n name: string;\n}\n\nexport interface ModulesState {\n modules: ModulesConfig;\n loading: boolean;\n ownerInstitutionId: string | null;\n ownerProfileType: string | null;\n /**\n * Commercial plan the modules came from, or `null` when they came from the\n * institution (every non-B2C tenant) or when nothing has been fetched yet.\n */\n plan: ActivePlan | 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/**\n * API response of `GET /me/modules` — the authenticated, per-user answer.\n */\ninterface MyModulesResponse {\n data: {\n modules: Partial<ModulesConfig>;\n plan: ActivePlan | null;\n } | null;\n}\n\n/**\n * What a fetch attempt produced. `plan` is only ever non-null for a B2C tenant.\n */\ninterface FetchedModules {\n version: Partial<ModulesConfig>;\n plan: ActivePlan | 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 * Run `attempt` with exponential backoff, aborting as soon as a newer request\n * supersedes this one. Returns null when every attempt failed.\n */\nconst withRetry = async <T>(\n requestId: number,\n attemptFn: () => Promise<T>,\n maxRetries: number = MAX_RETRIES\n): Promise<T | null> => {\n for (let attempt = 0; attempt <= maxRetries; 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 const result = await attemptFn();\n\n if (isStaleRequest(requestId)) return null;\n\n return result;\n } catch {\n // Continue to next retry attempt\n }\n }\n\n return null;\n};\n\n/**\n * Whether there is a session whose token the API instance can send.\n *\n * `/me/modules` is authenticated; without a token it would only ever answer 401,\n * so the public per-institution endpoint stays the pre-login path.\n */\nconst hasSession = (): boolean =>\n Boolean(useAuthStore.getState().tokens?.token);\n\n/**\n * Fetch the effective modules of the authenticated user.\n *\n * This is the only call that knows about commercial plans: in a B2C institution\n * it answers with the active plan's modules, and outside B2C it answers with the\n * institution's modules unchanged — which is why it replaces the public endpoint\n * for every product, not just the B2C one.\n */\nconst fetchMyModules = async (\n api: AxiosInstance,\n requestId: number\n): Promise<FetchedModules | null> =>\n withRetry(requestId, async () => {\n const response = await api.get<MyModulesResponse>('/me/modules');\n\n return {\n version: response.data?.data?.modules ?? {},\n plan: response.data?.data?.plan ?? null,\n };\n });\n\n/**\n * Fetch the institution's MODULES feature flag — the anonymous answer.\n *\n * Used before login, and as the fallback when `/me/modules` cannot be reached,\n * so a failure there degrades to the previous behaviour instead of an empty app.\n */\nconst fetchInstitutionModules = async (\n institutionId: string,\n api: AxiosInstance,\n requestId: number,\n profileType?: string,\n maxRetries: number = MAX_RETRIES\n): Promise<FetchedModules | null> =>\n withRetry(\n requestId,\n async () => {\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 return {\n version: response.data?.data?.featureFlags?.version ?? {},\n plan: null,\n };\n },\n maxRetries\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 plan: null,\n\n /**\n * Fetch the modules configuration from the API.\n *\n * Picks the endpoint by session, not by tenant: with a session it asks\n * `/me/modules`, which resolves the commercial plan when the institution is\n * B2C and returns the institution's own modules otherwise. Without a session\n * — the login screen — it falls back to the public per-institution flag.\n * Branching on \"is this tenant B2C?\" instead would leave the authenticated\n * path unexercised everywhere else, so it would rot.\n *\n * Caching is stale-while-revalidate. A cached value is served immediately and\n * still revalidated in the background whenever there is a session, because\n * modules can now change server-side (a plan upgrade) with nothing on the\n * client to signal it — no cache key the client builds can detect that. The\n * background pass deliberately leaves `loading` alone: `ModuleProtectedRoute`\n * renders nothing while loading, so raising it on a warm boot would blank\n * every gated route for the length of a request.\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 const authenticated = hasSession();\n const cached = hasCachedModules(profileType);\n\n // Nothing to revalidate before login: the public flag is the only answer\n // available, and it is what the cache already holds.\n if (cached && !authenticated) return;\n\n const requestId = ++latestRequestId;\n\n if (!cached) {\n set({ loading: true });\n }\n\n const result = authenticated\n ? ((await fetchMyModules(api, requestId)) ??\n // Degrade to the previous behaviour rather than to an empty app when\n // the authenticated call cannot be reached — but with a single attempt.\n // The retries belong to `/me/modules`, which is the call that gives the\n // right answer; spending a second full backoff cycle here would double\n // the time gated routes stay blank, and `ModuleProtectedRoute` renders\n // nothing while `loading`. If the authenticated call is simply absent,\n // one request settles it; if the network is down, repeating it is waste.\n (await fetchInstitutionModules(\n institutionId,\n api,\n requestId,\n profileType,\n 0\n )))\n : await fetchInstitutionModules(\n institutionId,\n api,\n requestId,\n profileType\n );\n\n if (isStaleRequest(requestId)) return;\n\n if (result === null) {\n console.warn('[modulesStore] Failed to fetch modules after retries');\n // Keep whatever is already cached; only a cold start falls back to the\n // permissive defaults, which is the pre-existing behaviour.\n set(\n cached\n ? { loading: false }\n : { modules: defaultModules, loading: false }\n );\n return;\n }\n\n set({\n modules: mergeModulesConfig(result.version),\n plan: result.plan,\n ownerInstitutionId: institutionId,\n ownerProfileType: profileType ?? null,\n loading: false,\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 plan: 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 plan: state.plan,\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 * How many questions a PROVA is generated with. Configuration, not\n * visibility — an institution that leaves it unset keeps the default 10.\n */\n provaQuestions: number;\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_PROVA_QUESTIONS = 10;\n\nexport const DEFAULT_SIMULATIONS: SimulationsConfig = {\n enabled: true,\n enem: 'ENABLED',\n prova: 'ENABLED',\n simuladao: 'ENABLED',\n vestibular: 'ENABLED',\n provaQuestions: DEFAULT_PROVA_QUESTIONS,\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 /**\n * Printed kits — an entitlement of the top commercial plan, with no screen of\n * its own yet. Unlike every other key it defaults to `false`: it is granted by\n * a plan, never inherited from a permissive institution default.\n */\n printedKits: 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 // Granted by a commercial plan only — see the interface\n printedKits: false,\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_PROVA_QUESTIONS,\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 /** Printed kits: granted by a commercial plan, so it defaults to false. */\n hasPrintedKits: 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 /** Whether the Simulados module is enabled (master toggle). */\n hasSimulations: boolean;\n /** How many questions a generated PROVA has (default 10). */\n provaQuestions: number;\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 // Not `?? true`: this one is only ever granted, never inherited.\n hasPrintedKits: modules.printedKits ?? false,\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 // Number of questions a generated PROVA has. Anything that is not a\n // positive integer (unset, blank from the backoffice form) reads as the\n // default 10 — mirrors `resolveProvaQuestionsQuantity` on the backend.\n provaQuestions:\n Number.isInteger(simulations.provaQuestions) &&\n simulations.provaQuestions > 0\n ? simulations.provaQuestions\n : DEFAULT_PROVA_QUESTIONS,\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"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useModules
3
- } from "./chunk-NCVAMXYV.mjs";
3
+ } from "./chunk-6PH3QFMW.mjs";
4
4
 
5
5
  // src/components/ModuleProtectedRoute.tsx
6
6
  import { Navigate } from "react-router-dom";
@@ -25,4 +25,4 @@ var ModuleProtectedRoute = ({
25
25
  export {
26
26
  ModuleProtectedRoute
27
27
  };
28
- //# sourceMappingURL=chunk-6EWQZUPA.mjs.map
28
+ //# sourceMappingURL=chunk-PKH5SHBS.mjs.map
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
2
 
3
- var _chunkY457NXR3js = require('./chunk-Y457NXR3.js');
3
+ var _chunkPJIV7QPKjs = require('./chunk-PJIV7QPK.js');
4
4
 
5
5
  // src/components/ModuleProtectedRoute.tsx
6
6
  var _reactrouterdom = require('react-router-dom');
@@ -11,7 +11,7 @@ var ModuleProtectedRoute = ({
11
11
  children,
12
12
  redirectTo = "/painel"
13
13
  }) => {
14
- const { modules, loading } = _chunkY457NXR3js.useModules.call(void 0, );
14
+ const { modules, loading } = _chunkPJIV7QPKjs.useModules.call(void 0, );
15
15
  if (loading) {
16
16
  return null;
17
17
  }
@@ -25,4 +25,4 @@ var ModuleProtectedRoute = ({
25
25
 
26
26
 
27
27
  exports.ModuleProtectedRoute = ModuleProtectedRoute;
28
- //# sourceMappingURL=chunk-LJDMRQIG.js.map
28
+ //# sourceMappingURL=chunk-QFIPNJ46.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-LJDMRQIG.js","../src/components/ModuleProtectedRoute.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACHA,kDAAyB;AAgEd,+CAAA;AAnBJ,IAAM,qBAAA,EAAuB,CAAC;AAAA,EACnC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,EAAa;AACf,CAAA,EAAA,GAAiC;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAS,QAAQ,EAAA,EAAI,yCAAA,CAAW;AAGxC,EAAA,GAAA,CAAI,OAAA,EAAS;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AAIA,EAAA,MAAM,UAAA,mBAAY,OAAA,UAAA,CAAY,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAC,EAAA,EAAI,KAAA,GAAA;AAGlE,EAAA,GAAA,CAAI,CAAC,SAAA,EAAW;AACd,IAAA,uBAAO,6BAAA,wBAAC,EAAA,EAAS,EAAA,EAAI,UAAA,EAAY,OAAA,EAAO,KAAA,CAAC,CAAA;AAAA,EAC3C;AAEA,EAAA,uBAAO,6BAAA,oBAAA,EAAA,EAAG,SAAA,CAAS,CAAA;AACrB,CAAA;AD9CA;AACA;AACE;AACF,oDAAC","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-LJDMRQIG.js","sourcesContent":[null,"import React from 'react';\nimport { Navigate } from 'react-router-dom';\nimport { useModules } from '../hooks/useModules';\nimport type { ModulesConfig } from '../types/modulesConfig';\n\ntype ModuleKey = keyof ModulesConfig;\n\n/** Keys of ModulesConfig whose value is a boolean (i.e. gateable modules). */\ntype BooleanModuleKey = {\n [K in ModuleKey]: ModulesConfig[K] extends boolean ? K : never;\n}[ModuleKey];\n\ninterface BaseModuleProtectedRouteProps {\n children: React.ReactNode;\n redirectTo?: string;\n}\n\n/**\n * Gate on a boolean module key (`module`) OR on an explicit `enabled` flag\n * (for derived/nested gates such as the Simulados master, `simulations.enabled`).\n * At least one of the two is required, so a route can never be left ungated.\n */\nexport type ModuleProtectedRouteProps = BaseModuleProtectedRouteProps &\n (\n | { module: BooleanModuleKey; enabled?: boolean }\n | { module?: BooleanModuleKey; enabled: boolean }\n );\n\n/**\n * Route guard component that redirects if the specified module is disabled\n * Use this component to wrap routes that should only be accessible when the module is enabled\n *\n * @example\n * <Route path=\"simulador-sisu\" element={\n * <ModuleProtectedRoute module=\"simulator\">\n * <SimuladorSisu />\n * </ModuleProtectedRoute>\n * } />\n *\n * @example\n * <Route path=\"simulados\" element={\n * <ModuleProtectedRoute enabled={hasSimulations}>\n * <Simulados />\n * </ModuleProtectedRoute>\n * } />\n */\nexport const ModuleProtectedRoute = ({\n module,\n enabled,\n children,\n redirectTo = '/painel',\n}: ModuleProtectedRouteProps) => {\n const { modules, loading } = useModules();\n\n // While loading, render nothing to prevent flash of content\n if (loading) {\n return null;\n }\n\n // `enabled` wins when provided; otherwise gate on the boolean module key.\n // Fail closed when neither is supplied (the types prevent this, defensive).\n const isEnabled = enabled ?? (module ? Boolean(modules[module]) : false);\n\n // If disabled, redirect\n if (!isEnabled) {\n return <Navigate to={redirectTo} replace />;\n }\n\n return <>{children}</>;\n};\n"]}
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-QFIPNJ46.js","../src/components/ModuleProtectedRoute.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACHA,kDAAyB;AAgEd,+CAAA;AAnBJ,IAAM,qBAAA,EAAuB,CAAC;AAAA,EACnC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,EAAa;AACf,CAAA,EAAA,GAAiC;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAS,QAAQ,EAAA,EAAI,yCAAA,CAAW;AAGxC,EAAA,GAAA,CAAI,OAAA,EAAS;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AAIA,EAAA,MAAM,UAAA,mBAAY,OAAA,UAAA,CAAY,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAC,EAAA,EAAI,KAAA,GAAA;AAGlE,EAAA,GAAA,CAAI,CAAC,SAAA,EAAW;AACd,IAAA,uBAAO,6BAAA,wBAAC,EAAA,EAAS,EAAA,EAAI,UAAA,EAAY,OAAA,EAAO,KAAA,CAAC,CAAA;AAAA,EAC3C;AAEA,EAAA,uBAAO,6BAAA,oBAAA,EAAA,EAAG,SAAA,CAAS,CAAA;AACrB,CAAA;AD9CA;AACA;AACE;AACF,oDAAC","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-QFIPNJ46.js","sourcesContent":[null,"import React from 'react';\nimport { Navigate } from 'react-router-dom';\nimport { useModules } from '../hooks/useModules';\nimport type { ModulesConfig } from '../types/modulesConfig';\n\ntype ModuleKey = keyof ModulesConfig;\n\n/** Keys of ModulesConfig whose value is a boolean (i.e. gateable modules). */\ntype BooleanModuleKey = {\n [K in ModuleKey]: ModulesConfig[K] extends boolean ? K : never;\n}[ModuleKey];\n\ninterface BaseModuleProtectedRouteProps {\n children: React.ReactNode;\n redirectTo?: string;\n}\n\n/**\n * Gate on a boolean module key (`module`) OR on an explicit `enabled` flag\n * (for derived/nested gates such as the Simulados master, `simulations.enabled`).\n * At least one of the two is required, so a route can never be left ungated.\n */\nexport type ModuleProtectedRouteProps = BaseModuleProtectedRouteProps &\n (\n | { module: BooleanModuleKey; enabled?: boolean }\n | { module?: BooleanModuleKey; enabled: boolean }\n );\n\n/**\n * Route guard component that redirects if the specified module is disabled\n * Use this component to wrap routes that should only be accessible when the module is enabled\n *\n * @example\n * <Route path=\"simulador-sisu\" element={\n * <ModuleProtectedRoute module=\"simulator\">\n * <SimuladorSisu />\n * </ModuleProtectedRoute>\n * } />\n *\n * @example\n * <Route path=\"simulados\" element={\n * <ModuleProtectedRoute enabled={hasSimulations}>\n * <Simulados />\n * </ModuleProtectedRoute>\n * } />\n */\nexport const ModuleProtectedRoute = ({\n module,\n enabled,\n children,\n redirectTo = '/painel',\n}: ModuleProtectedRouteProps) => {\n const { modules, loading } = useModules();\n\n // While loading, render nothing to prevent flash of content\n if (loading) {\n return null;\n }\n\n // `enabled` wins when provided; otherwise gate on the boolean module key.\n // Fail closed when neither is supplied (the types prevent this, defensive).\n const isEnabled = enabled ?? (module ? Boolean(modules[module]) : false);\n\n // If disabled, redirect\n if (!isEnabled) {\n return <Navigate to={redirectTo} replace />;\n }\n\n return <>{children}</>;\n};\n"]}
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-GZN7FRHZ.mjs";
21
21
  import {
22
22
  TypeSelector_default
23
- } from "./chunk-5JF47R7V.mjs";
23
+ } from "./chunk-BYHXD3DU.mjs";
24
24
  import {
25
25
  createActivityCategoryConfig
26
26
  } from "./chunk-VAESYCAF.mjs";
@@ -40,7 +40,7 @@ import {
40
40
  } from "./chunk-P5GVODR2.mjs";
41
41
  import {
42
42
  useModulesStore
43
- } from "./chunk-NCVAMXYV.mjs";
43
+ } from "./chunk-6PH3QFMW.mjs";
44
44
  import {
45
45
  AnswerSheetCard,
46
46
  CardContainer,
@@ -114,7 +114,7 @@ import {
114
114
  ACTIVITY_MODE_OPTIONS,
115
115
  ACTIVITY_TYPE_OPTIONS,
116
116
  ActivitySubtype
117
- } from "./chunk-GMYYB6A2.mjs";
117
+ } from "./chunk-UI6YZ56K.mjs";
118
118
  import {
119
119
  Toaster_default,
120
120
  useToast
@@ -837,6 +837,7 @@ var RecipientStep = ({
837
837
  categories,
838
838
  onCategoriesChange,
839
839
  entityNameWithArticle,
840
+ warningMessage,
840
841
  studentsError,
841
842
  testIdPrefix
842
843
  }) => {
@@ -866,6 +867,16 @@ var RecipientStep = ({
866
867
  ]
867
868
  }
868
869
  ),
870
+ warningMessage?.trim() && /* @__PURE__ */ jsx6(
871
+ Alert_default,
872
+ {
873
+ variant: "solid",
874
+ action: "warning",
875
+ description: warningMessage,
876
+ className: "w-full flex-shrink-0",
877
+ "data-testid": testIdPrefix ? `${testIdPrefix}-recipient-warning` : void 0
878
+ }
879
+ ),
869
880
  /* @__PURE__ */ jsx6(
870
881
  "div",
871
882
  {
@@ -14124,7 +14135,8 @@ var SendActivityModal = ({
14124
14135
  onError,
14125
14136
  initialData,
14126
14137
  enableExamMode = false,
14127
- isInPersonExam = false
14138
+ isInPersonExam = false,
14139
+ recipientWarning
14128
14140
  }) => {
14129
14141
  const store = useSendActivityModalStore();
14130
14142
  const reset = useSendActivityModalStore((state) => state.reset);
@@ -14427,6 +14439,7 @@ var SendActivityModal = ({
14427
14439
  categories: categoriesToRender,
14428
14440
  onCategoriesChange: handleCategoriesChange,
14429
14441
  entityNameWithArticle,
14442
+ warningMessage: recipientWarning,
14430
14443
  studentsError: store.errors.students
14431
14444
  }
14432
14445
  );
@@ -14732,7 +14745,8 @@ var SendLessonModal = ({
14732
14745
  isLoading = false,
14733
14746
  onError,
14734
14747
  modalTitle: modalTitleProp,
14735
- hasAttachedActivities = false
14748
+ hasAttachedActivities = false,
14749
+ recipientWarning
14736
14750
  }) => {
14737
14751
  const store = useSendLessonModalStore();
14738
14752
  const reset = useSendLessonModalStore((state) => state.reset);
@@ -14883,6 +14897,7 @@ var SendLessonModal = ({
14883
14897
  categories: categoriesToRender,
14884
14898
  onCategoriesChange: handleCategoriesChange,
14885
14899
  entityNameWithArticle: ENTITY_NAME_WITH_ARTICLE,
14900
+ warningMessage: recipientWarning,
14886
14901
  studentsError: store.errors.students
14887
14902
  }
14888
14903
  );
@@ -21111,4 +21126,4 @@ export {
21111
21126
  ExamDetailsPage,
21112
21127
  ExamDetailsPage_default
21113
21128
  };
21114
- //# sourceMappingURL=chunk-42I5KRYG.mjs.map
21129
+ //# sourceMappingURL=chunk-TCTKQUSW.mjs.map