Uma jornada do usuário no Arah é uma sequência de interações que um usuário realiza para alcançar um objetivo específico dentro da plataforma, considerando:
Papel do usuário: VISITOR, RESIDENT, CURATOR, MODERATOR, EVENT_ORGANIZER, SYSTEM_ADMIN
Módulo/Funcionalidade: Auth, Territórios, Feed, Mapa, Eventos, Marketplace, Chat, etc.
Rola o feed: Vê posts de outros moradores sobre eventos locais, alertas, discussões
Toca em um post: Abre detalhes
Vai para o Mapa: Vê pins de posts georreferenciados
Explora Eventos: Vê eventos próximos, alguns com data futura
Verifica Perfil: Vê seu perfil básico (nome, avatar padrão)
Emoções: Interesse crescente, curiosidade sobre conteúdo exclusivo
Trigger: Maria quer participar mais ativamente, criar posts, acessar conteúdo exclusivo.
Tela 9: Solicitar Residência
Header: "Solicitar Residência" + botão voltar
Conteúdo:
Título: "Torne-se moradora de [Nome do Território]"
Descrição: "Como moradora, você terá acesso a conteúdo exclusivo e poderá criar posts, eventos e participar de votações."
Requisitos:
✓ Geolocalização dentro do território
✓ Verificação opcional de documento
✓ Aprovação por curadores
Passo 1: Verificação de Localização:
Mostra posição atual no mapa
Valida se está dentro do polígono ou próximo (raio de 2km)
Status: "✅ Localização verificada" ou "⚠️ Precisa estar mais próximo"
Passo 2: Upload de Documento (Opcional):
"Adicione um comprovante de residência (opcional)"
Botão "Adicionar Documento"
Preview do documento (se adicionado)
Formatos aceitos: PDF, JPG, PNG
Tamanho máximo: 10MB
Passo 3: Mensagem (Opcional):
Input de texto: "Deixe uma mensagem para os curadores (opcional)"
Placeholder: "Conte um pouco sobre você e sua relação com o território..."
Máximo: 500 caracteres
Ações:
Botão "Enviar Solicitação" (primary, habilitado após validação de localização)
Link "Cancelar"
Envio da Solicitação:
Valida localização
Upload do documento (se fornecido)
Cria JoinRequest com status PENDING
Notifica curadores (se não houver destinatários específicos)
Mostra confirmação
Tela 10: Confirmação de Solicitação
Ícone: Check verde
Título: "Solicitação Enviada"
Mensagem: "Sua solicitação foi enviada aos curadores. Você receberá uma notificação quando ela for revisada."
Status: Badge "PENDENTE" com cor amarela
CTA: "Voltar ao Feed"
Estado Posterior:
Maria continua como VISITOR
Badge no perfil mostra "Pendente de Aprovação"
Notificações são habilitadas para avisar sobre aprovação
Trigger: Curador aprova a solicitação de Maria
Notificação Recebida:
Push notification: "🎉 Você foi aprovada como moradora do [Nome do Território]!"
Badge no ícone de notificações
Tela 11: Notificação de Aprovação
Maria toca na notificação
Abre tela de notificações
Card de notificação destacado:
Ícone de confirmação (verde)
"Sua solicitação de residência foi aprovada!"
"Agora você tem acesso completo ao território."
CTA: "Explorar Território"
Atualização Automática:
Vínculo atualizado: VISITOR → RESIDENT
Badge no header muda: "VISITANTE" → "MORADORA" (verde)
Feed atualiza: Agora mostra posts RESIDENTS_ONLY
FAB muda: "Criar Post" disponível
Tela 12: Feed Atualizado (Agora como Residente)
Banner de Parabéns (se primeira vez como residente):
"🎉 Parabéns! Você agora é moradora!"
"Você tem acesso a conteúdo exclusivo e pode criar posts e eventos."
CTA: "Criar Primeiro Post" / "Fechar"
Feed agora inclui:
Posts PUBLIC
Posts RESIDENTS_ONLY (novos!)
Eventos RESIDENTS_ONLY
Emoções: Satisfação, senso de pertencimento, empoderamento
Esta é a narrativa completa do acesso inicial. Agora vamos mapear todas as jornadas detalhadas por papel e módulo.
👥 Jornadas por Papel
🟢 JORNADAS DO VISITOR (Visitante)
Objetivo Principal: Explorar território, descobrir conteúdo público, decidir se quer se engajar
Permissões: Acesso a conteúdo PUBLIC apenas, visualização limitada
Limitações: Não pode criar posts RESIDENTS_ONLY, não pode criar eventos RESIDENTS_ONLY, não pode usar marketplace (compras/vendas), não pode participar de votações
Jornada 1: Explorar Feed Público do Território
Objetivo: Ver o que está acontecendo no território
Pré-condições:
✅ Usuário autenticado
✅ Território selecionado como ativo
✅ Vínculo VISITOR criado
Fluxo Passo a Passo:
Ação: Usuário toca na aba "Feed" na bottom navigation
Tela: FeedScreenEstado Inicial:
Header: Nome do território + badge "VISITANTE" (cinza)
Banner informativo (se primeira vez): "Você está vendo conteúdo público. Para acessar conteúdo exclusivo, solicite residência."
Pull-to-refresh habilitado
Lista vazia (loading skeleton aparece)
Loading State:
3-5 skeleton loaders de cards de post
Animações shimmer
Duração: ~500ms-2s (dependendo da conexão)
Ação: API retorna posts PUBLIC do território
Posts Exibidos:
Apenas posts com visibility = PUBLIC
Posts RESIDENTS_ONLY são filtrados automaticamente (não aparecem)
Ordenação: Mais recentes primeiro
Paginação: 20 posts por página
Card de Post (Para VISITOR):
┌─────────────────────────────────────┐
│ [Avatar] Nome do Autor há 2h │
│ │
│ 📍 Próximo a você (1.2 km) │
│ │
│ Título do Post (se houver) │
│ │
│ Conteúdo do post aqui... │
│ Pode ter múltiplas linhas. │
│ │
│ [Imagem se houver - 16:9] │
│ │
│ ───────────────────────────────── │
│ ❤️ 12 💬 5 📤 Compartilhar │
└─────────────────────────────────────┘
Elementos Visuais:
Avatar do autor (circular, 40px)
Nome do autor (heading4, clicável → abre perfil)
Timestamp (caption, "há X minutos/horas/dias")
Badge de proximidade "📍 Próximo a você" (se GeoAnchor disponível)
Tipo de post (badge discreto): NOTICE, ALERT, ANNOUNCEMENT
Conteúdo (bodyMedium, markdown renderizado)
Imagens (se houver, aspect ratio 16:9, cached)
Ações: Like (heart), Comentar (chat), Compartilhar (share)
Indicador visual: Border sutil cinza (distinguindo de RESIDENTS_ONLY)
Interações:
Tap no card: Abre PostDetailScreen
Tap no avatar/nome: Abre UserProfileScreen do autor
Tap em "Gostar": Animação de like (scale + bounce), cor vermelha, incrementa contador
Tap em "Comentar": Abre PostDetailScreen com foco no input de comentário
Tap em "Compartilhar": Abre bottom sheet com opções (copiar link, compartilhar externamente)
Swipe left no card: Ações rápidas (favoritar, reportar)
Pull to refresh: Atualiza feed, mostra indicador de loading no topo
Passo 3: Scroll Infinito
Ação: Usuário rola até o final da lista
Comportamento:
Quando chega a 80% do final, carrega próxima página automaticamente
Indicador de loading no final: "Carregando mais posts..."
Se não houver mais posts: Mensagem "Você viu todos os posts públicos"
Ação: Usuário toca em um card de post
Transição: Slide transition da direita (300ms)
Tela: PostDetailScreenConteúdo:
Header com nome do território + botão voltar
Card do post expandido (mesma estrutura do feed, mas maior)
Mensagem: "Você precisa estar fisicamente próximo ao território para solicitar residência."
Opções:
"Tentar Novamente" (refaz verificação)
"Voltar" (cancela solicitação)
Link: "Por que preciso estar próximo?" (explica motivo)
Ação: Usuário pode adicionar comprovante de residência
Tela: DocumentUploadStepOpções:
Botão "Adicionar Documento"
Formatos aceitos: PDF, JPG, PNG
Tamanho máximo: 10MB
Preview do documento (se adicionado)
Botão "Remover" (se documento adicionado)
Fluxo de Upload:
Toca em "Adicionar Documento"
Abre seletor de arquivo (File Picker)
Seleciona documento
Preview aparece
Upload inicia (progress bar)
Upload completo → "✅ Documento enviado"
Opcional:
Checkbox "Pular esta etapa" → Permite continuar sem documento
Passo 4: Mensagem para Curadores (Opcional)
Ação: Usuário pode deixar mensagem
Input de Texto:
Placeholder: "Conte um pouco sobre você e sua relação com o território..."
Máximo: 500 caracteres
Contador: "X/500 caracteres"
Opcional: Pode deixar em branco
Ação: Usuário toca em "Enviar Solicitação"
Validação Final:
✅ Localização verificada
✅ Formulário completo (documento e mensagem são opcionais)
Processamento:
Valida localização novamente
Upload do documento (se fornecido)
Cria JoinRequest com status PENDING
Define destinatários:
Se recipientUserIds fornecido → Para esses usuários
Se não → Para curadores do território
Se não houver curadores → Para SystemAdmin
Notifica destinatários (push + in-app)
Retorna sucesso
Tela de Confirmação:
┌─────────────────────────────────────┐
│ ✅ Solicitação Enviada │
│ │
│ Sua solicitação foi enviada aos │
│ curadores do território. │
│ │
│ Status: PENDENTE │
│ │
│ Você receberá uma notificação │
│ quando ela for revisada. │
│ │
│ [Botão Voltar ao Feed] │
└─────────────────────────────────────┘
Transição:
Volta para Feed
Badge no header muda: "VISITANTE" → "PENDENTE" (amarelo)
Banner informativo: "Aguardando aprovação de residência..."
Pós-condições:
JoinRequest criada com status PENDING
Usuário continua como VISITOR
Notificações habilitadas para aprovação/rejeição
Documento armazenado (se fornecido) para revisão
Jornada 7: Verificar Status de Solicitação de Residência
Objetivo: Acompanhar status da solicitação de residência
Pré-condições:
✅ Solicitação de residência enviada (status PENDING)
Fluxo Passo a Passo:
Passo 1: Acessar Status
Triggers:
Banner no feed: "Sua solicitação está sendo revisada"
Menu do perfil: "Status de Residência"
Badge "PENDENTE" no header (clicável)
Tela: ResidencyStatusScreenEstado Inicial:
Header: "Status de Residência" + botão voltar
Card de status com informações
Card de Status:
┌─────────────────────────────────────┐
│ Status: PENDENTE │
│ │
│ Data da Solicitação: 20 Jan, 2025 │
│ │
│ Revisando: Curadores do território │
│ │
│ Sua solicitação está sendo │
│ revisada. Você receberá uma │
│ notificação quando ela for │
│ aprovada ou rejeitada. │
│ │
│ [Ícone de relógio animado] │
└─────────────────────────────────────┘
Estados Possíveis:
PENDING: Badge amarelo, mensagem de aguardo
APPROVED: Badge verde, mensagem de sucesso (quando aprovado)
REJECTED: Badge vermelho, mensagem de rejeição + motivo (se fornecido)
GeoAnchor derivado automaticamente (se mídia tem EXIF)
Upload:
Progress bar por mídia
Compressão automática de imagens
Thumbnails gerados
Preview atualizado em tempo real
Preview das Mídias:
Grid de miniaturas
Botão "X" para remover cada mídia
Drag & drop para reordenar
Tap em miniatura → Abre viewer fullscreen
Passo 4: Visualizar Preview
Card de Preview:
Mesma estrutura do card de post no feed
Mostra como ficará publicado
Atualiza em tempo real conforme edição
Ação: Usuário toca em "Publicar"
Validações:
✅ Conteúdo não vazio (mínimo 10 caracteres)
✅ Conteúdo não excede 4000 caracteres
✅ Título não excede 200 caracteres (se fornecido)
✅ Território ativo válido
✅ Sem sanções de posting
✅ Feature flags respeitadas (ex: ALERT só se flag habilitada)
Se Válido:
Botão "Publicar" fica disabled
Indicador de loading: "Publicando..."
Upload de mídias (se houver)
POST /api/v1/feed
Sucesso → Confirmação
Tela de Confirmação:
┌─────────────────────────────────────┐
│ ✅ Post Publicado! │
│ │
│ Seu post foi publicado com │
│ sucesso no feed do território. │
│ │
│ [Preview do post publicado] │
│ │
│ [Botão Ver no Feed] │
│ [Botão Criar Outro Post] │
└─────────────────────────────────────┘
Se Erro:
Snackbar com mensagem de erro
Botão "Publicar" reabilitado
Erro específico:
"Conteúdo muito curto" (se < 10 caracteres)
"Você não tem permissão para criar posts" (se sanção)
"Erro ao publicar. Tente novamente." (erro genérico)
Pós-condições:
Post publicado no feed
Post aparece no mapa (se tem GeoAnchor)
Notificações enviadas para moradores interessados (se relevante)
Gamificação: +5 pontos por criar post (se habilitada)
Validação: Não pode ser no passado (se menos de 1 hora atrás)
Hora de Início (obrigatório):
Time picker
Formato: HH:mm (24h)
Data de Fim (opcional):
Checkbox "Evento tem data de término"
Se marcado, mostra date picker
Validação: Deve ser após data de início
Hora de Fim (opcional, se data de fim marcada):
Time picker
Validação: Deve ser após hora de início
Validações:
Data de início não pode ser no passado (com tolerância de 1 hora)
Data de fim deve ser após data de início
Duração máxima: 30 dias (se configurado)
Botão "Próximo": Habilitado quando data/hora válidas
Campos:
Endereço (obrigatório):
Input com autocomplete (geocoding)
Sugestões conforme digita
Tap em sugestão → Preenche coordenadas automaticamente
Localização no Mapa:
Mapa interativo
Pin arrastável
Coordenadas atualizadas ao mover pin
Botão "Usar Minha Localização" → Move pin para posição atual
Validações:
Localização deve estar dentro do território (ou próximo, raio de 5km)
Coordenadas válidas (lat: -90 a 90, lng: -180 a 180)
Mapa Interativo:
Zoom automático para território
Pin verde (arrastável)
Polígono do território destacado
Botão "Centralizar no Território"
Campos:
Imagem de Capa (opcional):
Botão "Adicionar Imagem de Capa"
Picker de imagem
Preview da imagem selecionada
Aspect ratio: 16:9 (crop sugerido)
Capacidade (opcional):
Input numérico: "Limite de participantes"
Se vazio, evento ilimitado
Validação: Mínimo 2, máximo 10000
Requer Aprovação (opcional):
Switch: "Aprovar participantes manualmente"
Se habilitado, participantes precisam ser aprovados
Validações:
Capacidade: Se definida, deve ser >= 2
Tela de Preview:
Card completo do evento (como aparecerá no feed)
Todas as informações revisáveis
Botão "Editar" em cada seção
Ação Final: Usuário toca em "Publicar"
Validações Finais:
✅ Todos os campos obrigatórios preenchidos
✅ Data/hora válidas
✅ Localização válida e dentro do território
✅ Sem conflitos (evento não sobrepõe outros eventos muito próximos no mesmo horário)
Processamento:
Upload de imagem de capa (se houver)
POST /api/v1/events
Indicador de loading: "Criando evento..."
Sucesso → Confirmação
Tela de Confirmação:
┌─────────────────────────────────────┐
│ ✅ Evento Criado! │
│ │
│ Seu evento foi criado com sucesso │
│ e já está visível no feed e no │
│ mapa do território. │
│ │
│ [Preview do evento criado] │
│ │
│ [Botão Ver Evento] │
│ [Botão Compartilhar Evento] │
└─────────────────────────────────────┘
Pós-condições:
Evento publicado no feed
Evento aparece no mapa (pin azul)
Notificações enviadas para moradores interessados em eventos
Gamificação: +25 pontos por criar evento (se habilitada)
Organizador adicionado automaticamente como participante
🎯 Resumo de Jornadas por Papel
VISITOR (Visitante)
✅ Explorar Feed Público
✅ Explorar Mapa Territorial
✅ Explorar Eventos Públicos
✅ Buscar e Filtrar Conteúdo
✅ Visualizar Perfil de Outro Usuário
✅ Solicitar Residência
✅ Verificar Status de Solicitação
✅ Criar Post (PUBLIC ou RESIDENTS_ONLY)
✅ Participar de Evento
✅ Criar Evento Comunitário
✅ Usar Marketplace (compras/vendas)
✅ Participar de Votações
✅ Usar Chat (canais e DM)
✅ Verificar Alertas de Saúde
✅ Sugerir Assets Territoriais
✅ Recuperar Conta (reset de senha, recuperação de 2FA)
✅ Excluir Conta (LGPD/GDPR)
✅ Usar Modo Offline
CURATOR (Curador)
✅ Aprovar Solicitações de Residência
✅ Validar Assets Territoriais
✅ Gerenciar Votações Comunitárias
✅ Dashboard de Governança
✅ Configurar Feature Flags Territoriais
✅ Revisar Work Queue (evidências, documentações)
MODERATOR (Moderador)
✅ Revisar Reports
✅ Aplicar Sanções Territoriais
✅ Bloquear/Desbloquear Usuários
✅ Ocultar/Restaurar Conteúdo
✅ Dashboard de Moderação
EVENT_ORGANIZER (Organizador de Eventos)
✅ Gerenciar Participantes de Eventos
✅ Credenciar Participantes
✅ Dashboard de Eventos
SYSTEM_ADMIN (Administrador do Sistema)
✅ Gerenciar Territórios
✅ Gerenciar Usuários Globais
✅ Configurar Sistema
✅ Monitorar Work Queue Global
✅ Dashboard Administrativo
Jornada 8: Recuperação de Conta e Reset de Senha
Objetivo: Recuperar acesso à conta em caso de perda de credenciais
Pré-condições:
❌ Usuário perdeu acesso ao método de autenticação
❌ Usuário esqueceu senha/token
Fluxo Passo a Passo:
Passo 1: Acessar Recuperação
Ação: Usuário toca em "Esqueceu sua conta?" na tela de login
Tela: AccountRecoveryScreenOpções:
"Recuperar via Email"
"Recuperar via Telefone"
"Recuperar código 2FA" (se 2FA habilitado)
Ação: Usuário seleciona método e fornece email/telefone
Processo:
Valida email/telefone
Envia código de recuperação (email/SMS)
Mostra tela de inserção de código
Tela: RecoveryCodeScreen
Input de código (6 dígitos)
Botão "Reenviar código" (após 60 segundos)
Botão "Voltar"
Ação: Usuário insere código recebido
Validações:
✅ Código válido e não expirado (15 minutos)
✅ Tentativas máximas: 3 (após isso, bloquear por 1 hora)
Se Válido:
Permite redefinir senha/configurar novo método de autenticação
Expira código usado
Se Inválido:
Mostra erro: "Código inválido. Tente novamente."
Incrementa tentativas
Passo 4: Redefinir Acesso
Tela: ResetAccessScreenOpções:
Configurar novo método de autenticação social
Redefinir 2FA (se aplicável)
Configurar backup codes
Pós-condições:
Acesso recuperado
Notificação enviada sobre recuperação de conta
Jornada 9: Excluir Conta (LGPD/GDPR)
Objetivo: Excluir conta e dados pessoais conforme LGPD/GDPR
Pré-condições:
✅ Usuário autenticado
✅ Usuário quer excluir conta
Fluxo Passo a Passo:
Passo 1: Acessar Configurações de Conta
Ação: Usuário vai em Perfil → Configurações → Conta → Excluir Conta
Tela: DeleteAccountScreenAvisos:
"⚠️ Esta ação é irreversível"
"Todos os seus dados serão excluídos permanentemente"
"Você pode exportar seus dados antes de excluir"
Ação: Usuário toca em "Exportar Meus Dados"
Processo:
Gera arquivo JSON com todos os dados do usuário
Disponibiliza para download
Envia também por email (se configurado)
Conteúdo do Export:
Perfil completo
Posts criados
Comentários
Eventos criados/participados
Vínculos territoriais
Preferências
Histórico de atividades
Ação: Usuário toca em "Excluir Minha Conta"
Confirmação Dupla:
Modal de confirmação: "Tem certeza que deseja excluir sua conta?"
Input de confirmação: Digitar "EXCLUIR" para confirmar
Processo:
Valida confirmação
POST /api/v1/auth/delete-account
Backend marca conta para exclusão
Período de graça (7 dias) - usuário pode cancelar
Após 7 dias, exclusão permanente
Passo 4: Período de Graça
Notificação:
"Sua conta será excluída em 7 dias. Você pode cancelar a exclusão a qualquer momento."
Tela: AccountDeletionPendingScreen
Contador regressivo: "Exclusão em X dias"
Botão "Cancelar Exclusão"
Aviso: "Após exclusão, não será possível recuperar seus dados"
Passo 5: Exclusão Concluída
Pós-condições:
Conta excluída permanentemente
Dados removidos (anonimizados ou deletados)
Logout automático
Redirecionamento para tela de login
Jornada 10: Usar Modo Offline
Objetivo: Usar funcionalidades básicas do app sem internet
Pré-condições:
✅ App já usado anteriormente (dados cacheados)
❌ Sem conexão à internet
Fluxo Passo a Passo:
Passo 1: Detecção de Modo Offline
Ação: App detecta perda de conexão
Banner de Aviso:
"📴 Você está offline. Algumas funcionalidades estão limitadas."
Badge discreto no topo da tela
Funcionalidades Disponíveis:
✅ Feed (últimos posts cacheados)
✅ Eventos (próximos eventos cacheados)
✅ Perfil próprio
✅ Mapa (dados cacheados)
Limitações:
❌ Não pode atualizar feed
❌ Não pode buscar novos territórios
❌ Não pode criar eventos (requer validação de localização)
Passo 3: Criar Post Offline
Ação: Usuário cria post enquanto offline
Fluxo:
Preenche formulário normalmente
Toca em "Publicar"
Post salvo localmente (fila offline)
Badge: "⏳ Post será publicado quando online"
Post aparece no feed local com badge "Pendente"
Ação: App detecta retorno de conexão
Processo Automático:
Mostra banner: "🔄 Sincronizando dados..."
Processa fila offline:
Publica posts pendentes
Envia comentários pendentes
Registra likes pendentes
Atualiza feed automaticamente
Notifica: "✅ Sincronização concluída"
Resolução de Conflitos:
Se post foi editado/deletado online enquanto offline:
Mostrar diálogo: "Este post foi alterado online. O que você deseja fazer?"
Opções: "Manter alterações online", "Sobrescrever com versão offline"
Pós-condições:
Dados sincronizados
Feed atualizado
Fila offline vazia
🔄 Jornadas Cruzadas (Interações)
Objetivo: Denunciar post, evento ou usuário inadequado
Atualizar 00_INDEX.md com link para 27_USER_JOURNEYS_MAP.md
Expandir seção de i18n em 24_FLUTTER_FRONTEND_PLAN.md (média prioridade)
Este documento (27_USER_JOURNEYS_MAP.md) complementa perfeitamente a documentação existente, fornecendo:
✅ Narrativa completa de acesso inicial
✅ Jornadas detalhadas por papel (VISITOR, RESIDENT, etc.)
✅ Fluxos passo a passo com UI/UX esperada
✅ Pontos de fricção e otimizações
✅ Mapa visual de jornadas
✅ Análise completa da documentação existente
✅ Recomendações para desenvolvimento
A documentação do projeto Arah está pronta para suportar o desenvolvimento completo do app Flutter, com apenas algumas melhorias complementares recomendadas.
Versão: 1.0 Última Atualização: 2025-01-20 Autor: Sistema de Documentação Arah