Skip to main content

Documentation 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.

ComuniTEA is designed to be used directly by a child, which means the communication board must be as tap-friendly and distraction-free as possible. Left unprotected, configuration screens like the Vocabulary Manager, Activity Editor, or Settings could be accidentally opened and modified by the child mid-session. The parental gate solves this by introducing a two-state model — child mode (locked) and caregiver mode (unlocked) — controlled by a 4-digit PIN modal. Caregivers can freely navigate all configuration screens once the PIN is entered; locking requires only a single toggle and no PIN. The gate is backed by Supabase (parental_settings table) and local AsyncStorage so that preferences survive app restarts.

Edit Mode: Child vs. Caregiver

The EditModeContext (context/EditModeContext.tsx) provides the global edit-mode state. Every part of the app that must be restricted from child interaction reads isEditMode from this context.
interface EditModeContextProps {
    isEditMode: boolean;
    hasPin: boolean;
    /** Show PIN modal and unlock if correct. */
    requestUnlock: () => void;
    /** Unlock directly (use only after identity has already been verified). */
    enterEditMode: () => void;
    /** Lock without PIN. */
    lockEditMode: () => void;
    /** Open the change-PIN flow. */
    changePinRequest: () => void;
}
StateWho has accessDescription
isEditMode: falseChildCommunication board is fully functional; Settings, Vocabulary Manager, Activity Editor, and Team Manager are PIN-gated
isEditMode: trueCaregiverAll configuration screens are accessible; edit handles and delete buttons appear on the board
The useEditMode() hook exposes this context to any component:
import { useEditMode } from '../context/EditModeContext';

const { isEditMode, requestUnlock, lockEditMode } = useEditMode();

PIN Modal (PinModal)

PinModal (components/PinModal.tsx) is a full-screen numeric keypad overlay that supports two modes:
modePurpose
'setup'Create a new 4-digit PIN. The caregiver enters a PIN and then confirms it. If the two entries match, the PIN is saved; if not, the modal shakes and resets.
'verify'Enter an existing 4-digit PIN. The onSuccess callback is called immediately when all 4 digits are entered; the parent context (EditModeContext) is responsible for comparing the entered value to the stored PIN.
The PIN is stored in AsyncStorage under STORAGE_KEYS.PARENTAL_PIN as a plain 4-digit string. On Settings screen load, the app reads this value and shows PinModal in 'verify' mode before rendering the settings content:
useEffect(() => {
    AsyncStorage.getItem(STORAGE_KEYS.PARENTAL_PIN).then(pin => {
        setProfileStoredPin(pin);
        if (pin === null) {
            setPinVerified(true);   // No PIN set yet — grant access
        } else {
            setShowProfilePin(true); // PIN exists — show verification modal
        }
    });
}, []);

useParental() Hook

useParental() (from lib/hooks/useParental.ts) loads and updates the parental_settings row for the authenticated user. It exposes the full ParentalSettings interface along with update helpers:
export interface ParentalSettings {
    daily_limit_minutes: number;
    used_seconds_today: number;
    date_today: string;
    tts_speed: number;
    animation_intensity: AnimationIntensity;
    game_mode_enabled: boolean;
}

export function useParental() {
    // ...
    return {
        settings,
        loading,
        usedSecondsToday,
        isBlocked,
        addUsedSeconds,
        updateDailyLimit,
        updateSensoryConfig,
        updateGameMode,
        refresh: load,
    };
}
Key properties:
  • settings.animation_intensity — current AnimationIntensity value (see below)
  • settings.tts_speed — speech rate multiplier between 0.5 and 2.0
  • isBlockedtrue when the child has exceeded their daily usage limit; the board shows a time-limit screen
  • addUsedSeconds(n) — increments the daily usage counter; called by the app’s session timer
  • updateSensoryConfig(patch) — upserts tts_speed or animation_intensity to Supabase and writes an audit log entry

AnimationIntensity

The AnimationIntensity type controls how much visual motion the app uses during pictogram selection and phrase playback:
export type AnimationIntensity = 'none' | 'soft' | 'normal';
ValueLabelDescription
'none'Sin animacionesFully static screen — no transitions, no celebratory effects
'soft'SuavesLight transitions only — no celebration animations, muted feedback
'normal'NormalFull animations — confetti on level completion, bounce effects on selection
This setting is surfaced in Settings → Configuración sensorial → Intensidad de animaciones and maps directly to the animation_intensity column in parental_settings.

Protected Screens

The following screens are only fully accessible when the caregiver has authenticated through the parental gate:

Settings

The main settings screen (app/settings.tsx) requires PIN verification on every visit. If the stored PIN is null, access is granted immediately so the caregiver can set one.

Vocabulary Manager

app/vocabulary-manager.tsx — enables or disables individual pictograms per category. Accessible from Settings → Control parental → Gestión de vocabulario.

Activity Editor

app/activity-editor.tsx — creates and manages guided activity sequences for the child. Accessible from Settings → Control parental → Actividades guiadas.

Team Manager

app/team-manager.tsx — invites therapists and other professionals to view the child’s usage data. Accessible from Settings → Control parental → Equipo del niño.

Parental Settings in Supabase

The parental_settings table (created by migrations 20260307000001_parental_settings.sql and 20260331000004_phase3_parental_sensory_config.sql) stores all caregiver-controlled preferences server-side, scoped to each user by Row Level Security:
CREATE TABLE IF NOT EXISTS public.parental_settings (
    user_id              uuid        PRIMARY KEY REFERENCES public.profiles(id) ON DELETE CASCADE,
    daily_limit_minutes  int         NOT NULL DEFAULT 30,
    used_seconds_today   int         NOT NULL DEFAULT 0,
    date_today           date        NOT NULL DEFAULT (CURRENT_DATE AT TIME ZONE 'UTC'),
    tts_speed            numeric(3,1) NOT NULL DEFAULT 1.0
                         CHECK (tts_speed BETWEEN 0.5 AND 2.0),
    animation_intensity  text        NOT NULL DEFAULT 'normal'
                         CHECK (animation_intensity IN ('none', 'soft', 'normal')),
    game_mode_enabled    boolean     NOT NULL DEFAULT false
);
Every change to tts_speed or animation_intensity via updateSensoryConfig() is also written to the config_audit_log table (created in the same migration), which records the field name, old value, and new value with a timestamp. This audit trail can be used by therapists to review configuration history.

Daily Usage Limit

Caregivers can set an optional daily usage cap from Settings → Control parental → Límite de uso diario:
Optiondaily_limit_minutes
Disabled0
15 minutes15
30 minutes30
60 minutes60
used_seconds_today is reset automatically when date_today differs from the current UTC date. When isBlocked becomes true, the communication board is replaced by a time-limit screen until the next day.

Changing the PIN

To change the PIN, the caregiver taps changePinRequest() from EditModeContext. This triggers a two-step flow:
  1. Verify current PINPinModal is shown in 'verify' mode with title “Ingresa el PIN actual”
  2. Enter new PIN — On success, PinModal is shown in 'setup' mode with title “Nuevo PIN Parental”
The new PIN is written to AsyncStorage under STORAGE_KEYS.PARENTAL_PIN and replaces the previous value immediately.
There is no PIN recovery mechanism in the current version of ComuniTEA. If the caregiver forgets their PIN, the only way to regain access to Settings and other protected screens is to reinstall the application, which will also clear all local AsyncStorage data including the PIN. Make sure to store your PIN in a safe place.

Build docs developers (and LLMs) love