Skip to content

Desafio Kanban - Envio do desafio valinor - Pedro Paulo Cividanes#492

Open
Pedro-Paulo-Mendes wants to merge 1 commit intoFieldControl:masterfrom
Pedro-Paulo-Mendes:desafio-kanban-pedro-paulo
Open

Desafio Kanban - Envio do desafio valinor - Pedro Paulo Cividanes#492
Pedro-Paulo-Mendes wants to merge 1 commit intoFieldControl:masterfrom
Pedro-Paulo-Mendes:desafio-kanban-pedro-paulo

Conversation

@Pedro-Paulo-Mendes
Copy link
Copy Markdown

Respostas

Envio de solução


Framework, linguagem e ferramentas

Back-end — kanban-api

Tecnologia Função
NestJS 11 Framework principal da API
TypeScript Linguagem base do projeto
class-validator / class-transformer Validação e transformação dos DTOs
ValidationPipe (global) Proteção contra payloads inválidos ou extras
Jest + Supertest Testes unitários e de integração
ESLint + Prettier Qualidade e padronização do código
Render Hospedagem do servidor

Front-end — kanban-web

Tecnologia Função
Angular 21 Framework principal do cliente
TypeScript Linguagem base do projeto
Angular CDK (DragDropModule) Drag-and-drop nativo entre colunas
RxJS Gerenciamento de chamadas assíncronas à API
FormsModule Two-way binding nos inputs dos modais
Vitest Testes unitários do front-end
ESLint + Prettier Qualidade e padronização do código
Vercel Hospedagem da aplicação web

Técnologias X e Y

NestJS em vez de Express puro
Quando comecei a pensar na arquitetura da API, o Express seria a opção mais simples e rápida. Porém, sem uma estrutura opinada, o código cresce desorganizado — principalmente em projetos separados por módulos como este. O NestJS me deu uma arquitetura consistente desde o início, com injeção de dependência nativa, decorators, separação em módulos (ColumnsModule, CardsModule) e um ciclo de vida claro. Para um desafio onde organização e boas práticas são critérios de avaliação, fazia muito mais sentido.

Angular em vez de React ou Vue
O desafio pedia explicitamente o uso do Angular, então não havia dúvida aqui. Mas mesmo como escolha própria, o Angular se encaixa bem: ele já vem com tudo que preciso (HttpClient, FormsModule, CDK, roteamento), sem precisar montar um ecossistema na mão. O sistema de tipagem forte com TypeScript e a organização por componentes também me ajudam a manter o código legível.

Angular CDK em vez de uma biblioteca de drag-and-drop externa
Optei pelo @angular/cdk em vez de bibliotecas como SortableJS ou ng-drag-drop porque ele é o módulo oficial do ecossistema Angular, mantido pela própria equipe do framework. Isso evita conflitos de versão, atualização quebrada de dependências e edge cases bizarros. O transferArrayItem do CDK resolveu o movimento de cards entre colunas de forma limpa e confiável.

JSON como persistência em vez de um banco de dados
Para o escopo deste desafio, não quis adicionar a complexidade de configurar um banco relacional ou NoSQL. A persistência via arquivo cards.json é suficiente para demonstrar a lógica de CRUD e mantém a API autossuficiente. Já sei que isso tem limitações (discuto isso na seção de melhorias).

Vitest em vez de Karma/Jasmine
O Karma era o test runner padrão do Angular por anos, mas está sendo descontinuado. O Vitest é significativamente mais rápido, tem suporte nativo a ESM e integração direta com o Angular moderno. Faz mais sentido adotar o que está chegando do que manter o que está saindo.


Princípios de software

  • Single Responsibility (SOLID): cada classe tem uma única responsabilidade — o Controller apenas recebe e devolve respostas HTTP, o Service concentra toda a lógica de negócio, e o Entity define a estrutura dos dados.
  • Injeção de Dependência: o ColumnsService recebe o CardsService via construtor, sem criar instâncias manualmente. No Angular, o KanbanService é injetado no componente pelo próprio framework.
  • DTO Pattern: toda entrada de dados passa por um DTO validado (CreateCardDto, UpdateCardDto, etc.), garantindo que payloads inválidos ou maliciosos sejam rejeitados antes de chegar na lógica da aplicação.
  • Código limpo e nomenclatura semântica: nomes como loadColumns, submitCard, requestDeleteColumn e confirmDelete descrevem exatamente o que cada função faz, sem precisar de comentários para explicar.
  • Separação de camadas: API e client são projetos completamente independentes, se comunicando apenas via contrato HTTP. O front não acessa dados diretamente — tudo passa pelo KanbanService.
  • OnPush Change Detection: no Angular, usei ChangeDetectionStrategy.OnPush para que o Angular só re-renderize os componentes quando os dados realmente mudam, evitando re-renders desnecessários.
  • Proteção de input no servidor: o ValidationPipe global com whitelist: true e forbidNonWhitelisted: true garante que nenhum campo não declarado no DTO chegue a ser processado.

