eStock – Sistema de Controle de Estoque
2025Sistema de gestão de estoque em tempo real desenvolvido para pequenas empresas. Catálogo de produtos com taxonomia marca/modelo/nome no Firebase, controle de quantidades, operações em lote, importação CSV e exportação de lista formatada — tudo protegido por Firebase Auth com estado de sessão persistido via Redux.
eStock é um sistema de controle de estoque baseado em navegador, criado para pequenas empresas que precisam de uma alternativa confiável a planilhas e listas no WhatsApp. Os produtos são armazenados no Firestore com uma taxonomia de três níveis (marca → modelo → nome), com quantidades rastreadas em tempo real entre sessões, e equipes podem exportar listas de estoque formatadas com um único clique. Todo o app é protegido por Firebase Auth com persistência de sessão — um refresh na página não exige novo login.
Pequenas empresas de varejo e distribuição no Brasil frequentemente controlam estoque por planilhas compartilhadas ou mensagens informais no WhatsApp. Esses sistemas quebram rapidamente: edições simultâneas causam perda de dados, não existe histórico de alterações de quantidade, e gerar uma lista formatada de produtos para fornecedor ou cliente exige trabalho manual de copiar e colar. O eStock foi criado para substituir esse fluxo por um app web estruturado e em tempo real.
Construir um sistema de estoque multiusuário que: (1) organize produtos por marca, modelo e nome para filtragem rápida; (2) suporte incrementos e decrementos de quantidade com validação (sem estoque negativo); (3) permita importação em lote via CSV para migração inicial de dados; (4) gere listas de texto formatadas prontas para colar em mensagens ou emails; (5) não exija infraestrutura de backend além do Firebase.
- ◈Desenvolvedor solo — arquitetura, frontend, modelagem de dados, integração Firebase
- 01Firebase Firestore como banco de dados principal — o modelo de subscription em tempo real do Firestore faz com que qualquer atualização de quantidade seja refletida imediatamente em todas as sessões abertas, sem polling manual. Sua estrutura de documentos e coleções mapeia naturalmente para a taxonomia marca/modelo/nome, e as regras de segurança do Firebase Auth + Firestore aplicam acesso por linha sem necessidade de um backend dedicado.
- 02Redux Toolkit + Redux Persist para estado global — em vez de usar Context API ou estado local para a lista de produtos, o Redux Toolkit fornece atualizações de estado previsíveis e serializáveis com async thunks para operações no Firestore. O Redux Persist serializa o store no localStorage para que a lista sobreviva a refreshes — importante para conexões lentas onde um fetch a cada carregamento degradaria a UX.
- 03UI otimista para atualizações de quantidade — o thunk updateProductQuantity despacha a nova quantidade para o Redux imediatamente e depois escreve no Firestore. Se a escrita falhar, um dispatch compensatório reverte o estado local ao valor anterior. Isso faz os incrementos de quantidade parecerem instantâneos mesmo em conexões lentas.
- 04Bibliotecas de UI duplas: Ant Design + Material UI — o componente Table do Ant Design foi escolhido para o StockManagement por ter ordenação multi-coluna, filtros e paginação embutidos. O Material UI foi usado para outros componentes de layout e formulário onde seu design system se adequava melhor. Misturar bibliotecas aumenta o bundle, mas os ganhos de produtividade justificaram para uma ferramenta de negócios.
- 05Formik + Yup para validação de formulários — o formulário AddProduct tem validação não trivial: a quantidade deve ser positiva na primeira criação, marca e modelo podem ser selecionados de valores existentes ou digitados como novos. Os schemas Yup expressam essas regras de forma declarativa e se integram bem ao sistema de exibição de erros por campo do Formik.
- 06Importação CSV com PapaParse e file input por ref — a importação CSV em lote usa o PapaParse para transformar arquivos selecionados no navegador em objetos de produto escritos no Firestore. O elemento de input de arquivo fica oculto e é acionado programaticamente via forwardRef, mantendo a UI limpa — um botão visível na toolbar aciona o input oculto sem expor o estilo nativo do file input.
- 07Taxonomia de três níveis (marca → modelo → nome) — em vez de um único campo de nome de produto, os produtos são organizados por marca, modelo e nome específico. Essa estrutura permite que o recurso de exportação de lista filtre e agrupe em qualquer nível, além de prevenir duplicatas ambíguas — a verificação de unicidade consulta os três campos juntos antes de permitir a criação de um novo produto.
- 08Exportação de lista formatada para compartilhamento no mundo real — a página ListExport converte os produtos filtrados em uma string de texto simples (opcionalmente incluindo quantidades) e copia para a área de transferência. Os donos de negócio precisavam colar listas de estoque em mensagens de WhatsApp, e-mails para fornecedores e formulários de pedido. O toggle para incluir ou não as quantidades atende a ambos os casos de uso.
- 09AuthObserver + hook de timeout de sessão — um componente AuthObserver se inscreve no onAuthStateChanged do Firebase na raiz do app, sincronizando o estado de autenticação com o Redux sem prop drilling. Um hook useSessionTimeout separado desloga automaticamente o usuário após um período configurável de inatividade — importante para dispositivos compartilhados em armazéns ou ambientes de varejo.
- →Atualizações otimistas melhoram significativamente a performance percebida para ações de alta frequência como ajustes de estoque — mas exigem lógica de rollback cuidadosa para manter UI e banco sincronizados quando escritas falham.
- →As regras de segurança do Firestore são uma preocupação de arquitetura de primeira classe: defini-las antecipadamente junto com o modelo de dados evitou ter que refatorar o controle de acesso no meio do projeto.
- →Misturar Ant Design e MUI no mesmo projeto é gerenciável, mas requer escopo intencional — ambas as bibliotecas injetam resets CSS globais e seus sistemas de theming não se compõem nativamente.
- →A superfície de configuração do PapaParse é ampla o suficiente para lidar com CSVs do mundo real bagunçados (cabeçalhos inconsistentes, espaços extras), mas validar e mapear as linhas para o modelo de dados ainda exige lógica de transformação explícita.
- →O Redux Persist resolve o problema de UX do refresh de página de forma elegante, mas serializar grandes listas de produtos no localStorage pode causar latência de hidratação no carregamento inicial — vale medir antes de habilitar o persistReducer em datasets grandes.
Funcional — implantado e utilizado em produção por um cliente de pequena empresa