Tech Challenge Final - Pós-Graduação em Front-End Engineering
Este projeto foi desenvolvido como a entrega final para o Hackathon da Pós-Graduação FIAP. A solução visa fornecer aos integrantes da cooperativa FIAP Farms uma visão estratégica de suas vendas e um planejamento assertivo das culturas com maior lucratividade, através de uma aplicação cross-platform (Web e Mobile).
A plataforma FIAP Farms é uma solução completa para gestão de cooperativas agrícolas, oferecendo dashboards inteligentes de vendas e produção, controle de ciclo de vida de produção, sistema de metas e alertas, tudo isso em uma arquitetura robusta e escalável que funciona tanto na web quanto em dispositivos móveis.
- Resumo
- Demonstração da Aplicação
- Features Principais
- Estrutura do Projeto
- Arquitetura do Projeto
- Stack Tecnológica
- Como Executar
- Conceitos Aplicados
- Dashboard de Vendas: Visualização em tempo real dos produtos com maior lucratividade e dados de venda
- Dashboard de Produção: Visualização em tempo real dos dados de produção
- Controle de Produção: Quadro Kanban para acompanhar e gerenciar o ciclo de vida da produção (que gera inventário de produtos)
- Controle de Vendas: Formulários para registrar novas vendas (que consomem o inventário de produtos)
- Sistema de Metas e Alertas: Sistema de alertas que notifica o usuário na UI quando metas de produção ou vendas são atingidas (meta global fixa de 5000 de lucro de vendas e 2000 itens produzidos)
- Autenticação: Sistema completo de autenticação de usuários para proteger os dados de cada cooperado
- Cross-Platform: Aplicação web responsiva e aplicativo móvel nativo com React Native
fiap-farms-hackathon/
├── apps/ # Aplicações
│ ├── web-shell/ # Container app (Next.js)
│ │ ├── pages/ # Páginas e roteamento
│ │ ├── components/ # Componentes específicos do shell
│ │ └── hooks/ # Hooks de navegação e breadcrumbs
│ ├── web-sales/ # Microfrontend de vendas (Next.js)
│ │ ├── pages/ # Dashboard e formulário de vendas
│ │ ├── hooks/ # useSalesManagement, useSalesDashboard
│ │ └── utils/ # Transformers específicos de vendas
│ ├── web-products/ # Microfrontend de produção (Next.js)
│ │ ├── pages/ # Dashboard e gestão de produção
│ │ ├── hooks/ # useProductionManagement, useProductionDashboard
│ │ └── utils/ # Transformers específicos de produção
│ └── mobile/ # App React Native
│ ├── app/ # Estrutura do Expo Router
│ ├── components/ # Componentes mobile (Paper)
│ ├── hooks/ # Hooks mobile
│ └── utils/ # Transformers mobile
├── packages/ # Packages compartilhados
│ ├── core/ # Clean Architecture - Lógica de negócio
│ │ ├── src/domain/ # Entidades e interfaces de repositórios
│ │ ├── src/application/ # Casos de uso
│ │ └── src/infrastructure/ # Implementações Firestore
│ ├── shared-stores/ # Estado global (Zustand)
│ │ ├── src/stores/ # Auth, goals, notifications
│ │ └── src/hooks/ # Hooks para consumir as stores
│ ├── web-ui/ # Biblioteca de componentes web (MUI)
│ │ └── src/components/ # Componentes web reutilizáveis
│ ├── firebase/ # Configuração do Firebase
│ │ └── src/ # Configuração client Firebase
│ ├── functions/ # Firebase Cloud Functions
│ │ └── src/ # Funções serverless
│ └── typescript-config/ # Configurações TypeScript compartilhadas
└── turbo.json # Configuração do Turborepo
A arquitetura deste projeto foi cuidadosamente planejada para ser robusta, escalável, testável e, ao mesmo tempo, pragmática para o escopo de um hackathon. A solução segue princípios modernos de desenvolvimento de software com foco em separação de responsabilidades e reutilização de código.
┌─────────────────────────────────────────────────────────┐
│ APPLICATIONS │
├─────────────────┬─────────────────┬─────────────────────┤
│ Web Shell │ Sales Module │ Products Module │
│ (Container App) │ (Microfrontend) │ (Microfrontend) │
│ Port: 3000 │ Port: 4000 │ Port: 5000 │
├─────────────────┴─────────────────┴─────────────────────┤
│ Mobile App (React Native) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ PACKAGES │
├─────────────────┬─────────────────┬─────────────────────┤
│ @core │ @shared-stores │ @web-ui │
│ (Clean Arch) │ (Zustand) │ (MUI Components) │
├─────────────────┼─────────────────┼─────────────────────┤
│ @firebase │ @typescript- │ │
│ (Configuration) │ config │ │
└─────────────────┴─────────────────┴─────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ FIREBASE BACKEND │
├─────────────────┬─────────────────┬─────────────────────┤
│ Authentication │ Firestore │ Cloud Functions │
│ │ (Database) │ (Automations) │
└─────────────────┴─────────────────┴─────────────────────┘
A aplicação web foi construída seguindo uma arquitetura de Microfrontends, composta por três aplicações Next.js independentes:
apps/web-shell
: A aplicação "container" ou "shell", responsável pelo layout principal, navegação, notificações e autenticaçãoapps/web-sales
: Microfrontend focado no dashboard e formulários de vendasapps/web-products
: Microfrontend focado no dashboard e controle de produção
Essas aplicações fazem o expose de seus entrypoints e o shell as renderiza sob demanda.
Todas as aplicações compartilham instancias de seus pacotes compartilhados como @fiap-farms/core
, @fiap-farms/shared-stores
, @fiap-farms/web-ui
, @fiap-farms/firebase
e funcionam também de forma independente.
O pacote @fiap-farms/core
implementa os princípios da Clean Architecture para manter a separação de responsabilidades e garantir que as regras de negócio sejam independentes de frameworks e ferramentas externas.
packages/core/src/
├── domain/ # Lógica de negócio pura (sem dependências externas)
│ ├── entities/ # Entidades de negócio (Product, Sale, Production, etc.)
│ └── repositories/ # Interfaces dos repositórios (contratos)
├── application/ # Regras de negócio da aplicação
│ └── use-cases/ # Casos de uso orquestrando lógica de domínio
└── infrastructure/ # Preocupações externas (bancos, APIs)
└── repositories/ # Implementações concretas (Firestore)
└── firestore/ # Implementações específicas do Firestore
As dependências apontam apenas para dentro, seguindo o princípio da Clean Architecture:
Infrastructure → Application → Domain
- Infrastructure pode importar de Application e Domain
- Application pode importar apenas de Domain
- Domain não importa nada de outras camadas (lógica de negócio pura)
- Product: Um produto da cooperativa.
- InventoryItem: Um item de inventário da cooperativa.
- ProductionItem: Um item de produção da cooperativa.
- ProductionStatus: Status possíveis de um item de produção da cooperativa.
- Sale: Uma venda da cooperativa.
- SaleItem: Um item de uma venda da cooperativa.
Gestão de Produtos
GetProductsUseCase
- Obter listagem de produtos
Gestão de Inventário
GetInventoryOverviewUseCase
- Obter status atual do inventário
Gestão de Produção
StartNewProductionUseCase
- Criar novos itens de produçãoUpdateProductionStatusUseCase
- Atualizar status de produção de um itemGetProductionOverviewUseCase
- Obter dados gerais de produção atuaisGetSalesDashboardDataUseCase
- Obter dados do dashboard de produção
Gestão de Vendas
RegisterSaleUseCase
- Registrar novas vendasGetSalesDashboardDataUseCase
- Obter dados do dashboard de vendas
// Iniciando uma nova produção
const productionRepo = new FirestoreProductionRepository(db);
const useCase = new StartNewProductionUseCase(productionRepo);
const newProduction = await useCase.execute({
productId: 'product-123',
ownerId: 'user-456',
location: 'Campo A',
expectedHarvestDate: new Date('2024-12-01'),
});
Para o gerenciamento de estado global, foi escolhido o Zustand em vez da Context API por sua simplicidade, performance superior (evitando re-renders desnecessários) e ausência de boilerplate.
useAuthStore
: Gerencia o estado de autenticaçãouseSalesGoal
: Gerencia metas de vendas e notificações de conquistauseProductionGoal
: Gerencia metas de produção e notificações de conquista
O shared-stores implementa um sistema completo de notificações baseado em conquistas de metas de vendas e produção, que funciona de forma consistente tanto na web quanto no mobile.
- Stores de Metas (Goal Stores)
As stores useSalesGoalStore
e useProductionGoalStore
funcionam com listeners em tempo real do Firestore.
- Detecção Automática de Conquistas
As stores monitoram automaticamente quando uma meta é atingida:
- Meta de Vendas: Monitora o
totalSaleProfit
agregado de todas as vendas do usuário - Meta de Produção: Monitora o
yield
agregado de todos os itens colhidos (status: 'harvested'
)
Quando currentProfit >= targetProfit
ou currentYield >= targetYield
, a flag isGoalAchieved
é automaticamente ativada e uma notificação é renderizada.
- Persistência Cross-Platform do Status de Leitura
O hook useNotificationReadState
gerencia o estado de leitura das notificações com persistência automática.
Foi criado um padrão através dos hooks listeners que orquestra o ciclo de vida de todos os listeners da aplicação:
// No root da aplicação
function App() {
useAuthListener(); // Listener de autenticação
useProductionGoalListener(); // Listener de metas de produção
useSalesGoalListener(); // Listener de metas de vendas
return <YourAppContent />;
}
Este padrão garante que todos os listeners sejam ativados no login e desativados no logout de forma atômica, eliminando race conditions.
Tanto as aplicações web quanto a aplicação mobile foram construídas com componentes baseados no Material Design da Google (MUI x Native Paper).
Além disso, a mesma nomenclatura e estrutura visual foi utilizada na construção de componentes, calls to action, ícones, cores, linguagem e demais blocos que formam a identidade das aplicações.
As aplicações web e mobile utilizam o React Hook Form para padronizar a abordagem de validação de formulários.
Todas as aplicações utilizam o DayJS e APIs nativas como toLocaleString
para padronizar as tratativas de apresentação e formatação de datas.
@fiap-farms/core
: Lógica de negócio compartilhada entre web e mobile@fiap-farms/shared-stores
: Estado global consumido por ambas as plataformas- Persistência automática de dados salvos pela store:
localStorage
na web eAsyncStorage
no React Native
- Persistência automática de dados salvos pela store:
@fiap-farms/firebase
: Configuração do Firebase para ambas as plataformas- Configuração unificada de autenticação com persistência cross-platform (
localStorage
xAsyncStorage
)
- Configuração unificada de autenticação com persistência cross-platform (
O projeto segue uma clara separação entre UI concerns e view concerns:
- UI Components: Componentes puros focados apenas na apresentação visual
- View Logic: Hooks customizados que gerenciam estado, efeitos colaterais e lógica de apresentação
- Business Logic: Casos de uso na camada core que são agnósticos de interface
- Transformers como View Models: Utilizamos transformers para converter dados da camada de domínio para formatos adequados à apresentação, atuando como view models que adaptam as entidades de negócio para as necessidades específicas da UI
A plataforma Firebase foi utilizada como BaaS (Backend as a Service):
Sistema completo de autenticação com persistência automática entre sessões.
Banco de dados NoSQL em tempo real com as seguintes coleções:
products
- Catálogo global de produtosproduction_items
- Itens em produção por usuárioinventory
- Inventário agregado por usuáriosales
- Histórico de vendas por usuáriogoals
- Metas configuradas globalmente
A base de dados foi modelada seguindo práticas de desnormalização para otimizar a performance de leitura, com um fluxo de dados causal: Produção → Inventário → Vendas.
// products - Catálogo global de produtos
{
_id: "product_id",
name: "Tomate",
description: "Tomate orgânico",
unit: "kg",
costPerUnit: 5.50
}
// production_items - Itens em produção (por usuário)
{
_id: "production_id",
productId: "product_id",
ownerId: "user_id",
productName: "Tomate",
productUnit: "kg",
status: "planted|in_production|harvested",
plantedDate: "2024-01-15",
expectedHarvestDate: "2024-04-15",
harvestedDate: "2024-04-10", // opcional
yield: 150, // kg colhidos
location: "Campo A",
updatedAt: "2024-04-10"
}
// inventory - Estoque disponível (por usuário, atualizado por Cloud Functions)
{
_id: "inventory_id",
ownerId: "user_id",
productId: "product_id",
productName: "Tomate",
quantity: 150,
unit: "kg",
lastUpdated: "2024-04-10"
}
// sales - Histórico de vendas (por usuário)
{
_id: "sale_id",
ownerId: "user_id",
saleDate: "2024-04-12",
items: [
{
productId: "product_id",
productName: "Tomate",
quantity: 50,
pricePerUnit: 8.50,
totalProfit: 150.00 // calculado por Cloud Function
}
],
totalSaleAmount: 425.00,
totalSaleProfit: 150.00, // calculado por Cloud Function
client: "Restaurante ABC"
}
// goals - Metas globais configuradas
{
_id: "goal_id",
type: "sales|production",
// Um dos:
targetProfit: 2000,
// ou
targetYield: 5000
}
- Produção: Agricultor planta →
production_items
statusplanted
- Colheita: Status muda para
harvested
→ Cloud Function incrementainventory
- Venda: Venda registrada → Cloud Function decrementa
inventory
e calcula lucro - Metas: Listeners monitoram vendas/produção em tempo real para notificações
Funções serverless para lógicas críticas e seguras:
Cálculo de Lucro e Decremento de Inventário
// Acionada onCreate de uma nova venda
export const onSaleCreated = onDocumentCreated(
'sales/{saleId}',
async event => {
// Busca custo do produto e "carimba" o lucro no documento
// Garante integridade histórica e segurança dos dados de custo
// Decrementa quantities do inventory baseado nos itens vendidos
}
);
Incremento de Inventário
// Acionada onUpdated em status de produções
export const onProductionHarvested = onDocumentUpdated(
'production_items/{itemId}',
async event => {
// Detecta mudança para status "harvested"
// Incrementa inventory baseado no yield
}
);
- Next.js: Meta-framework React para aplicações web
- React Native: Framework para desenvolvimento mobile nativo
- TypeScript: Superset JavaScript com tipagem estática
- Material-UI (MUI): Biblioteca de componentes web seguindo Material Design
- MUI X Charts: Componentes de gráficos avançados
- MUI X Data Grid: Tabelas e grids de dados complexos
- React Hook Form MUI: Wrapper para integração do React Hook Form com MUI
- React Native Paper: Biblioteca de componentes mobile Material Design
- React Native Gifted Charts: Biblioteca de gráficos otimizada para React Native
- Zustand: Gerenciamento de estado global leve e performático
- React Hook Form: Biblioteca para formulários performáticos
- DayJS: Biblioteca leve para manipulação de datas
- Turborepo: Ferramenta de build para monorepos com cache inteligente
- Module Federation: Arquitetura de microfrontends com Webpack
- Expo: Plataforma para desenvolvimento React Native
- Firebase: Plataforma BaaS completa
- Authentication: Autenticação de usuários
- Firestore: Banco NoSQL em tempo real
- Cloud Functions: Funções serverless
- Github Actions: Para criar workflows de CI
- ESLint: Linter para qualidade de código
- Prettier: Formatador de código automático
- TypeScript Config: Configurações TypeScript compartilhadas
base.json
: Configuração base para todos os projetosnextjs.json
: Configurações específicas para Next.jsreact-library.json
: Configurações para bibliotecas React
-
Node.js: Versão LTS (22.x) - Download
- Recomendamos o uso do nvm para gerenciar versões
- Se usando nvm:
nvm use
(envm install
se necessário)
-
Para desenvolvimento Mobile:
- Emulador Android/iOS configurado ou dispositivo físico conectado
- Recomendação: scrcpy para espelhar tela Android no computador
# Instalar scrcpy (macOS) brew install scrcpy
# Clone o repositório
git clone [email protected]:K-Schaeffer/fiap-farms-hackathon.git
cd fiap-farms-hackathon
# Sete a versão node do projeto
nvm use
# Instale as dependências (executar na raiz)
npm install
Executar todas as aplicações:
npm run dev
Isso iniciará todas as aplicações simultaneamente:
- Web Shell (Container):
http://localhost:3000
- Web Sales (Microfrontend):
http://localhost:4000
- Web Products (Microfrontend):
http://localhost:5000
- Mobile App: Expo Metro Bundler para desenvolvimento
- Packages: Build automático em watch mode de todas as bibliotecas (
@fiap-farms/core
,@fiap-farms/shared-stores
,@fiap-farms/web-ui
, etc.)
Executar apenas aplicações web:
npm run dev:web
Executar apenas mobile:
npm run dev:mobile
Executar Cloud Functions (desenvolvimento):
npm run dev:functions
Build para produção:
npm run build
Limpeza completa:
npm run clean
Formatação de código:
npm run format
Verificação de lint:
npm run lint
Deploy das Cloud Functions:
npm run deploy:functions
- Clean Architecture: Separação clara de responsabilidades em camadas bem definidas
- Microfrontends: Arquitetura distribuída para aplicações frontend
- Monorepo: Gerenciamento centralizado de múltiplos projetos relacionados
- Cross-Platform Development: Compartilhamento de código entre web e mobile
- Material Design: Guidelines de design consistentes
- Responsive Design: Adaptação para diferentes tamanhos de tela
- Domain-Driven Design (DDD): Modelagem focada no domínio do negócio
- Dependency Injection: Inversão de controle para testabilidade
- Repository Pattern: Abstração da camada de dados
- Use Case Pattern: Orquestração de regras de negócio
- Lazy Loading: Microfrontends carregados sob demanda via Module Federation
- Code Splitting: Chunks automáticos gerados pelo Next.js
- Build Caching: Cache inteligente do Turborepo para builds incrementais
- State Memoization: Zustand evita re-renders desnecessários
- Database Optimizations: Queries Firestore com índices otimizados para performance