KasyKasy

Drive (ride-hailing)

Corridas para passageiro e motorista com mapa Mapbox. Estimativa de preço no servidor, pagamento real via Stripe no futuro.

Drive é o módulo de ride-hailing do kit: o usuário pede uma corrida como passageiro ou entra no modo motorista para aceitar solicitações por perto. O fluxo completo roda nos 3 backends (Firebase, Supabase, API REST) com a mesma UI.

PapelO que faz
PassageiroEscolhe embarque e destino no mapa, vê distância, duração e valor estimado, acompanha a corrida em tempo real
MotoristaCadastra o veículo, fica online, aceita corridas próximas e conduz até concluir ou cancelar

O mapa usa Mapbox via flutter_map (tiles HTTP, funciona em nativo e web). A rota e o preço são calculados no servidor (Mapbox Directions + coeficientes que você define), não no app.

Os mapas iniciais do motorista e do passageiro usam zoom 16, inclusive ao receber a localização inicial e ao recentralizar. Os tiles Mapbox mantêm dimensão lógica de 512, com retina nativa para preservar a legibilidade dos nomes das ruas. Quando há uma rota, o mapa ajusta o enquadramento automaticamente para mostrar o trajeto completo.

O valor mostrado na tela é apenas uma estimativa. O kit não cobra o passageiro nem repassa pagamento ao motorista. Para cobrança real, integre o módulo Stripe (web) ou outro provedor no seu backend.

Implementação

Pelo MCP: peça ao assistente "adiciona drive no meu projeto". Ele roda add_feature por você. Veja MCP do Kasy.

  1. Ative o módulo (não vem no modo Rápido por padrão):

    kasy add drive        # adiciona (pede token Mapbox e coeficientes de preço)
    kasy remove drive     # remove
    kasy add --list       # mostra o que está ligado

    O kasy add drive grava MAPBOX_ACCESS_TOKEN no .env, semeia os coeficientes DRIVE_* e, no Firebase/Supabase, tenta gravar o token Mapbox como secret do servidor.

  2. Crie o token Mapbox:

    1. Crie conta em mapbox.com
    2. Gere um access token público (pk.…)
    3. Configure limites de uso e restrições de URL/bundle no console Mapbox
  3. Configure secrets e coeficientes:

    kasy configure drive

    Ou pela seção Drive (Ride-hailing) do kasy configure:

    VariávelOnde ficaUso
    MAPBOX_ACCESS_TOKEN.env do appTiles e mapa no Flutter
    MAPBOX_ACCESS_TOKENSecret do servidor (Firebase/Supabase)Directions e cálculo de preço no backend
    DRIVE_BASE_FAREfunctions/.env ou Supabase secretsTarifa base (padrão 5)
    DRIVE_PRICE_PER_KMidemPreço por km (padrão 1.5)
    DRIVE_PRICE_PER_MINidemPreço por minuto (padrão 0.25)
    DRIVE_CURRENCYidemCódigo ISO da moeda (padrão USD)

    No API REST, os coeficientes ficam no .env do seu servidor. Veja o contrato em docs/drive.md (entregue no projeto) e o README do patch API.

    Pelo MCP: cole o token Mapbox e os coeficientes no chat e peça "configura o Drive". O assistente grava com configure_project_keys (Firebase/Supabase). Veja MCP do Kasy.

  4. Faça o deploy do backend:

    BackendO que fazer
    Firebasekasy deploy (publica driveFunctions + triggers de push)
    Supabasesupabase db push (migration drive) + supabase functions deploy request-ride
    API RESTImplemente os endpoints POST /drive/rides, POST /drive/rides/{id}/accept etc. (veja README do patch)

    Pelo MCP (Firebase): "faz o deploy do backend" (deploy_backend).

  5. Confirme as permissões nativas. O app pede localização em runtime (embarque, motorista online). No iOS, Info.plist já traz as chaves de uso quando o módulo está ligado. Valide em dispositivo real antes de publicar.

  6. Teste o fluxo. Duas formas:

    • Sozinho, sem GPS de verdade: fora de produção, ligue "Teste automatizado" no menu lateral do Drive, ele simula o motorista andando uma rota fixa, então uma única conta testa passageiro e motorista alternando de papel. Veja Modo de teste automatizado abaixo.

    • Com dois dispositivos ou contas (ou emulador + físico), simulando passageiro e motorista ao mesmo tempo:

      1. Abra Configurações
      2. Toque no tile Drive (ícone de carro)
      3. Escolha Pedir corrida (passageiro) ou Modo motorista
  7. Para cobrança real (fora do escopo do módulo Drive), adicione Stripe (web) ou outro gateway e amarre a cobrança ao evento complete da corrida no seu backend.

