Aparência
App do Responsável (mobile)
O que é este documento — o mapa funcional e técnico do app do responsável do ionCLASS: o cliente mobile (guardião/responsável) que aciona o "Estou Chegando", acompanha a retirada ao vivo, gerencia responsáveis e permissões por aluno e recebe notificações de entrada/saída. É uma das quatro superfícies do produto — veja as irmãs em Monitor de Portaria, Painel Público e Painel Administrativo.
1. O que é
O app do responsável é um cliente REST puro do backend Laravel (/api/v1/*) — sem código compartilhado com as outras superfícies, apenas o contrato de API espelhado à mão (endpoints + schemas Zod). O público é o responsável: pai, mãe ou outro responsável vinculado a um ou mais alunos. Ele:
- sinaliza que está chegando para retirar o(s) filho(s) ("Estou Chegando");
- acompanha o estado de retirada ao vivo de cada aluno (o mesmo fluxo que a portaria opera);
- gerencia outros responsáveis e permissões temporárias por aluno (gated por capabilities);
- recebe alertas de entrada/saída e notificações push.
Autenticação é Sanctum bearer token, guardado em MMKV; um 401 limpa token + usuário e volta ao login. Onboarding é CPF + email → código de 6 dígitos (sem código de convite, sem fila de aprovação) — ver Autenticação e Autorização.
2. Stack técnica
| Camada | Tecnologia |
|---|---|
| Runtime | Expo SDK 55 + Expo Router (roteamento por arquivos), React Native 0.83 com New Architecture |
| UI / tema | NativeWind 4 (Tailwind para RN), primitivos estilo shadcn, Reanimated 4 (worklets) |
| Estado local / storage | MMKV — token, escola ativa, flags |
| HTTP | axios + interceptors (Bearer, X-School-Id, X-Pin-Confirmation, 401) · zod como fonte de verdade dos tipos |
| Tempo real | laravel-echo + pusher-js/react-native (Reverb, protocolo pusher) |
| Push | Firebase FCM + Notifee (apresentação/canal local das notificações) |
| Localização | expo-location (geolocalização no "Estou Chegando") |
⚠️ O app é buildado direto do nativo (Xcode/Android Studio), não só por configuração declarativa. Não há test runner, lint ou typecheck configurados por padrão — a checagem de tipos é feita à parte.
3. Estrutura de telas
O app se organiza em três grandes áreas: as telas fora da sessão (autenticação), as abas (a casa do app) e as telas de detalhe empilhadas sobre as abas.
3.1 Fora da sessão
| Tela | Conteúdo |
|---|---|
| Boas-vindas | Splash / entrada |
| Login | Login (CPF/email + senha) |
| Primeiro acesso | Onboarding: informa CPF + email para o match |
| Verificar código | Confirma o código de 6 dígitos enviado por email (Fortify) |
| Foto | Captura da foto do responsável (usada na verificação da portaria) |
| Esqueci a senha / Redefinir senha | Fluxo de recuperação de senha |
3.2 As 5 abas
Ordem da barra (a central em destaque): Início · Alunos · ESTOU CHEGANDO · Alertas · Menu.
| Aba | Conteúdo |
|---|---|
| Início | Home: resumo dos alunos / atalhos |
| Alunos | Lista de alunos e detalhe do aluno com estado de retirada ao vivo, responsáveis e permissões |
| ESTOU CHEGANDO | Aba central: monta o sinal de chegada; leva à tela do sinal em andamento |
| Alertas | Feed de entradas/saídas |
| Menu | Ponto de entrada para perfil, notificações, segurança e veículos |
3.3 Telas de detalhe empilhadas
- Menu → Perfil, Notificações, Segurança.
- Veículos → lista, cadastro e edição — CRUD de veículos.
- Raiz → definição do PIN e permissão/preview de localização.
4. Funcionalidades
4.1 Onboarding (CPF + email → código)
Sem código de convite e sem fila de aprovação de responsável: o app coleta CPF + email, o backend faz o match com o responsável pré-cadastrado e dispara um código de 6 dígitos por email; a confirmação passa pelo Fortify. CPF desconhecido → 422 silencioso (não abre fila administrativa). Detalhes em Autenticação e Autorização.



4.2 Alunos e detalhe ao vivo
A aba Alunos e o detalhe do aluno trazem o estado de retirada de cada aluno e reconciliam ao vivo por WebSocket (§6). O detalhe é também onde vivem responsáveis e permissões do aluno.



4.3 Gestão de responsáveis e permissões temporárias (capabilities)
Cada aluno tem um titular (pai/mãe, com todas as capacidades implicitamente) e responsáveis secundários com um subconjunto. O backend devolve capabilities já resolvido no detalhe do aluno; o app libera telas/ações conforme essas capabilities:
| Capability | Habilita |
|---|---|
manage_responsibles | Incluir, editar e remover outros responsáveis do aluno |
view_temporary_permissions | Visualizar as permissões temporárias do aluno |
create_temporary_permissions | Criar, editar e cancelar permissões temporárias |
view_activities | Ver o histórico de entradas e saídas do aluno |
Endpoints do lado do app: me/students/{student}/responsibles (vincular/editar/remover), além dos endpoints de permissões temporárias e de pessoas autorizadas.
4.4 "Estou Chegando"
O fluxo central do produto. Na aba ESTOU CHEGANDO o responsável:
- seleciona quais alunos vai retirar (irmãos podem ir juntos no mesmo sinal);
- escolhe o modo de transporte (a pé / veículo) e, se dirigindo, o veículo;
- escolhe o ponto de retirada (portão);
- envia a geolocalização (expo-location) junto ao sinal.
POST v1/arrival-signals cria o sinal; GET v1/arrival-signals/active alimenta a tela de sinal ativo, e POST v1/arrival-signals/{id}/cancel cancela. O sinal cai na fila da portaria (Monitor de Portaria) e no painel público (Painel Público). Ver o fluxo ponta a ponta em Ciclo de Retirada.



4.5 Alertas
Feed de entradas/saídas do(s) aluno(s) — o histórico de eventos de acesso, também alimentado por push e reconciliado ao vivo.
4.6 Veículos (CRUD)
Cadastro/edição/remoção de veículos do responsável, com marcação de favorito. Usados no "Estou Chegando" e exibidos no cartão da portaria para identificação visual.
4.7 Segurança / PIN
Um PIN de 4 dígitos protege ações sensíveis. Ao verificar/definir/redefinir o PIN, o backend emite uma confirmação de curta duração (token + validade), mantida só em memória (nunca em MMKV, some ao relançar o app). O interceptor do axios injeta esse token no header X-Pin-Confirmation; ele expira de forma "dura", sem renovação automática. Fica na tela de Segurança (+ fluxo de definição do PIN).
4.8 Notificações
Tela de Notificações: toggle master + preferências por tipo de notificação + quiet hours (horário silencioso). O registro do device de push é feito por POST v1/me/devices (e DELETE v1/me/devices/{device} no logout).
4.9 Perfil
Tela de Perfil: editar dados, foto, consentimento biométrico + face-quality e exclusão de conta.
5. Multi-escola
O responsável tem vínculo N:N com escolas. A escola ativa é mantida pelo app e persistida no MMKV; toda chamada REST injeta o header X-School-Id com ela. Quando há mais de uma escola, o usuário troca a ativa pelo avatar da escola no header, e trocar de escola reseta a navegação e reabre a conexão de tempo real.
⚠️ Este seletor de escola é considerado temporário ("remover quando o rollout terminar"). A escola escopa o que o app vê/edita/cria.
6. Tempo real
O app assina o canal privado responsible.{userId}.school.{schoolId} (autorizado por identidade do usuário e responsável ativo naquela escola — um responsável bloqueado não assina). As credenciais do Reverb vêm de GET v1/me/monitor/credentials (mesmo shape do operador) e o handshake do canal passa por /api/broadcasting/auth (Sanctum, com Bearer + X-School-Id).
- Conecta só em foreground. A camada de tempo real recria o Echo quando token ou escola mudam.
- Eventos:
StudentStateChanged(estado de retirada),StudentRosterChanged(rebusca a lista) eResponsibleNotificationCreated(inbox). - Reconciliação por versão do estado de retirada (regra da portaria): aplica o novo estado sem nunca regredir abaixo da versão local; evento mais antigo é ignorado (identidade do objeto preservada para evitar re-render).
- É best-effort: se o WS cair, a verdade do servidor reconcilia no próximo refetch ao focar a tela.
Ver Tempo Real e o runbook de operação em Runbook de Tempo Real.
7. Push (FCM + Notifee)
WebSocket cobre o app aberto; FCM cobre o app fechado — os dois convivem. O device é registrado em POST v1/me/devices; o Notifee apresenta a notificação local (canal/quiet hours). A deduplicação usa a versão do estado de retirada (estado nunca regride) e o identificador real da notificação (inbox), então push + WS nunca divergem.
8. Tema
Fonte única de tema (tokens de cor + adapter do React Navigation). Paleta de marca: navy #043471 (primary no claro), azul #0277F4 (accent), light #5AB5FC, turquoise #21D7CA. O CSS de estilos é gerado a partir dessa fonte de tema — nunca editar à mão (é sobrescrito). Dark mode pelo esquema de cores do sistema via NativeWind.