01Contexto e problema
Muitos sites de barbearia só mostram um botão de WhatsApp, e o agendamento continua manual. Este projeto simula uma barbearia completa para mostrar como um site pode receber reservas sozinho, sem conflito de horário e sem exigir cadastro do cliente.
02Objetivo
- Agendamento em poucos passos, sem criar conta.
- Impedir que dois clientes reservem o mesmo horário com o mesmo barbeiro.
- Uma área restrita para a equipe consultar os agendamentos.
- Regras de acesso garantidas pelo banco, não só pela interface.
03Solução desenvolvida
Uma SPA em React e TypeScript (Vite) conectada ao Supabase. Serviços, barbeiros, horários e agendamentos ficam no PostgreSQL com Row Level Security. A reserva de um visitante passa por uma função SQL que valida os dados antes de gravar.
04Minha contribuição
Projeto individual: interface e identidade visual, modelagem do banco, políticas de acesso, funções SQL, migrações versionadas e publicação na Vercel.
05Tecnologias e arquitetura
06Principais funcionalidades
- Agendamento: serviço, barbeiro (ou qualquer um disponível), dia entre os próximos dias de funcionamento e horário.
- Sem cadastro: o cliente informa só nome e WhatsApp.
- Horários do dia: horários que já passaram, com margem de 30 minutos, não aparecem para reserva.
- Área da equipe: login pelo Supabase Auth, acesso liberado apenas para perfis de administrador, com a lista de agendamentos, serviço e barbeiro.
- Site institucional: serviços com preço e duração, barbeiros, galeria e localização.
07Desafios técnicos e soluções
Dois clientes no mesmo horário
Solução: um índice único parcial em (barbeiro_id, data, horario), ignorando agendamentos cancelados. O banco recusa a segunda reserva, e a interface traduz o erro 23505 em “Esse horário já foi reservado. Escolha outro.”
Aceitar reservas de visitantes sem abrir a tabela
Solução: visitantes não inserem direto em appointments. Eles chamam a função create_guest_appointment, que exige nome e WhatsApp, recusa datas passadas e confere se o serviço e o barbeiro estão ativos antes de gravar com status pendente.
Separar o que é público do que é da equipe
Solução: Row Level Security em todas as tabelas. O público lê apenas serviços e barbeiros ativos; agendamentos só são visíveis ao próprio cliente ou a administradores, verificados pela função is_admin(). Mesmo com a chave pública do Supabase no navegador, o banco aplica as regras.
08Demonstração
A demo está publicada e permite testar o fluxo de agendamento completo. A barbearia, os barbeiros e o telefone são fictícios.
09Aprendizados e melhorias futuras
O principal aprendizado foi colocar as regras de negócio onde elas não podem ser contornadas: no banco. A interface melhora a experiência, mas quem garante que não haja conflito de horário ou acesso indevido são o índice, a função e as políticas de RLS.
Próximos passos
- Validar no banco se o horário pertence à agenda do barbeiro (tabela
schedules) e bloquear horários passados no servidor, não só na interface. - Separar o componente principal em componentes menores e adicionar testes.
- Permitir à equipe confirmar, concluir ou cancelar agendamentos pelo painel.
