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.

The Profile & Reports section of ComuniTEA is designed for the adults in a child’s support network — parents, speech-language therapists, psychologists, and teachers. It surfaces clear, actionable data about how the child is using the AAC board: which pictograms they reach for most, how many sentences they build per session, whether their accuracy in exercises is improving, and what daily routines look like. Reports can be exported as PDF and shared directly with any member of the child’s support team. The goal is not clinical surveillance but collaborative support: giving families and therapists a shared picture of the child’s communicative growth.

Usage statistics (useStats)

Every interaction with the tablero and exercises is captured by the useStats hook and stored in the usage_stats Supabase table. Events fire-and-forget: they never block the UI, and they are queued locally when the device is offline and synced when connectivity is restored.
export type StatEvent =
  | 'session_start'   // child opens the app with an active session
  | 'pictogram_tap'   // child taps a final pictogram (not a category tile)
  | 'sentence_play'   // child plays the frase strip
  | 'free_text'       // child uses the free-text keyboard with ElevenLabs
  | 'ai_expand';      // child uses the magic-wand AI phrase expansion

export interface StatEventMeta {
  categoryId?: string;      // root category when event is pictogram_tap
  sentenceLength?: number;  // number of pictograms when event is sentence_play
  latencyMs?: number;       // AI call latency for ai_expand events
  intent?: string;          // communicative intent of the pictogram
}

export function useStats(): {
  logEvent: (event: StatEvent, meta?: StatEventMeta) => void;
  /** Records a completed sentence to sentence_log for the personalized predictor. */
  logSentence: (pictogramIds: string[]) => void;
}
The logSentence method also writes to the sentence_log table, which powers personalized pictogram ordering predictions over time.
Events are queued via enqueueEvent() when the device is offline and flushed to Supabase automatically once the network is restored. No usage data is ever silently discarded.

Report generation (useReport)

The useReport hook fetches a comprehensive FullReportData object by calling four Supabase RPC functions in parallel. A selectable days window (default: 7 days) controls the reporting period.
export interface FullReportData {
  current: ReportData;           // stats for the selected period
  previous: ReportData | null;   // same-length period immediately before (for trend comparison)
  daily: DailyPoint[];           // per-day breakdown
  gameHistory: GameHistoryPoint[];
  insights: ReportInsight[];     // AI-generated suggestions (up to 5, non-expired)
}

export interface ReportData {
  description: string;
  byEventType: Record<string, number>;   // event counts keyed by StatEvent
  byHour: Record<string, number>;        // activity distribution by hour of day
  topPictograms: { id: string; count: number }[];
  sessions: number;
  sentencePlays: number;
  pictogramTaps: number;
  periodDays: number;
}

export interface DailyPoint {
  day: string;           // ISO date string
  sessions: number;
  sentence_plays: number;
  pictogram_taps: number;
  ai_expands: number;
}

export interface GameHistoryPoint {
  completed_at: string;
  sublevel: number;
  correct: number;
  total_trials: number;
  pct: number;
}

export interface ReportInsight {
  id: string;
  insight_type: string;
  message: string;
  seen: boolean;
  created_at: string;
}
The previous period is computed by fetching a double-length window (p_days * 2) and subtracting the current-period totals, yielding the prior-period baseline for trend arrows in the UI.
export function useReport(): {
  data: FullReportData | null;
  loading: boolean;
  error: string | null;
  fetchReport: (days?: number) => Promise<void>;
}

Statistics display (EstadisticasRow)

The top of the profile screen shows a three-card summary row powered by EstadisticasRow:
MetricDescription
Frases hoyNumber of sentence_play events recorded today
Días seguidosConsecutive days streak (from profile streakDays)
AciertosExercise accuracy percentage across all recorded attempts

Achievements system

ComuniTEA includes a fixed catalog of five achievements displayed in the LogrosGrid component as a horizontal scrollable row of emoji badges. Unlocked badges are shown with a golden background; locked badges are greyed out.
export const ACHIEVEMENT_CATALOG: AchievementDef[] = [
  {
    id: 'first_sentence',
    emoji: '⭐',
    title: 'Primera frase',
    check: (c) => c.sentencesToday >= 1,
  },
  {
    id: 'streak_3',
    emoji: '🔥',
    title: '3 días seguidos',
    check: (c) => c.streakDays >= 3,
  },
  {
    id: 'level_3',
    emoji: '🏆',
    title: 'Nivel 3',
    check: (c) => c.level >= 3,
  },
  {
    id: 'xp_500',
    emoji: '🌟',
    title: '500 XP',
    check: (c) => c.totalXpApprox >= 500,
  },
  {
    id: 'practice_80',
    emoji: '🎯',
    title: '80% aciertos',
    check: (c) =>
      c.totalAttempts >= 5 &&
      Math.round((100 * c.correctAttempts) / c.totalAttempts) >= 80,
  },
];
Achievements are evaluated on each session via evaluateNewAchievementIds(), which receives current session stats plus the set of already-unlocked IDs. Any newly qualifying achievements are written back to the child’s profile in Supabase. The buildLogrosFromUnlocked(unlockedIds) helper maps the catalog to LogroItem[] objects for rendering.

