ComuniTEA uses Zustand for all global client-side state. There are no React Context providers to wrap — any component can read or mutate state by calling a hook directly, and any non-React utility (inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ElthonJohan/comunitea/llms.txt
Use this file to discover all available pages before exploring further.
lib/, event handlers, background tasks) can call useXxxStore.getState() to read or .setState() to write. Four of the six stores persist their state to AsyncStorage via Zustand’s persist middleware using custom legacy-compatible storage adapters; the remaining two (useRutinasProgressStore and useVocabularySentenceStore) are in-memory only and reset on app restart.
useSettingsStore
File: stores/settingsStore.tsPersistence:
AsyncStorage key user_voice_preference (via voiceLegacyStorage adapter)
Manages the user’s voice profile selection. The store writes only the raw string 'femenina' or 'masculina' to AsyncStorage (not a Zustand envelope) to maintain compatibility with installations that stored the value directly.
The currently active voice profile. Passed to
getAudioAssets(voice) whenever the app plays pictogram audio. Defaults to 'femenina'.Set to
true by onRehydrateStorage once the store has finished reading from AsyncStorage. Components that depend on voice should gate rendering on hydrated to avoid a flash of the default value.Updates the active voice and immediately persists the new value to
AsyncStorage under the key user_voice_preference.useG2ProgressStore
File: stores/g2ProgressStore.tsPersistence:
AsyncStorage key comunitea_ejercicios_g2 (via g2LegacyStorage adapter)
Tracks all progress for the Grupo 2 exercise path — emotions recognition, help-seeking situations, star ratings per exercise and per sub-exercise, and auxiliary registers used by the progress reports.
State Shape
Actions & Selectors
| Method | Signature | Description |
|---|---|---|
isExerciseDone | (nivel, ejIndex) => boolean | Returns true if the exercise at (nivel, ejIndex) is in completados. |
isLevelComplete | (nivel) => boolean | true when all G2_EJERCICIOS_POR_NIVEL exercises for a level are done. |
isLevelUnlocked | (nivel) => boolean | Level 1 is always unlocked; higher levels require the previous level to be complete. |
nivelBadgeState | (nivel) => 'bloqueado' | 'disponible' | 'completado' | Drives the badge icon on each level card. |
firstIncompleteIndex | (nivel) => number | Returns the index of the first incomplete exercise — used to resume mid-level. |
registerFail | (nivel, ejIndex) => Promise<void> | Increments the fail counter and fires a gamification event (wrong_attempt). |
registerSubFail | (nivel: 2|3, sub) => Promise<void> | Records a fail against a named sub-exercise slot (E1/E2/E3). |
completeExercise | (nivel, ejIndex) => Promise<void> | Marks an exercise done, calculates level stars on the last exercise, fires exercise_completed. |
completeSubExercise | (nivel: 2|3, sub) => Promise<void> | Completes a named sub-exercise, computes sub-exercise stars, and recalculates level stars when E3 is the last to finish. |
registerEmocion | (emotionId) => Promise<void> | Appends an emotion ID to emocionesRegistradas (capped at 30). |
registerAyudaRegistro | (situacion, persona) => Promise<void> | Appends a help record to ayudasRegistradas (capped at 40). |
estrellasNivel | (nivel) => 0|1|2|3 | Star count for a level; 0 if not yet complete. |
estrellasSubEjercicio | (nivel: 2|3, sub) => 1|2|3|null | Star count for a named sub-exercise; null if not yet rated. |
resetAllProgress | () => void | Resets all G2 state to defaults (useful in the developer settings screen). |
Migration Note
On rehydration, the store automatically runsmigrateG2LegacyThreeSlotsToSix — this backfills exercise slots 4–6 for users who completed a level back when only 3 exercises existed per level, preventing a stuck “Próximamente” state.
Standalone Loaders
Two async helpers read G2 data directly from AsyncStorage without touching the store — useful in background report generation:useG3ProgressStore
File: stores/g3ProgressStore.tsPersistence:
AsyncStorage key comunitea_ejercicios_g3 (via g3LegacyStorage adapter)
Tracks progress for the Grupo 3 exercise path — a linear “camino” (path) of levels, each containing exactly 3 exercises. Stars are awarded per level based on total wrong attempts across its 3 exercises.
State Shape
Actions & Selectors
| Method | Signature | Description |
|---|---|---|
isExerciseDone | (nivel, ejIndex) => boolean | Checks if a specific exercise is complete. |
isLevelComplete | (nivel) => boolean | true when all 3 exercises for the level are done. |
isLevelUnlocked | (nivel) => boolean | Level 1 always unlocked; requires previous level complete otherwise. |
nivelBadgeState | (nivel) => 'bloqueado' | 'disponible' | 'completado' | Drives badge rendering on the path map. |
firstIncompleteIndex | (nivel) => number | First incomplete exercise index (0–2). |
registerFail | (nivel, ejIndex) => Promise<void> | Increments fail counter and fires wrong_attempt gamification event. |
completeExercise | (nivel, ejIndex) => Promise<void> | Marks done; when ejIndex === 2 (last exercise), calculates level stars from total fails. |
setCaminoCompleto | () => Promise<void> | Persists 'true' to STORAGE_KEYS.EJERCICIOS_G3_COMPLETADOS and sets caminoCompleto: true. |
estrellasNivel | (nivel) => 0|1|2|3 | Star count; 0 if level not yet complete. |
segmentBetweenCompleted | (fromNivel, toNivel) => boolean | Used by the path-map UI to decide whether to draw an active connector line between two nodes. |
resetAllProgress | () => Promise<void> | Clears all G3 progress including the EJERCICIOS_G3_COMPLETADOS key. |
useRutinasProgressStore
File: stores/rutinasProgressStore.tsPersistence: None — in-memory only, resets on app restart. Tracks how many steps of each daily routine exercise the child has completed. The store is intentionally lightweight and does not persist — routine completion is a daily activity that starts fresh each session.
Maps a routine exercise ID (e.g.,
'manana', 'colegio', 'noche') to the number of completed steps.Sets (or overwrites) the completed step count for a given routine ID.
useVocabularySentenceStore
File: stores/vocabularySentenceStore.tsPersistence: None — in-memory only. Manages the sentence strip in the vocabulary module — the ordered sequence of
VocabularyItem objects the child is building before pressing “play”. Cleared after each sentence is played or manually dismissed.
The ordered array of vocabulary items currently in the strip. Displayed left-to-right in the sentence bar at the top of the vocabulary screen.
Appends an item to the end of the sentence strip.
Removes the item at the given index (used when the child taps a chip in the strip to deselect it).
Empties the strip (called after playing or after a timeout).
useAppThemeStore
File: stores/appThemeStore.tsPersistence:
AsyncStorage key comunitea-accent-palette (via standard Zustand createJSONStorage)
Controls the global colour palette of the app. The palette is applied to tabs, buttons, and accent surfaces via constants/Colors.ts colour tokens.
The currently active colour palette. Defaults to
'sage'. Changes take effect immediately across all screens through the useAppThemeStore subscription.Updates the palette and persists the selection to AsyncStorage.
Progress Store Re-exports
stores/progressStore.ts is the single barrel export for all exercise-progress stores. Import from here to avoid deep relative paths:
Persistence Summary
| Store | Persisted | AsyncStorage Key | Adapter |
|---|---|---|---|
useSettingsStore | ✅ | user_voice_preference | Custom legacy (raw string) |
useG2ProgressStore | ✅ | comunitea_ejercicios_g2 | Custom legacy (flat JSON) |
useG3ProgressStore | ✅ | comunitea_ejercicios_g3 | Custom legacy (flat JSON) |
useAppThemeStore | ✅ | comunitea-accent-palette | Standard Zustand JSON |
useRutinasProgressStore | ❌ | — | None |
useVocabularySentenceStore | ❌ | — | None |
Accessing Stores Outside React
All Zustand stores expose.getState() and .setState() as static methods on the store hook. This is how the gamification bridge and report loaders read progress data outside the React tree: