From 58e5889b89163e47566c0b85f1471684018ec345 Mon Sep 17 00:00:00 2001 From: 230417 <230417@epvc.pt> Date: Tue, 13 Jan 2026 14:53:41 +0000 Subject: [PATCH] Add project report and implement calendar week view component --- RELATORIO_PROJETO.md | 423 ++++++++++++++++++++++++ web/src/components/CalendarWeekView.tsx | 269 +++++++++++++++ web/src/lib/cn.ts | 4 +- web/src/lib/format.ts | 2 +- web/src/pages/Booking.tsx | 236 ++++++------- web/src/pages/Dashboard.tsx | 357 +++++++++++++++++--- 6 files changed, 1107 insertions(+), 184 deletions(-) create mode 100644 RELATORIO_PROJETO.md create mode 100644 web/src/components/CalendarWeekView.tsx diff --git a/RELATORIO_PROJETO.md b/RELATORIO_PROJETO.md new file mode 100644 index 0000000..1583490 --- /dev/null +++ b/RELATORIO_PROJETO.md @@ -0,0 +1,423 @@ +# 📊 Relatório do Projeto Smart Agenda + +**Data:** Janeiro 2025 +**Versão:** 1.0.0 +**Status:** Em Desenvolvimento + +--- + +## 📋 Visão Geral + +O **Smart Agenda** é uma aplicação completa para gestão de agendamentos de barbearias, disponível em duas versões: +- **Mobile:** React Native/Expo (aplicação nativa) +- **Web:** React + TypeScript + Vite (aplicação web responsiva) + +--- + +## 🏗️ Arquitetura do Projeto + +### Estrutura de Pastas + +``` +SmartAgendaMobile/ +├── src/ # Aplicação Mobile (React Native/Expo) +│ ├── components/ # Componentes UI reutilizáveis +│ ├── context/ # Context API (estado global) +│ ├── data/ # Dados mock +│ ├── lib/ # Utilitários +│ ├── navigation/ # Configuração de navegação +│ └── pages/ # Páginas da aplicação +│ +└── web/ # Aplicação Web (React + Vite) + └── src/ + ├── components/ # Componentes UI + ├── context/ # Context API + ├── data/ # Dados mock + ├── lib/ # Utilitários + ├── pages/ # Páginas + └── routes.tsx # Rotas da aplicação +``` + +--- + +## 🎯 Funcionalidades Implementadas + +### 👤 Para Clientes + +1. **Exploração de Barbearias** + - Lista de barbearias disponíveis + - Visualização de detalhes (serviços, produtos, barbeiros) + - Avaliações e informações de localização + +2. **Sistema de Agendamento** + - Seleção de serviço + - Escolha de barbeiro + - Seleção de data e horário + - Validação de disponibilidade em tempo real + - Histórico de agendamentos + +3. **Carrinho de Compras** + - Adicionar produtos ao carrinho + - Agrupamento por barbearia + - Checkout e finalização de pedidos + +4. **Perfil do Usuário** + - Visualização de agendamentos + - Histórico de pedidos + - Gestão de conta + +### 🏪 Para Barbearias + +1. **Dashboard Completo** + - Métricas de faturamento + - Gráficos de receita (Recharts) + - Estatísticas de agendamentos e pedidos + - Filtros por período (hoje, semana, mês, ano) + +2. **Gestão de Agendamentos** + - Visualização de todos os agendamentos + - Alteração de status (pendente, confirmado, concluído, cancelado) + - Filtros por status + +3. **Gestão de Pedidos** + - Visualização de pedidos de produtos + - Alteração de status + - Histórico completo + +4. **CRUD de Serviços** + - Criar, editar e excluir serviços + - Definir preço e duração + - Associar barbeiros aos serviços + +5. **CRUD de Produtos** + - Criar, editar e excluir produtos + - Controlo de stock + - Alertas de stock baixo + +6. **CRUD de Barbeiros** + - Adicionar e remover barbeiros + - Definir especialidades + - Gestão de horários e disponibilidade + +--- + +## 🎨 Design e UI + +### Paleta de Cores Atual +- **Primária:** Indigo/Blue (profissional, moderno) +- **Secundária:** Slate (neutro) +- **Background:** Gradientes suaves +- **Status:** Sistema de badges coloridos + +### Componentes UI Criados + +1. **Componentes Base:** + - `Button` - Botões com variantes (solid, outline, ghost, danger) + - `Card` - Cards com hover effects + - `Input` - Inputs estilizados + - `Badge` - Badges coloridos + - `Tabs` - Sistema de abas + - `Chip` - Chips selecionáveis + - `Dialog` - Modais + +2. **Componentes Específicos:** + - `ShopCard` - Card de barbearia + - `ServiceList` - Lista de serviços + - `ProductList` - Lista de produtos + - `CartPanel` - Painel do carrinho + - `DashboardCards` - Cards do dashboard + - `Header` - Cabeçalho com navegação + - `Shell` - Layout principal + +### Landing Page + +Página inicial desenvolvida com: +- **Hero Section** - Seção principal com CTA +- **Features Grid** - 6 funcionalidades principais +- **Como Funciona** - Passo a passo em 3 etapas +- **Barbearias em Destaque** - Cards de barbearias +- **Benefícios** - Mobile-first e aumento de receita +- **Depoimentos** - Testemunhos de clientes +- **CTA Final** - Chamada para ação + +--- + +## 🔧 Tecnologias Utilizadas + +### Mobile (React Native/Expo) +- **Expo** ~54.0.27 +- **React Native** 0.81.5 +- **React Navigation** - Navegação +- **AsyncStorage** - Persistência +- **Nanoid** - Geração de IDs +- **TypeScript** - Tipagem + +### Web (React + Vite) +- **React** 18.3.1 +- **TypeScript** 5.6.3 +- **Vite** 5.4.10 +- **React Router** v6 - Roteamento +- **Tailwind CSS** 3.4.14 - Estilização +- **Recharts** 2.12.7 - Gráficos +- **Lucide React** 0.473.0 - Ícones +- **Zustand** 4.5.4 - Estado (não utilizado, Context API em uso) +- **Date-fns** 4.1.0 - Manipulação de datas +- **Nanoid** 5.0.7 - Geração de IDs + +--- + +## 💾 Gestão de Estado + +### Context API +- Estado global centralizado em `AppContext` +- Persistência automática em `localStorage` (web) +- Funções para: + - Autenticação (login, logout, registro) + - Gestão de carrinho + - Criação de agendamentos e pedidos + - CRUD completo de serviços, produtos e barbeiros + - Atualização de status + +### Dados Mock +- 2 usuários demo (cliente e barbearia) +- 2 barbearias com serviços, produtos e barbeiros +- Sistema de dados persistente + +--- + +## 🌐 Rotas da Aplicação Web + +1. `/` - Landing Page +2. `/login` - Login +3. `/registo` - Registro +4. `/explorar` - Explorar barbearias +5. `/barbearia/:id` - Detalhes da barbearia +6. `/agendar/:id` - Agendamento +7. `/carrinho` - Carrinho de compras +8. `/perfil` - Perfil do usuário +9. `/painel` - Dashboard da barbearia + +--- + +## 🔐 Sistema de Autenticação + +### Credenciais Demo +- **Cliente:** `cliente@demo.com` / `123` +- **Barbearia:** `barber@demo.com` / `123` + +### Funcionalidades +- Login com validação +- Registro de novos usuários +- Registro de barbearias (cria barbearia automaticamente) +- Logout +- Redirecionamento automático baseado em role + +--- + +## 💰 Sistema de Moeda + +- **Moeda Atual:** EUR (Euros) +- **Locale:** pt-PT +- Formatação automática em toda a aplicação +- Função `currency()` centralizada em `lib/format.ts` + +--- + +## 📱 Responsividade + +- Design **mobile-first** +- Breakpoints Tailwind (md, lg) +- Layout adaptativo +- Navegação mobile com menu hambúrguer +- Componentes responsivos + +--- + +## 📊 Funcionalidades do Dashboard + +### Métricas Principais +- Faturamento total +- Agendamentos do período +- Pedidos do período +- Produtos com stock baixo + +### Gráficos +- Gráfico de barras de receita por período +- Visualização de tendências + +### Gestão +- Tabs para navegação entre seções +- Filtros por período +- Ações rápidas (CRUD) + +--- + +## 🛠️ Melhorias Realizadas (Nesta Sessão) + +1. **Landing Page Desenvolvida** + - Página inicial completa e profissional + - Múltiplas seções com conteúdo rico + - Design moderno e atraente + +2. **Paleta de Cores Atualizada** + - Mudança de Amber para Indigo/Blue + - Atualização em todos os componentes + - Documentação de opções de cores criada + +3. **Correções Técnicas** + - Correção de erro TypeScript em `cn.ts` + - Configuração do servidor Vite para acesso externo + - Ajustes de lint + +4. **Documentação** + - Criação de `OPCOES_CORES.md` com 6 paletas alternativas + - Documentação de como aplicar novas cores + +5. **Moeda Atualizada** + - Mudança de BRL (Reais) para EUR (Euros) + - Formatação atualizada em toda a aplicação + +--- + +## 📝 Arquivos de Documentação + +1. **README.md** - Documentação principal do projeto mobile +2. **web/README.md** - Documentação da aplicação web +3. **web/OPCOES_CORES.md** - Opções de paletas de cores +4. **CONECTAR_ANDROID.md** - Instruções para conectar Android +5. **RELATORIO_PROJETO.md** - Este relatório + +--- + +## 🚀 Como Executar + +### Aplicação Web +```bash +cd web +npm install +npm run dev +# Acesse http://localhost:5173 +``` + +### Aplicação Mobile +```bash +npm install +npm start +# Escolha a plataforma (a/i/w) +``` + +--- + +## 📈 Estatísticas do Projeto + +### Arquivos Criados +- **Páginas:** 9 (Landing, Login, Register, Explore, ShopDetails, Booking, Cart, Profile, Dashboard) +- **Componentes UI:** 7 componentes base +- **Componentes Específicos:** 5 componentes +- **Context:** 1 (AppContext completo) +- **Utilitários:** 2 (format, storage) + +### Linhas de Código (Estimativa) +- Aproximadamente 3.000+ linhas de código TypeScript/TSX +- Componentes bem estruturados e reutilizáveis + +--- + +## ✅ Status das Funcionalidades + +### ✅ Completas +- [x] Autenticação (login/registro) +- [x] Exploração de barbearias +- [x] Sistema de agendamento +- [x] Carrinho de compras +- [x] Dashboard completo +- [x] CRUD de serviços +- [x] CRUD de produtos +- [x] CRUD de barbeiros +- [x] Gestão de agendamentos +- [x] Gestão de pedidos +- [x] Landing page +- [x] Design responsivo +- [x] Persistência de dados + +### 🔄 Em Desenvolvimento +- [ ] Melhorias no fluxo de agendamento (separação por etapas) +- [ ] Validações adicionais +- [ ] Testes automatizados + +### 📋 Futuras Melhorias +- [ ] Integração com API real +- [ ] Sistema de notificações +- [ ] Pagamentos online +- [ ] Sistema de avaliações +- [ ] Chat/suporte +- [ ] App mobile nativo completo + +--- + +## 🎨 Opções de Cores Disponíveis + +Documentadas em `web/OPCOES_CORES.md`: +1. Azul/Indigo (atual) ✅ +2. Âmbar/Amarelo +3. Verde/Emerald +4. Roxo/Violet +5. Vermelho/Rose +6. Ciano/Sky +7. Laranja/Orange + +--- + +## 🔍 Próximos Passos Sugeridos + +1. **Melhorar Fluxo de Agendamento** + - Separar etapas (serviço → barbeiro → data/hora) + - Melhorar UX do processo + +2. **Validações** + - Validação de formulários + - Mensagens de erro mais claras + - Validação de horários disponíveis + +3. **Testes** + - Testes unitários + - Testes de integração + - Testes E2E + +4. **Performance** + - Otimização de imagens + - Lazy loading + - Code splitting + +5. **Acessibilidade** + - ARIA labels + - Navegação por teclado + - Contraste de cores + +--- + +## 📞 Informações Técnicas + +### Portas Utilizadas +- **Web:** 5173 (Vite dev server) +- **Mobile:** Expo padrão + +### Estrutura de Dados +- Tipos TypeScript bem definidos +- Interfaces claras e documentadas +- Validação de tipos em tempo de compilação + +### Persistência +- **Web:** localStorage +- **Mobile:** AsyncStorage + +--- + +## 📄 Licença + +Projeto privado - Todos os direitos reservados + +--- + +**Última Atualização:** Janeiro 2025 +**Versão do Relatório:** 1.0 diff --git a/web/src/components/CalendarWeekView.tsx b/web/src/components/CalendarWeekView.tsx new file mode 100644 index 0000000..798fbbb --- /dev/null +++ b/web/src/components/CalendarWeekView.tsx @@ -0,0 +1,269 @@ +import { useMemo, useState, useEffect } from 'react'; +import { ChevronLeft, ChevronRight, ZoomIn, ZoomOut, RefreshCw } from 'lucide-react'; +import { Appointment, BarberShop } from '../types'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; + +type CalendarWeekViewProps = { + week: Date; + appointments: Appointment[]; + shop: BarberShop; + onWeekChange: (date: Date) => void; + onStatusChange: (id: string, status: Appointment['status']) => void; +}; + +export const CalendarWeekView = ({ + week, + appointments, + shop, + onWeekChange, + onStatusChange, +}: CalendarWeekViewProps) => { + const [currentTime, setCurrentTime] = useState(new Date()); + + // Atualizar hora atual a cada minuto + useEffect(() => { + const interval = setInterval(() => { + setCurrentTime(new Date()); + }, 60000); + return () => clearInterval(interval); + }, []); + + // Obter dias da semana + const weekDays = useMemo(() => { + const startOfWeek = new Date(week); + const day = startOfWeek.getDay(); + const diff = startOfWeek.getDate() - day + (day === 0 ? -6 : 1); // Segunda-feira + startOfWeek.setDate(diff); + + const days = []; + for (let i = 0; i < 7; i++) { + const date = new Date(startOfWeek); + date.setDate(startOfWeek.getDate() + i); + days.push(date); + } + return days; + }, [week]); + + // Gerar slots de horário (08:00 até 18:00, intervalos de 30 minutos) + const timeSlots = useMemo(() => { + const slots: string[] = []; + for (let hour = 8; hour <= 18; hour++) { + slots.push(`${hour.toString().padStart(2, '0')}:00`); + if (hour < 18) { + slots.push(`${hour.toString().padStart(2, '0')}:30`); + } + } + return slots; + }, []); + + // Formatar data para YYYY-MM-DD + const formatDateKey = (date: Date) => { + return date.toISOString().split('T')[0]; + }; + + // Obter agendamentos para um dia e horário específicos + const getAppointmentsAtSlot = (date: Date, timeSlot: string) => { + const dateKey = formatDateKey(date); + return appointments.filter((apt) => { + const aptDate = apt.date.split(' ')[0]; + const aptTime = apt.date.split(' ')[1]?.substring(0, 5); + return aptDate === dateKey && aptTime === timeSlot; + }); + }; + + // Navegação de semana + const goToPreviousWeek = () => { + const newDate = new Date(week); + newDate.setDate(newDate.getDate() - 7); + onWeekChange(newDate); + }; + + const goToNextWeek = () => { + const newDate = new Date(week); + newDate.setDate(newDate.getDate() + 7); + onWeekChange(newDate); + }; + + const goToToday = () => { + onWeekChange(new Date()); + }; + + // Verificar se é hoje + const isToday = (date: Date) => { + const today = new Date(); + return ( + date.getDate() === today.getDate() && + date.getMonth() === today.getMonth() && + date.getFullYear() === today.getFullYear() + ); + }; + + // Obter posição da linha de hora atual + const getCurrentTimePosition = (date: Date) => { + if (!isToday(date)) return null; + const now = currentTime; + const hours = now.getHours(); + const minutes = now.getMinutes(); + const totalMinutes = hours * 60 + minutes; + const startMinutes = 8 * 60; // 08:00 + const slotIndex = Math.floor((totalMinutes - startMinutes) / 30); + if (slotIndex < 0 || slotIndex >= timeSlots.length) return null; + return slotIndex; + }; + + // Nomes dos dias da semana + const dayNames = ['Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb', 'Dom']; + const dayNamesFull = ['Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado', 'Domingo']; + + return ( +
Escolha primeiro o barbeiro e a data.
+ ) : availableSlots.length > 0 ? ( + availableSlots.map((h) => ( + + )) + ) : ( +Nenhum horário disponível para esta data.
+ )}Escolha primeiro a data.
- ) : availableSlots.length > 0 ? ( - availableSlots.map((h) => ( - - )) - ) : ( -Nenhum horário disponível para esta data.
- )} -{svc?.name ?? 'Serviço'}
-{barber?.name ?? 'Barbeiro'} · {a.date}
-{currency(a.total)}
+ + {/* List View */} + {appointmentView === 'list' && ( +Nenhum agendamento no período
+Total de marcações
+{totalBookingsToday}
+ + +Novos clientes
+{newClientsToday}
+Marcações online
+{onlineBookingsToday}
+Ocupação
+{occupancyRate}%
+Cliente
+{customer?.name || 'Cliente'}
+{customer?.email || ''}
+Serviço
+{svc?.name ?? 'Serviço'}
+{barber?.name ?? 'Barbeiro'}
+Data e Hora
+{dateStr}
+{timeStr}
+Status
+{currency(a.total)}
+Sem reservas
++ Ambas as suas reservas online e manuais aparecerão aqui +
+