{"id":31626507,"url":"https://github.com/renanjava/fullstack-challenge","last_synced_at":"2026-04-11T05:33:47.206Z","repository":{"id":317930776,"uuid":"1068806358","full_name":"renanjava/fullstack-challenge","owner":"renanjava","description":"Teste Técnico para Desenvolvedor - Controle de tarefas com Apontamento de horas","archived":false,"fork":false,"pushed_at":"2025-10-04T00:19:54.000Z","size":111,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-04T00:27:16.491Z","etag":null,"topics":["nestjs","nodejs","postgresql","prismaorm","rabbitmq","vuejs"],"latest_commit_sha":null,"homepage":"https://trello.com/b/mb8IhClB/fullstack-challenge","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/renanjava.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-03T00:01:45.000Z","updated_at":"2025-10-04T00:19:57.000Z","dependencies_parsed_at":"2025-10-04T00:27:22.172Z","dependency_job_id":"6669694b-9094-4b49-8973-4b33d46593f6","html_url":"https://github.com/renanjava/fullstack-challenge","commit_stats":null,"previous_names":["renanjava/fullstack-challenge"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/renanjava/fullstack-challenge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renanjava%2Ffullstack-challenge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renanjava%2Ffullstack-challenge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renanjava%2Ffullstack-challenge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renanjava%2Ffullstack-challenge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/renanjava","download_url":"https://codeload.github.com/renanjava/fullstack-challenge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renanjava%2Ffullstack-challenge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31670019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-10T17:19:37.612Z","status":"online","status_checked_at":"2026-04-11T02:00:05.776Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nestjs","nodejs","postgresql","prismaorm","rabbitmq","vuejs"],"created_at":"2025-10-06T19:53:05.413Z","updated_at":"2026-04-11T05:33:47.191Z","avatar_url":"https://github.com/renanjava.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Node.js](https://img.shields.io/badge/node.js-v20.12.2-green)\n![NestJS](https://img.shields.io/badge/NestJS-v10.0.0-red)\n![Vue.js](https://img.shields.io/badge/Vue.js-v3.4.0-brightgreen)\n![PostgreSQL](https://img.shields.io/badge/PostgreSQL-v16-blue)\n![Docker](https://img.shields.io/badge/Docker-enabled-blue)\n![Test Coverage](https://img.shields.io/badge/coverage-80%25-brightgreen)\n\n# Time Tracker - Aplicação Fullstack\n\n## 📌 Visão Geral\n\nTime Tracker é uma aplicação fullstack completa para gerenciamento de tempo e tarefas, desenvolvida com **NestJS** no backend e **Vue.js** no frontend. O sistema permite que usuários gerenciem projetos, tarefas, colaboradores e rastreiem o tempo gasto em cada atividade, com autenticação JWT, processamento assíncrono com RabbitMQ e interface responsiva.\n\n---\n\n## 🚀 Tecnologias Utilizadas\n\n### Backend\n\n- **Framework**: NestJS\n- **Linguagem**: TypeScript\n- **ORM**: Prisma\n- **Banco de Dados**: PostgreSQL\n- **Autenticação**: JWT e Bcrypt\n- **Validação**: Class Validator \u0026 Class Transformer\n- **Mensageria**: RabbitMQ\n- **Documentação**: Swagger/OpenAPI\n- **Testes**: Jest (80%+ coverage)\n- **CI/CD**: GitHub Actions\n\n### Frontend\n\n- **Framework**: Vue.js 3 (Composition API + Options API)\n- **Build Tool**: Vite\n- **Estilização**: Bulma CSS\n- **Roteamento**: Vue Router\n- **Ícones**: Lucide Vue Next \u0026 Font Awesome\n\n### DevOps\n\n- **Containerização**: Docker \u0026 Docker Compose\n- **Web Server**: Nginx\n- **Orquestração**: Multi-stage builds\n- **CI/CD**: GitHub Actions com testes automatizados\n\n---\n\n## 📂 Estrutura do Projeto\n\n```plaintext\n/\n├── backend/\n│   ├── src/\n│   │   ├── modules/           # Módulos da aplicação (tasks, projects, users, etc)\n│   │   ├── auth/              # Configuração da autenticação com JWT\n│   │   ├── common/            # Decorators, filters, guards, pipes\n│   │   ├── prisma/            # Configuração Prisma\n│   │   ├── queue/             # Configuração RabbitMQ\n│   │   └── main.ts            # Arquivo principal\n│   ├── prisma/\n│   │   ├── migrations/        # Migrações do banco\n│   │   ├── seed.ts            # Seeds com dados fictícios\n│   │   └── schema.prisma      # Schema do banco\n│   ├── test/                  # Testes unitários e de integração\n│   └── Dockerfile\n│\n├── frontend/\n│   ├── src/\n│   │   ├── api/               # Configuração e chamadas HTTP\n│   │   ├── components/        # Componentes reutilizáveis\n│   │   ├── pages/             # Páginas da aplicação\n│   │   ├── interfaces/        # TypeScript interfaces\n│   │   ├── utils/             # Funções utilitárias\n│   │   ├── router/            # Configuração de rotas\n│   │   └── App.vue\n│   └── Dockerfile\n│\n├── docker-compose.yml\n└── README.md\n```\n\n---\n\n## 🎯 Funcionalidades\n\n### Autenticação e Segurança\n\n- ✅ Login com JWT Token (expiração em 5 minutos)\n- ✅ Hash de senha com Bcrypt através de Pipes customizados\n- ✅ Proteção de rotas com Guards\n- ✅ Refresh token e logout\n- ✅ Validação automática de token no frontend\n\n### Gestão de Projetos\n\n- ✅ CRUD completo de projetos\n- ✅ Associação de tarefas a projetos\n- ✅ Listagem e filtros por projeto\n\n### Gestão de Tarefas\n\n- ✅ CRUD completo de tarefas\n- ✅ Associação de tarefas a projetos e colaboradores (opcional)\n- ✅ Filtros por projeto e colaborador\n- ✅ Soft delete (campo `deletedAt`)\n- ✅ Ativar/desativar registros\n\n### Time Tracker\n\n- ✅ Iniciar/parar rastreamento de tempo com um clique\n- ✅ Validação de conflitos de intervalos de tempo\n- ✅ Validação de horário de início/fim\n- ✅ Processamento assíncrono com RabbitMQ para escalabilidade\n- ✅ Histórico de atividades recentes (últimos 3 registros)\n\n### Relatórios\n\n- ✅ Visualização de horas trabalhadas no dia atual (formato HH:MM)\n- ✅ Visualização de horas trabalhadas no mês atual (formato HH:MM)\n- ✅ Filtros por projeto e colaborador\n- ✅ Cards informativos responsivos\n\n### Gestão de Usuários e Colaboradores\n\n- ✅ CRUD de usuários\n- ✅ CRUD de colaboradores\n- ✅ Composição entre Users e Collaborators (cascade delete)\n- ✅ Campo único em Users conforme regra de negócio\n\n---\n\n## ✅ Validações e Regras de Negócio\n\n- Username único\n- Password criptografado (bcrypt)\n- Não permite time tracker com intervalo de tempo conflitante\n- Task sempre associada a um projeto\n- Colaborador opcional na task\n- Total de horas em um dia ≤ 24h\n- Timezone enviado em toda requisição de time tracker\n- Data de início ≤ data de fim\n- Validação de campos no frontend e backend\n\n---\n\n## 👤 User Stories\n\n- Usuário pode ver/adicionar/editar/excluir projetos\n- Usuário pode ver/adicionar/editar/excluir tarefas\n- Usuário pode associar tarefa a projeto e colaborador\n- Usuário pode filtrar tarefas por projeto/colaborador\n- Usuário pode iniciar/parar time tracker de uma tarefa\n- Usuário vê tempo gasto no dia/mês em destaque (HH:MM)\n- Usuário vê relatório dia-a-dia do mês\n\n---\n\n## 🏗️ Arquitetura e Design Patterns\n\n### Design Patterns Aplicados\n\n#### Backend\n\n- **Singleton Pattern**: Conexão única com banco de dados (padrão NestJS)\n- **Factory Pattern**: Criação de instâncias complexas\n- **Repository Pattern**: Abstração de acesso a dados com Prisma\n- **Decorator Pattern**: Decorators customizados para Swagger\n- **Adapter Pattern**: Pipes para transformação de dados\n- **Observer Pattern**: RabbitMQ para processamento assíncrono\n\n#### Frontend\n\n- **Composition API**: Reutilização de lógica com composables\n- **Component Pattern**: Componentes reutilizáveis e dinâmicos\n- **Observer Pattern**: Sistema de eventos entre componentes\n- **Factory Pattern**: Formulário dinâmico baseado em JSON\n\n### Boas Práticas Implementadas\n\n#### Segurança\n\n- Variáveis sensíveis com `.env` e GitHub Secrets\n- Whitelist em validações (`class-validator`)\n- UUID para IDs únicos e seguros\n- Hash automático de senhas com Pipes\n\n#### Banco de Dados\n\n- Prisma ORM com migrations versionadas\n- Soft delete ao invés de remoção física\n- Delete on cascade para evitar registros órfãos\n- CamelCase no código e snake_case no banco (`@map`)\n- Queries otimizadas com `include` e `count`\n\n#### Performance\n\n- Multi-stage builds no Docker (imagem otimizada)\n- Processamento assíncrono com RabbitMQ\n- Computed properties no Vue para reatividade eficiente\n- Nginx como servidor web para produção\n\n#### Testes\n\n- Testes unitários para services, controllers e repositories\n- Stubs com Faker.js para dados fictícios\n- Mocks para métodos em testes\n- Cobertura de código de 80%+\n- CI/CD com GitHub Actions\n\n#### Código Limpo\n\n- DTOs para input e serialização para output\n- Tratamento centralizado de erros com Global Filter\n- Decorators customizados para reduzir duplicação\n- Typescript para type safety\n- ESLint e Prettier configurados\n\n---\n\n## 🛠️ Instalação e Configuração\n\n### Pré-requisitos\n\n- **Node.js**: v22.20.0 ou superior\n- **Docker**: Para rodar os serviços\n- **Docker Compose**: Para orquestração\n\n### Passos para Instalação\n\n#### 1. Clone o repositório:\n\n```bash\ngit clone https://github.com/renanjava/fullstack-challenge\ncd fullstack-challenge\ncode .\n```\n\n#### 2. Configure as variáveis de ambiente:\n\n**Crie o arquivo .env no Backend** (`backend/.env`):\n\n```env\nDATABASE_URL=\"postgresql://postgres:postgres@postgres:5432/fullstack_challenge?schema=public\"\nDATABASE_NAME=\"fullstack_challenge\"\nJWT_SECRET=\"CAFECOMLEITE\"\nRABBITMQ_URL=amqp://admin:admin123@rabbitmq:5672\nRABBITMQ_QUEUE_TIME_TRACKER=time-tracker-queue\n```\n\n#### 3. Instale as dependências:\n\n```bash\n# Backend\ncd backend\nnpm install\n\n# Frontend\ncd ../frontend\nnpm install\n```\n\n---\n\n## 🖥️ Como Rodar a Aplicação\n\n### Docker Compose\n\nAntes de iniciar a aplicação com o Docker Compose, abra o Docker Desktop e certifique-se de que o Docker está em funcionamento. Isso é necessário para que os containers sejam executados corretamente.\n\n```bash\n# Na raiz do projeto\ndocker-compose up --build\n```\n\nA aplicação estará disponível em:\n\n- **Frontend**: http://localhost:80 (acesse a url pelo docker desktop por causa do NGINX)\n- **Backend**: http://localhost:3000\n- **Swagger**: http://localhost:3000/api\n- **RabbitMQ Management**: http://localhost:15672 (admin/admin123)\n\n## 📚 Principais Rotas da API\n\n### Autenticação\n\n- **POST** `/auth/register` - Criar novo usuário\n- **POST** `/auth/login` - Login (retorna JWT token)\n- **GET** `/auth/profile` - Perfil do usuário autenticado\n\n### Projetos\n\n- **GET** `/projects` - Listar todos os projetos\n- **GET** `/projects/:id` - Listar um projeto\n- **POST** `/projects` - Criar novo projeto\n- **PATCH** `/projects/:id` - Atualizar projeto\n- **DELETE** `/projects/:id` - Soft delete de projeto\n- **PATCH** `/projects/active/:id` - Reativar projeto\n\n### Tarefas\n\n- **GET** `/tasks` - Listar todas as tarefas\n- **GET** `/tasks/:id` - Listar uma tarefa\n- **POST** `/tasks` - Criar nova tarefa\n- **PATCH** `/tasks/:id` - Atualizar tarefa\n- **DELETE** `/tasks/:id` - Soft delete de tarefa\n- **PATCH** `/tasks/active/:id` - Reativar tarefa\n\n### Time Trackers\n\n- **POST** `/time-trackers` - Criar registro de tempo (processado via RabbitMQ)\n- **GET** `/time-trackers/:id` - Listar um registro de tempo\n- **POST** `/time-trackers` - Criar novo registro de tempo\n- **PATCH** `/time-trackers/:id` - Atualizar registro de tempo\n- **DELETE** `/time-trackers/:id` - Soft delete de registro de tempo\n- **PATCH** `/time-trackers/active/:id` - Reativar registro de tempo\n- **GET** `/time-trackers/day/:date` - Horas total em um dia de todos projetos/colaboradores\n- **GET** `/time-trackers/month/:date` - Horas total em um mês de todos projetos/colaboradores\n- **GET** `/time-trackers/project/:id/day/:date` - Horas por projeto/dia\n- **GET** `/time-trackers/project/:id/month/:date` - Horas por projeto/mês\n- **GET** `/time-trackers/collaborator/:id/day/:date` - Horas por colaborador/dia\n- **GET** `/time-trackers/collaborator/:id/month/:date` - Horas por colaborador/mês\n\n### Colaboradores\n\n- **GET** `/collaborators` - Listar todos os colaboradores\n- **GET** `/collaborators/:id` - Listar um colaborador\n- **POST** `/collaborators` - Criar novo colaborador\n- **PATCH** `/collaborators/:id` - Atualizar colaborador\n- **DELETE** `/collaborators/:id` - Soft delete de colaborador\n- **PATCH** `/collaborators/active/:id` - Reativar colaborador\n\n### Usuários\n\n- **GET** `/users` - Listar todas os usuários\n- **GET** `/users/:id` - Listar um usuário\n- **PATCH** `/users/:id` - Atualizar usuário\n- **DELETE** `/users/:id` - Soft delete de usuário\n- **PATCH** `/users/active/:id` - Reativar usuário\n\n- **📖 Documentação completa disponível em**: http://localhost:3000/api (Swagger)\n- **📖 Caso preferir, realize requisições no postman**: [Acesse a coleção do Postman](https://www.postman.com/renan-g-l/fullstack-challenge/collection/8z6hcp3/fullstack-challenge?action=share\u0026creator=30576907)\n\n---\n\n## ⚙️ Testes\n\n### Rodar Testes com Cobertura\n\n```bash\ncd backend\nnpm run test:cov\n```\n\n### Cobertura Atual\n\n- **Statements**: 80%+\n- **Branches**: 80%+\n- **Functions**: 80%+\n- **Lines**: 80%+\n\n---\n\n## 🔄 CI/CD\n\nO projeto utiliza **GitHub Actions** para:\n\n- ✅ Executar testes automaticamente em cada push/PR\n- ✅ Verificar cobertura de código (mínimo 80%)\n- ✅ Executar linter (ESLint)\n- ✅ Feedback rápido para desenvolvedores\n\nConfiguração em `.github/workflows/check.yml`\n\n---\n\n## 🐰 Processamento Assíncrono com RabbitMQ\n\nO sistema utiliza RabbitMQ para processar a criação de time trackers de forma assíncrona:\n\n### Fluxo:\n\n1. **Controller** recebe requisição POST `/time-trackers`\n2. **Service** envia mensagem para fila RabbitMQ\n3. **Worker** consome mensagem da fila\n4. **Repository** salva no banco de dados\n\n### Benefícios:\n\n- 🚀 Escalabilidade horizontal (múltiplos workers)\n- 🛡️ Resiliência (retry automático em caso de falha)\n- ⚡ Performance (resposta rápida ao usuário)\n- 📊 Processamento em lote eficiente\n\n---\n\n## 🎨 Frontend Features\n\n### Componentes Reutilizáveis\n\n- **Notification**: Sistema de notificações com 4 tipos (success, danger, warning, info)\n- **ModalForm**: Formulário dinâmico baseado em JSON\n- **List**: Lista genérica com ações de editar/deletar\n- **Filter**: Componente de filtros reutilizável\n- **DaysAndMonthsWorked**: Cards de relatório responsivos\n\n### Sistema de Eventos\n\n- Comunicação pai-filho via `emit`\n- Watch para observar mudanças de estado\n- Computed properties para reatividade\n\n### Proteção de Rotas\n\n- Guarda de autenticação com JWT\n- Redirecionamento automático para login\n- Validação de token em todas as requisições\n\n---\n\n## 📱 Responsividade\n\nToda a interface é **100% responsiva**, com breakpoints para:\n\n- 📱 Mobile (\u003c 768px)\n- 📱 Tablet (768px - 1024px)\n- 💻 Desktop (\u003e 1024px)\n\n---\n\n## 🗄️ Banco de Dados\n\n### Modelagem\n\n```\nUser (1) ──\u003e (N) Collaborator\nProject (1) ──\u003e (N) Task\nTask (1) ──\u003e (N) TimeTracker\nCollaborator (0..1) ──\u003e (N) TimeTracker\n```\n\n### Features\n\n- Soft delete em todas as entidades principais\n- Cascade delete configurado\n- Índices otimizados para queries frequentes\n- Timezone automático via JavaScript Date\n\n---\n\n## 📊 Seeds\n\nPara popular o banco com dados fictícios:\n- Atualize a .env do backend:\n```env\nDATABASE_URL=\"postgresql://postgres:postgres@localhost:5432/fullstack_challenge?schema=public\"\nDATABASE_NAME=\"fullstack_challenge\"\nJWT_SECRET=\"CAFECOMLEITE\"\nRABBITMQ_URL=amqp://admin:admin123@localhost:5672\nRABBITMQ_QUEUE_TIME_TRACKER=time-tracker-queue\n```\n\n```bash\ncd backend\nnpm install\nnpx prisma db seed\n```\n\nUtiliza **Faker.js** para gerar:\n\n- 20 usuários\n- 20 colaboradores\n- 20 projetos\n- 10~20 tarefas\n- 20 registros de time tracker\n\n- Observação: o seed gerado é apenas dados fictícios para popular o banco de dados, portanto, ele não passa nas validações da service (alguns time trackers terá horários no intervalo de tempo de outro time tracker)\n\n---\n\n## 🔐 Segurança\n\n- ✅ Senhas hasheadas com Bcrypt (salt rounds: 10)\n- ✅ JWT com expiração configurável\n- ✅ Validação de inputs com class-validator\n- ✅ Proteção contra SQL Injection (Prisma ORM)\n- ✅ CORS configurado\n\n---\n\n## 🐳 Docker\n\n### Multi-stage Build\n\nImagens otimizadas para produção:\n\n- Remoção de dev dependencies\n- Build apenas de arquivos necessários\n- Tamanho reduzido da imagem final\n\n### Health Checks\n\nMonitoramento automático da saúde dos containers:\n\n- Backend: endpoint `/`\n- PostgreSQL: verificação de conexão\n- RabbitMQ: verificação de filas\n\n### Volumes\n\nPersistência de dados garantida:\n\n- PostgreSQL: dados do banco\n- RabbitMQ: mensagens e configurações\n\n---\n\n## 📝 Licença\n\nEste projeto foi desenvolvido como parte de um teste técnico.\n\n---\n\n## 👨‍💻 Autor\n\n- GitHub: [@renanjava](https://github.com/renanjava)\n- LinkedIn: [Renan Geraldini Leão](https://linkedin.com/in/renan-g-l)\n- Email: renanleao.f90@hotmail.com\n\n---\n\n## 🙏 Agradecimentos\n\nObrigado pela oportunidade de demonstrar minhas habilidades técnicas através deste projeto!\n\n---\n\n**⭐ Se este projeto foi útil, considere dar uma estrela no repositório!**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenanjava%2Ffullstack-challenge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frenanjava%2Ffullstack-challenge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenanjava%2Ffullstack-challenge/lists"}