Desafios e problemas

CORS entre Vercel e Render
O maior desafio foi a configuração de CORS. Em ambiente de desenvolvimento tudo funcionava perfeitamente, mas ao publicar o front na Vercel e a API no Render os requests começavam a ser bloqueados. Resolvi habilitando o app.enableCors() no main.ts da API e configurando o vercel.json no front-end com os rewrites corretos para o domínio do Render.

Sincronização de estado com o drag-and-drop
Mover um card entre colunas parecia simples visualmente, mas garantir que o columnId do card fosse atualizado corretamente na API (e não apenas na tela) exigiu atenção. A solução foi chamar o kanbanService.updateCard(card) assim que o transferArrayItem do CDK era executado, atualizando o columnId do card antes de passar para o array de destino.

ChangeDetection com OnPush e chamadas assíncronas
Ao usar ChangeDetectionStrategy.OnPush, percebi que as respostas das chamadas HTTP não estavam refletindo na interface automaticamente, já que saem fora do ciclo de detecção do Angular. Resolvi usando NgZone.run() para garantir que as atualizações de estado acontecessem dentro da zona do Angular, forçando o re-render corretamente.

Persistência no Render com sistema de arquivos efêmero
O Render tem um sistema de arquivos efêmero — ou seja, os dados do cards.json são perdidos sempre que o servidor reinicia. Isso é uma limitação conhecida e documentada. Para o escopo do desafio é aceitável, mas já tenho em mente como resolver (veja a próxima seção).


Melhorias e próximas implementações

  • Banco de dados real: substituir o cards.json por um banco como PostgreSQL (via TypeORM ou Prisma), resolvendo o problema de persistência efêmera no Render e abrindo caminho pra queries mais complexas.
  • Autenticação: adicionar um sistema de login com JWT, permitindo que diferentes usuários tenham seus próprios boards sem interferir nos dados uns dos outros.
  • Tempo real com Socket.io: implementar WebSockets para que múltiplos usuários vejam as mudanças no board em tempo real, sem precisar recarregar a página.
  • API em GraphQL: migrar os endpoints REST para GraphQL, permitindo que o front-end busque exatamente os dados que precisa em cada consulta, reduzindo over-fetching.
  • Testes E2E: adicionar testes end-to-end com Playwright ou Cypress para cobrir os fluxos completos da aplicação (criar coluna, adicionar card, mover entre colunas, deletar).
  • Persistência de ordem dos cards: atualmente, a ordem dos cards dentro de uma coluna não é salva. Adicionar um campo order e persistir a posição após cada drag-and-drop.

Vídeo de apresentação

🎬 Assista à gravação do projeto rodando

Gravado com Jam.dev mostrando o projeto hospedado em produção: front na Vercel e back-end no Render.


Sobre você

Oi, sou o Pedro Paulo Mendes Cividanes, tenho 19 anos e sou nativo de São José do Rio Preto.

Estudei no Colégio Anglo Rio Preto e, paralelamente, fiz alguns cursos no SENAI, como Power BI e Java Foundations, que me ajudaram a entrar mais fundo no mundo da tecnologia. Hoje estou no terceiro semestre de Ciências da Computação na UNIP.

Comecei a me interessar por desenvolvimento porque quero ter qualidade de vida com minha família em uma área que me permita trabalhar de casa, sendo próximo das pessoas que amo — e ao mesmo tempo continuar aprendendo sobre como o mundo (e a web) funcionam por baixo dos panos. Automatizar processos e entender o funcionamento real das coisas são as partes que mais me motivam.

Trabalho na prefeitura de Rio Preto na Secretaria Municipal da Educação, onde desenvolvo jogos educativos usados em escolas da cidade. Já fiz projetos para a minha igreja e estou desenvolvendo com alguns amigos um sistema de gerenciamento de estoque. Tudo isso enquanto ainda estou na faculdade, o que tem sido uma escola e tanto.

Meu GitHub é Pedro-Paulo-Mendes.


Outros detalhes

Este foi meu primeiro contato com NestJS de forma mais aprofundada. Já tinha visto o framework em tutoriais, mas construí esta API do zero durante o desafio e aproveitei para entender de verdade o que acontece em cada camada. Foi desafiador e muito enriquecedor ao mesmo tempo.

A aplicação está publicada e funcionando em produção:


📧 pedropmc07@gmail.com
📱 (17) 98227-4524

@Pedro-Paulo-Mendes Pedro-Paulo-Mendes requested a review from a team as a code owner March 25, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant