Sistema fullstack de agendamento para barbearias com painel dedicado para clientes e barbeiros, desenvolvido com React 19, Node.js, PostgreSQL e TypeScript.
Sobre o projeto: Este projeto foi desenvolvido de forma independente por José Hermes. Durante o processo, foram utilizadas ferramentas de IA como assistentes de apoio — Claude (Anthropic) para orientação arquitetural e revisão de código. Todo o planejamento, decisões técnicas e implementação foram conduzidos pelo autor.
- Visão Geral
- Tecnologias
- Funcionalidades
- Requisitos
- Instalação
- Deploy
- Testes
- Estrutura do Projeto
- Documentação da API
- Contribuindo
O BarberSync resolve o problema de fricção no agendamento de serviços de barbearia:
- 👤 Clientes escolhem o serviço, data e hora, e acompanham o status em tempo real
- 💈 Barbeiros recebem agendamentos, confirmam/recusam e marcam como concluído
- 🔔 Sistema de notificação e validação para evitar conflitos de horário
- 🛡️ Autenticação JWT com roles (cliente/barbeiro)
1. Cliente se cadastra e realiza login
↓
2. Cliente escolhe serviço, data e hora
↓
3. Sistema valida data retroativa e conflito de horário
↓
4. Barbeiro recebe o agendamento como "Pendente"
↓
5. Barbeiro aceita/recusa ou marca como concluído
↓
6. Cliente acompanha status em tempo real no dashboard
| Tecnologia | Versão | Uso |
|---|---|---|
| React | 19.2.4 | UI moderna e reativa |
| React Router | 7.12.0 | Navegação e rotas protegidas |
| TypeScript | 5.9.2 | Tipagem estática |
| React Hook Form | 7.71.2 | Gerenciamento de formulários |
| SCSS | (Embedded) | Estilização modular (padrão 7-1) |
| Axios | 1.13.6 | Cliente HTTP |
| Tailwind CSS | 4.1.13 | Utility-first CSS |
| Tecnologia | Versão | Uso |
|---|---|---|
| Node.js | ≥18 | Runtime JavaScript |
| Express | 5.2.1 | Framework web |
| PostgreSQL | 12+ | Banco relacional |
| JWT | 9.0.3 | Autenticação |
| Bcrypt | 6.0.0 | Hash seguro de senhas |
| Joi | latest | Validação de schemas |
| Jest | 30.3.0 | Framework de testes |
| Supertest | 7.2.2 | Testes de integração HTTP |
- ✅ Cadastro e login com validação de email
- ✅ Autenticação JWT com expiração configurável
- ✅ Proteção de rotas por perfil (cliente/barbeiro)
- ✅ Hash seguro de senhas com bcrypt (10 rounds)
- ✅ Criação de agendamentos com validação de data retroativa
- ✅ Verificação de conflito de horário (double booking)
- ✅ Seleção de serviço com preço e duração
- ✅ Adição de notas/observações
- ✅ Listar todos seus agendamentos
- ✅ Ver detalhes: serviço, data, status, preço
- ✅ Cancelar agendamentos (soft delete)
- ✅ Acompanhar status em tempo real
- ✅ Listar todos os agendamentos do dia
- ✅ Ver informações do cliente (nome, email)
- ✅ Aceitar, recusar ou marcar como concluído
- ✅ Filtrar por status (pendente, confirmado, etc)
pending→ Aguardando confirmação do barbeiroconfirmed→ Barbeiro confirmou o agendamentocompleted→ Serviço realizadocancelled→ Agendamento cancelado
- Node.js ≥ 18.0.0
- npm ≥ 9.0.0 ou yarn ≥ 3.0.0
- PostgreSQL ≥ 12.0
- Git
Verifique suas versões:
node --version
npm --version
psql --versiongit clone https://github.com/Neto13k/barber-sync.git
cd barber-synccd backend
npm installCrie o arquivo .env baseado em .env.example:
# Servidor
PORT=3000
NODE_ENV=development
# Banco de Dados
DB_USER=seu_usuario
DB_HOST=localhost
DB_NAME=barber_sync
DB_PASSWORD=sua_senha
DB_PORT=5432
# JWT
JWT_SECRET=sua_chave_secreta_muito_segura_aqui
JWT_EXPIRE=1h.env. Use .env.example como template.
Crie o banco de dados e as tabelas:
# Conectar ao PostgreSQL e criar database
psql -U seu_usuario -h localhost
# No prompt psql:
CREATE DATABASE barber_sync;
\q
# Executar script SQL
psql -U seu_usuario -d barber_sync -f backend/database/database.sqlInicie o servidor:
npm run dev✅ Server rodando em: http://localhost:3000
cd frontend
npm install
npm run dev✅ Frontend rodando em: http://localhost:5173
O projeto está em produção e pode ser acessado em:
🔗 https://barber-sync-nu.vercel.app/
| Camada | Plataforma | Observação |
|---|---|---|
| Frontend | Vercel | Build automático a cada push na main |
| Backend | Render | Serviço Web com Node.js |
| Banco de Dados | Render PostgreSQL | Instância gerenciada pelo Render |
Vercel (Frontend)
| Variável | Valor |
|---|---|
VITE_API_URL |
https://barber-sync.onrender.com |
Render (Backend)
| Variável | Descrição |
|---|---|
DATABASE_URL |
String de conexão interna do PostgreSQL (gerada pelo Render) |
JWT_SECRET |
Chave secreta para assinatura dos tokens JWT |
NODE_ENV |
production |
PORT |
Injetado automaticamente pelo Render |
node backend/server/server.js
- O plano gratuito do Render suspende o serviço após 15 minutos de inatividade. A primeira requisição pode levar até 60 segundos.
- Variáveis de ambiente adicionadas no Vercel só são aplicadas após um novo deploy.
O projeto inclui testes de integração cobrindo os fluxos críticos:
cd backend
npm testnpm run test:watchnpm run test:coverage✅ Autenticação
- Registro com sucesso
- Email duplicado (erro 409)
- Login válido com token
- Email inexistente (erro 404)
- Senha incorreta (erro 401)
✅ Agendamentos
- Listar serviços (rota pública)
- Criar agendamento sem token (erro 401)
- Data retroativa (erro 400)
- Conflito de horário (erro 409)
- Criar agendamento válido
- Acesso negado para cliente alterar status
- Barbeiro confirmar/recusar/concluir
✅ Autorização
- Apenas barbeiros podem ver todos os agendamentos
- Cliente só vê seus próprios agendamentos
barber-sync/
├── backend/
│ ├── server/
│ │ └── server.js # Configuração principal do Express
│ ├── routes/
│ │ ├── user.routes.js # Rotas de autenticação
│ │ └── appointment.routes.js # Rotas de agendamento
│ ├── controllers/
│ │ ├── userController.js # Lógica de autenticação
│ │ └── appointmentController.js # Lógica de agendamento
│ ├── middleware/
│ │ ├── authMiddleware.js # Validação JWT
│ │ ├── validateRequest.js # Validação de entrada
│ │ └── errorHandler.js # Tratamento de erros global
│ ├── validators/
│ │ ├── userValidator.js # Schemas Joi para usuários
│ │ └── appointmentValidator.js # Schemas Joi para agendamentos
│ ├── database/
│ │ ├── barber_sync.js # Pool de conexão PostgreSQL
│ │ └── database.sql # Schema e seed do banco
│ ├── tests/
│ │ ├── setup.js # Configuração de testes
│ │ ├── unit/
│ │ │ └── authMiddleware.test.js
│ │ └── integration/
│ │ ├── users.test.js
│ │ └── appointments.test.js
│ ├── .env.example # Template de variáveis
│ └── package.json
│
├── frontend/
│ ├── src/
│ │ ├── routes/ # Páginas e rotas
│ │ ├── components/ # Componentes reutilizáveis
│ │ ├── hooks/ # Custom React hooks
│ │ ├── services/ # Chamadas à API
│ │ ├── styles/ # SCSS (padrão 7-1)
│ │ └── App.tsx
│ ├── public/ # Assets estáticos
│ └── package.json
│
└── README.md
http://localhost:3000
Todas as rotas autenticadas requerem header:
Authorization: Bearer <seu_token_jwt>
| Método | Endpoint | Descrição | Autenticação |
|---|---|---|---|
| POST | /users/register |
Cadastro de novo usuário | ❌ Não |
| POST | /users/login |
Login e gerar token JWT | ❌ Não |
POST /users/register
{
"firstName": "Jose",
"lastName": "Silva",
"email": "jose@example.com",
"password": "senha123456",
"isBarber": false
}POST /users/login
{
"email": "jose@example.com",
"password": "senha123456"
}Resposta (201):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"firstName": "Jose",
"lastName": "Silva",
"email": "jose@example.com",
"isBarber": false
}
}| Método | Endpoint | Descrição | Autenticação |
|---|---|---|---|
| GET | /appointments/services |
Listar serviços | ❌ Não |
| POST | /appointments |
Criar agendamento | ✅ Sim |
| GET | /appointments |
Meus agendamentos | ✅ Sim |
| GET | /appointments/all |
Todos (apenas barbeiro) | ✅ Sim |
| PUT | /appointments/:id |
Atualizar status | ✅ Sim |
| DELETE | /appointments/:id |
Cancelar agendamento | ✅ Sim |
POST /appointments
{
"serviceId": 1,
"appointmentDate": "2026-06-25T10:30:00Z",
"notes": "Gostaria de um acabamento especial"
}GET /appointments/services — Resposta (200):
[
{
"id": 1,
"title": "Corte na máquina",
"description": "Serviço rápido e preciso",
"price": "10.00",
"duration_minutes": 20
}
]┌──────────────────┐
│ USERS │
├──────────────────┤
│ id (PK) │
│ first_name │
│ last_name │
│ email (UNIQUE) │
│ password │
│ is_barber │
│ created_at │
└────────┬─────────┘
│ 1
│ N
┌────▼──────────────────┐
│ APPOINTMENTS │
├───────────────────────┤
│ id (PK) │
│ client_id (FK) │
│ service_id (FK) │
│ appointment_date │
│ notes │
│ status │
│ created_at │
└────┬──────────┬───────┘
│ │ 1
│ ┌───▼──────────────┐
│ │ SERVICES │
│ ├──────────────────┤
│ │ id (PK) │
│ │ title │
│ │ description │
│ │ price │
│ │ duration_minutes │
│ │ created_at │
│ └──────────────────┘
│ N
CREATE INDEX idx_appointments_client_id ON appointments(client_id);
CREATE INDEX idx_appointments_appointment_date ON appointments(appointment_date);
CREATE INDEX idx_appointments_status ON appointments(status);Contribuições são bem-vindas! Por favor:
- Faça um Fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/AmazingFeature) - Commit suas mudanças (
git commit -m 'Add some AmazingFeature') - Push para a branch (
git push origin feature/AmazingFeature) - Abra um Pull Request
feat: adiciona nova funcionalidade
fix: corrige bug existente
docs: atualiza documentação
refactor: refatora código sem alterar funcionalidade
test: adiciona ou atualiza testes
style: mudanças de formatação (não afeta lógica)
chore: tarefas de manutenção
Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.
Jose Neto | Desenvolvedor Full Stack
Encontrou um bug? Abra uma issue no GitHub.
Última atualização: Junho 2026