Informações

Como o fluxo funciona

Na primeira abertura (Configurações → Drive), o app pergunta uma vez se o usuário quer usar como passageiro ou motorista e salva a escolha. Depois disso, o Drive abre direto na tela do papel salvo; a troca é pelo menu lateral do próprio Drive.

A corrida ativa é reconhecida em qualquer navegador ou dispositivo logado na mesma conta, trocar de aparelho no meio de uma corrida não perde o acompanhamento nem deixa pedir uma corrida duplicada por engano.

Passageiro:

  1. Busca o destino por texto ou ajusta os pinos de embarque/destino no mapa
  2. Vê a rota, distância, tempo e o preço estimado (calculado no servidor)
  3. Pede a corrida e acompanha em tempo real: posição do motorista, veículo e placa, ETA ao vivo
  4. Se nenhum motorista aceitar em cerca de 1 minuto, aparece "Nenhum motorista disponível" com contagem regressiva e a opção de tentar novamente, até 2 vezes. Depois disso só resta cancelar e tentar mais tarde
  5. Pode cancelar apenas enquanto a corrida está requested ou accepted. Depois que embarcou (in_progress), não dá mais para cancelar pelo app

Motorista:

  1. Precisa cadastrar o veículo (onboarding) antes de ficar online. O switch abre o cadastro automaticamente se faltar
  2. Online liga o GPS contínuo: a posição é publicada no backend e é ela que o passageiro vê no mapa
  3. Corridas próximas chegam como um overlay em tela cheia com som e vibração, com Aceitar e Recusar (recusar só esconde para aquele motorista). Enquanto está numa corrida, não recebe novas solicitações
  4. Ao aceitar, entra na navegação até o embarque. O botão "Embarquei o passageiro" só libera quando o GPS está a até 100 m do ponto de embarque
  5. Depois disso navega até o destino, e "Concluir corrida" só libera a até 100 m do destino. Fora do raio, o botão fica desabilitado com uma dica na tela

Regras de transição (validadas no servidor)

O botão liberar na tela não é a única proteção. O backend valida cada transição nos 3 backends, com as mesmas regras:

AçãoSó é aceita quando
AceitarCorrida ainda requested (se dois motoristas aceitam, só o primeiro ganha)
Iniciar (embarquei)Corrida accepted e o chamador é o motorista designado
ConcluirCorrida in_progress e o chamador é o motorista designado
CancelarCorrida ainda não completed nem canceled; só passageiro ou motorista da corrida

Localização em segundo plano

Por padrão, o GPS do motorista só é publicado com o app aberto (primeiro plano). Se ele minimizar no meio de uma corrida, a posição para de atualizar até ele voltar pro app.

Pra manter a posição chegando mesmo com o app minimizado, adicione o módulo Localização em segundo plano (kasy add background_location). Ele se conecta sozinho ao Drive: liga automaticamente pro motorista enquanto ele está online, sem precisar editar nada.