Favorites tracking (FavoritosRow)

The FavoritosRow component renders a horizontal list of the child’s favorite pictograms — those with esFavorito: true in the merged board. Favorites are surfaced as tappable mini-cards (64 × 72 px) showing the pictogram’s emoji and label. Tapping a favorite in the profile view can be configured to trigger the pictogram’s audio clip (onPressPicto prop). Caregivers see favorites as a quick-glance indicator of which vocabulary items the child has chosen to pin, and can update them from the tablero editor.

Daily routines (useRutinas)

The routine manager lets caregivers build a visual daily schedule that links to the child’s tablero context. Routines are stored in the Supabase tasks table with row-level security.
export interface Rutina {
  id: string;
  user_id: string;
  label: string;
  emoji: string;
  completed: boolean;
  duration: number | null;  // estimated minutes, null if open-ended
  position: number;         // display order
}
When a user first opens the routines screen, five default tasks are seeded automatically:
EmojiLabelDuration
☀️Despertar
🚽Baño5 min
🪥Lavarse los dientes2 min
🥞Desayunar15 min
🏫Ir a la escuela
export function useRutinas(): {
  rutinas: Rutina[];
  loading: boolean;
  error: string | null;
  toggleCompleted: (id: string) => Promise<void>;
  addRutina: (label: string, emoji?: string, duration?: number) => Promise<void>;
  deleteRutina: (id: string) => Promise<void>;
  /** Unchecks all tasks — useful for starting a new day. */
  resetCompleted: () => Promise<void>;
  reload: () => Promise<void>;
}
toggleCompleted uses optimistic updates: the UI updates immediately and the Supabase call fires in the background. resetCompleted is intended to be called at the start of each day to clear all completed states.

AI Insights

AI-generated recommendations appear in the report screen under the insights section. They are produced by the ai-insights Supabase Edge Function, which calls the OpenAI API and returns short, actionable suggestions in warm, non-clinical Spanish. The Edge Function receives:
{
  "vocabularyLevel": "INTERMEDIO",
  "sublevel": 3,
  "avgSentenceLength": 2.1,
  "totalSentences": 47,
  "topPictogramLabels": ["Quiero", "Manzana", "Jugo", "Mamá", "Jugar"],
  "unusedCategoryLabels": ["Emociones", "Actividades"]
}
And responds with:
{
  "suggestions": [
    "Esta semana el niño usó 'Quiero' 28 veces pero nunca usó 'Siento'; considera trabajar la expresión de emociones en la próxima sesión.",
    "El niño tocó pictogramas de comida 14 veces — prueba agregar más opciones en la categoría Comida para ampliar su vocabulario.",
    "Lleva 4 días seguidos usando la app. ¡Es un gran avance! Puedes celebrarlo con él."
  ]
}
Insights are fetched as part of fetchReport() from the ai_insights table — up to 5 non-expired rows, ordered by unread-first. Each insight has a seen flag that caregivers can mark to dismiss it.

PDF export

The report screen uses expo-print and expo-sharing to generate and share a formatted PDF of the current report. The export is triggered from app/report.tsx and includes:
  • Summary statistics (sessions, sentence plays, pictogram taps)
  • Bar chart of activity by hour of day
  • Daily usage line chart
  • Top 5 most-used pictograms
  • Exercise game history
  • AI insight suggestions
import * as Print from 'expo-print';
import * as Sharing from 'expo-sharing';
The PDF is generated client-side from an HTML template, printed to a temporary URI, and then passed to the native share sheet via Sharing.shareAsync(). No data leaves the device except through the standard OS share mechanism.

Team access (useChildTeam)

Caregivers can share report access with the child’s full support team using the useChildTeam hook. Team members are stored in the child_team Supabase table with role-based permissions.
export type TeamRole = 'padre_madre' | 'terapeuta' | 'psicologo' | 'docente';

export interface TeamMember {
  id: string;
  role: TeamRole;
  can_view_reports: boolean;
  can_edit_vocabulary: boolean;
  status: 'pending' | 'active' | 'revoked';
  invite_email: string | null;
  accepted_at: string | null;
}
Default permissions by role:
RoleView ReportsEdit Vocabulary
padre_madre
terapeuta
psicologo
docente
export function useChildTeam(): {
  members: TeamMember[];
  isLoading: boolean;
  error: string | null;
  loadTeam: () => Promise<void>;
  inviteMember: (role: TeamRole, email?: string) => Promise<TeamMember | null>;
  acceptInvite: (token: string) => Promise<string | null>;
  revokeMember: (memberId: string) => Promise<void>;
  updatePermissions: (memberId: string, perms: Partial<TeamMember>) => Promise<void>;
  /** Generates a 7-day share token for report-only access. */
  generateShareToken: () => Promise<string | null>;
}
Invitations generate a pending TeamMember record with a unique invite_token. The invited professional accepts by entering the token in their own instance of the app, which calls the accept_team_invite Supabase RPC function. All team management actions are logged in the audit trail via auditLog().
Team members with can_edit_vocabulary: true can add, remove, and reorder pictograms in the child’s board. Grant this permission only to people who are actively involved in the child’s AAC therapy plan.

Build docs developers (and LLMs) love