Hoje esse rastreamento em background é só do lado do motorista. O passageiro não é acompanhado em background porque nenhuma tela ou dado do Drive depende disso: a posição dele é capturada uma única vez, no momento do pedido (o pickup fixo que o motorista vê no mapa), e não muda depois disso mesmo com o app aberto.

Modo de teste automatizado (dev)

Fora de produção (qualquer build com ENV diferente de prod), o menu lateral do Drive tem um item "Teste automatizado". Ligado, ele deixa testar o fluxo inteiro, pedir, aceitar, recusar, embarcar, concluir, sozinho, com uma única conta, sem precisar de dois dispositivos nem de GPS de verdade:

  • A localização vira uma rota fixa simulada (um trecho real, roteirizado pelo Mapbox); o motorista "anda" essa rota sozinho, num ritmo acelerado (a corrida inteira leva segundos, não minutos).
  • Nas telas de corrida em andamento, um botão próprio na barra superior (ícone de carro/pino) troca sua própria conta para o outro papel, vira motorista pra você mesmo aceitar/recusar aquela solicitação, ou volta a ser passageiro, já que é a mesma pessoa testando os dois lados. O botão de voltar continua se comportando como em produção (cancela a corrida ou sai da navegação), sem misturar as duas ações.
  • Recusar não cancela a corrida: ela continua requested e visível para outros motoristas, igual em produção.

Só nesse modo: um hot restart (R maiúsculo no flutter run/kasy run, ou recarregar a aba do zero) reinicia a posição do veículo simulado, ele volta a andar a rota do começo, mesmo que já tivesse chegado. Isso é uma limitação do simulador (a posição só existe na memória do app, nunca é salva em lugar nenhum), não um bug do fluxo real. Em produção não existe equivalente: o GPS do celular é uma fonte externa que continua de onde estava, nenhum restart "esquece" a posição do motorista.

Esse toggle nunca aparece em build de produção (ENV=prod), nenhum usuário final o vê.

Onde ver no Firebase Console

O Drive não grava motorista nem corrida na aba Authentication. Lá só existe a conta e o User UID. Os dados ficam no Firestore do mesmo projeto que o app usa.

O que procurarOndeNota
Conta de testeAuthentication → UsersCopie o User UID
Cadastro de motoristaFirestore → drivers/{uid}Mesmo {uid} da Authentication
CorridasFirestore → rides/Criadas pela callable requestRide
Push do aparelhoFirestore → users/{uid}/devices/Não é nome do motorista

Teste automatizado: só o GPS é simulado. Pedir, aceitar e mudar status sempre vão pro backend. Se rides/ estiver vazio, confira deploy das functions, secret Mapbox e se drive_api.dart usa a mesma região do functionsRegion no kit_setup.json.

No Supabase, use o schema drive (drivers, rides) no Table Editor.

Testar sem o setup completo

Com withDrive ligado, as telas do Drive abrem mesmo sem token Mapbox (o mapa fica vazio). Para o fluxo ponta a ponta (solicitar, aceitar, iniciar, concluir), você precisa do token no .env, dos secrets configurados e do backend deployado.

SituaçãoO que funciona
Debug sem token MapboxTelas abrem; mapa sem tiles
Debug com token + backend local/deployFluxo completo passageiro + motorista
Release sem tokenMapa quebrado; não publique assim

O que vem na UI

  • Entrada: intro do Drive com escolha de papel na primeira vez (Configurações → Drive); papel fica salvo
  • Passageiro: home com mapa em tela cheia, busca de destino, ajuste de pinos, estimativa e acompanhamento ao vivo
  • Motorista: onboarding do veículo, switch online/offline, overlay de corridas próximas, navegação com rota progressiva e ETA
  • Push: notificações quando uma corrida é criada ou muda de status (Firebase triggers / Supabase equivalente)

Não há sistema de papéis separado: quem tem perfil em drivers/{uid} é motorista; qualquer usuário logado pode pedir corrida.

Atualizado em 03/11/2026