Skip to content

mpraes/webapp_gas_mais_barato

Repository files navigation

🔥 Gás Mais Barato

Plataforma inteligente de comparação de preços de GLP com foco em Economia Real

Compare preços de gás de cozinha (GLP 13kg) em sua cidade e descubra quanto você pode economizar. Dados oficiais da ANP, atualizados semanalmente.

Next.js TypeScript License


✨ Destaques

🎯 Foco em Economia Real

Não mostramos apenas preços - mostramos quanto você pode economizar:

  • 💰 Economia Potencial: R$ 29,50 por botijão = R$ 354,00/ano
  • 📊 Contexto Percentual: Economize até 24% escolhendo o posto mais barato
  • 📈 Distribuição de Preços: Visualização de quartis para entender o mercado
  • 🎯 Benchmark Inteligente: Mediana como referência de "preço justo"

⚡ Performance e Robustez

  • Server Components: Renderização instantânea no servidor
  • Cache Inteligente: 30 minutos de TTL para dados da ANP
  • Error Boundaries: Nunca mostra tela branca ao usuário
  • SEO Otimizado: Metadata dinâmica por cidade + JSON-LD
  • 100% Responsivo: 8 breakpoints customizados (mobile → ultra-wide)

📊 Business Intelligence

11 métricas calculadas automaticamente:

  • Preço mínimo, máximo, médio e mediano
  • Economia potencial (absoluta e percentual)
  • Volatilidade do mercado
  • Distribuição estatística (quartis Q1, Q2, Q3)
  • Desvio padrão e confiança dos dados

🚀 Demo

https://gasmaisbarato.com

Screenshots

┌─────────────────────────────────────────┐
│  🔥 Gás Mais Barato                     │
│  ┌───────────────────────────────────┐  │
│  │ 🔍 Buscar cidade...               │  │
│  └───────────────────────────────────┘  │
├─────────────────────────────────────────┤
│  💰 Economia Potencial: R$ 29,50        │
│     R$ 354,00/ano (24% de economia)     │
├─────────────────────────────────────────┤
│  📊 Distribuição de Preços              │
│  [Verde════Mediana════Vermelho]        │
│  R$ 95,50    R$ 107,00    R$ 125,00    │
├─────────────────────────────────────────┤
│  💡 Dica: Busque postos abaixo da       │
│     mediana (R$ 107,00) para garantir   │
│     bom custo-benefício                 │
└─────────────────────────────────────────┘

🏗️ Arquitetura

Stack Tecnológica

  • Framework: Next.js 14.2 (App Router)
  • Language: TypeScript 5.4 (Strict Mode)
  • Styling: Tailwind CSS 3.4
  • Icons: Lucide React
  • Data Processing: csv-parse
  • Testing: Vitest + Testing Library

Estrutura de Diretórios

webapp_gas_mais_barato/
├── app/                          # Next.js App Router
│   ├── layout.tsx                # Layout raiz + SEO metadata
│   ├── page.tsx                  # Página principal (Server Component)
│   ├── error.tsx                 # Error boundary global
│   ├── not-found.tsx             # Página 404 customizada
│   ├── opengraph-image.tsx       # Open Graph image generator
│   ├── [city]/                   # Rotas dinâmicas por cidade
│   │   └── page.tsx              # /sao-paulo, /rio-de-janeiro, etc.
│   └── globals.css               # Estilos globais (Tailwind)
│
├── components/                   # Componentes React
│   ├── kpi-card.tsx              # Card de KPI reutilizável
│   ├── search-bar.tsx            # Busca com autocomplete (Client)
│   ├── stations-list.tsx         # Lista de postos (responsivo)
│   ├── price-distribution.tsx    # Visualização de quartis
│   └── error-boundary.tsx        # Componentes de erro
│
├── lib/                          # Lógica de negócio
│   ├── analytics.ts              # 🧠 Funções puras de BI
│   ├── metadata.ts               # Geração de metadata SEO
│   ├── utils.ts                  # Utilitários (cn, etc.)
│   └── data/
│       └── csv-processor.ts      # Pipeline de dados ANP
│
├── types/                        # Type definitions
│   └── gas.ts                    # Interfaces TypeScript
│
├── data/                         # Dados ANP
│   └── ultimas-4-semanas-glp.csv # CSV oficial (fallback)
│
├── public/                       # Assets estáticos
│   ├── favicon.ico
│   └── apple-touch-icon.png
│
├── package.json                  # Dependências
├── tsconfig.json                 # TypeScript config (strict mode)
├── next.config.js                # Next.js config + headers
├── tailwind.config.ts            # Tailwind config
└── .eslintrc.json                # ESLint rules (no-any: error)

📦 Instalação

Pré-requisitos

  • Node.js >= 18.17.0
  • npm >= 9.0.0

Setup Rápido

# 1. Clone o repositório
git clone https://github.com/seu-usuario/webapp_gas_mais_barato.git
cd webapp_gas_mais_barato

# 2. Instale as dependências
npm install

# 3. Execute em desenvolvimento
npm run dev

# 4. Abra no navegador
http://localhost:3000

Build de Produção

# Validar TypeScript
npm run type-check

# Lint do código
npm run lint

# Build para produção
npm run build

# Executar em produção
npm start

🎯 Funcionalidades

🔍 Busca Inteligente

  • Autocomplete: Sugestões de cidades enquanto digita
  • Navegação por Teclado: ↑↓ para navegar, Enter para selecionar
  • Case-Insensitive: Busca flexível (são paulo = São Paulo)
  • URL-Friendly: Compartilhe links /sao-paulo diretamente

💰 Métricas de Economia

KPIs Primários (Destaque)

  1. Economia Potencial (verde)

    • Valor absoluto: R$ 29,50
    • Projeção anual: R$ 354,00/ano
    • Percentual: 24% de economia
  2. Menor Preço

    • Melhor oferta encontrada
    • Posto com melhor custo-benefício
  3. Potencial de Economia

    • Percentual de economia: 24%
    • Comparação: mais barato vs. mais caro

KPIs Secundários

  • Preço Típico (Mediana): R$ 107,00

    • 50% dos postos cobram menos
    • Mais robusto que média
  • Volatilidade do Mercado: Variação Significativa

    • Baseado em price range percentage
    • Indicador de competitividade
  • Confiança dos Dados: Alta

    • Baseado em número de postos (47)
    • Score: Baixa / Moderada / Média / Alta / Muito Alta

📊 Visualização de Distribuição

Gráfico de Quartis:

[Verde════════Amarelo════════Vermelho]
  ↑              ↑               ↑
 Q1(25%)      Mediana         Q3(75%)
R$ 100,00     R$ 107,00       R$ 115,00

Interpretação:

  • Verde: 25% mais baratos (até R$ 100,00)
  • Amarelo: Preço típico/mediana (R$ 107,00)
  • Vermelho: 25% mais caros (acima de R$ 115,00)

📍 Lista de Postos

Desktop: Tabela completa com colunas

  • Posto | Preço | Bandeira | Bairro | Endereço | vs. Mediana | Ações

Tablet: Tabela responsiva

  • Layout adaptativo com table-autolg:table-fixed
  • Espaçamento otimizado para telas médias

Mobile: Cards responsivos

  • Layout otimizado para telas pequenas
  • Todas informações preservadas
  • Touch targets ≥ 44px (WCAG AAA)

Features:

  • Ordenação automática por preço
  • Badge "🏆 Melhor Preço" no mais barato
  • Indicador visual vs. Mediana (↑/↓)
  • Formatação brasileira (R$, DD/MM/YYYY)

🔒 Tratamento de Erros

Error Boundaries:

  • app/error.tsx: Captura erros globais
  • app/not-found.tsx: Página 404 customizada
  • ErrorFallback: Componente reutilizável

Tipos de Erro:

  1. Fetch Error: Problema ao buscar dados ANP
  2. Processing Error: Erro ao processar CSV
  3. Not Found: Cidade não encontrada
  4. Unknown: Erro genérico

UX de Erro:

  • Visual amigável (não mostra stack traces)
  • Botão "Tentar Novamente" funcional
  • Link para suporte
  • Detalhes técnicos apenas em desenvolvimento

🔎 SEO Otimizado

Metadata Dinâmica por Cidade:

// Para: /?city=São Paulo
title: "Gás a partir de R$ 95,50 em São Paulo | Gás Mais Barato"
description: "Preços de GLP em São Paulo variam de R$ 95,50 a R$ 125,00.
              Economize até 24% (R$ 29,50) escolhendo o posto mais barato."

Structured Data (JSON-LD):

  • WebSite com SearchAction
  • AggregateOffer com preços min/max
  • Breadcrumbs por cidade

Open Graph:

  • Imagem gerada dinamicamente (1200x630px)
  • Título e descrição otimizados
  • Twitter Cards

🧠 Lógica de Negócio (BI)

Funções Puras (lib/analytics.ts)

Todas funções são puras (sem side effects):

// Função principal: calcula todas as métricas
calculateCityMetrics(
  stations: GasStation[],
  city: string
): CityMetrics | null

// Funções auxiliares
findCheapestStation(stations, city): GasStation | null
findMostExpensiveStation(stations, city): GasStation | null
getTopCheapestStations(stations, city, limit): GasStation[]
calculatePriceVariance(price, cityMetrics): number
calculateAnnualSavings(currentPrice, cityMetrics): number
calculateBrandAverages(stations, city?): Map<string, number>

Pipeline de Dados (lib/data/csv-processor.ts)

┌─────────────────┐
│  ANP Live URL   │ (dados semanais)
└────────┬────────┘
         │ fetch()
         ↓
┌─────────────────┐
│  CSV Parser     │ (csv-parse)
│  - UTF-8        │
│  - Delimiter ;  │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  Validation &   │
│  Transformation │
│  - Type guards  │
│  - Price parse  │
│  - Date parse   │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  Deduplication  │ (CNPJ)
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  In-Memory      │ (30 min TTL)
│  Cache          │
└─────────────────┘

Tratamento de Erros:

  • Try-catch em todas operações de I/O
  • Fallback para arquivo local se API ANP falhar
  • Validação linha a linha (skip inválidos)
  • Logs estruturados de estatísticas

🧪 Testes

# Testes unitários
npm test

# Testes com UI
npm run test:ui

# Coverage
npm run test:coverage

Estrutura de Testes (a implementar):

tests/
├── unit/
│   ├── analytics.test.ts        # Testes de funções puras
│   ├── csv-processor.test.ts    # Testes de parsing
│   └── metadata.test.ts         # Testes de SEO
├── integration/
│   └── api.test.ts              # Testes de integração
└── e2e/
    └── user-flow.spec.ts        # Testes E2E (Playwright)

📊 Métricas de Qualidade

Aspecto Status Detalhes
TypeScript ✅ 100% Strict mode, sem any
Type Safety ✅ Completo Type guards + validação runtime
Error Handling ✅ Robusto Boundaries + fallbacks
Performance ✅ Otimizado Server Components + cache
SEO Score ✅ ~95 Metadata dinâmica + JSON-LD
Accessibility ✅ WCAG AAA ARIA + 44px touch targets
Responsividade ✅ 8 Breakpoints Mobile-first (320px → 3840px)
Segurança ✅ Headers CSP, X-Frame-Options

📱 Design Responsivo

Breakpoints Customizados

O projeto implementa 8 breakpoints customizados para garantir experiência otimizada em todos os dispositivos:

Breakpoint Width Dispositivos Layout
xs 375px iPhone SE, smartphones pequenos 1 coluna, cards mobile
sm 640px Smartphones grandes, phablets 2 colunas, tabela simplificada
md 768px Tablets portrait Tabela completa inicia
lg 1024px Tablets landscape, laptops 3 colunas, table-fixed
xl 1280px Desktops padrão Layout completo
2xl 1536px Desktops grandes Container expandido
3xl 1920px Full HD, monitores padrão Max-width 1600px
4xl 2560px Ultra-wide, 2K/4K Max-width 2000px

Estratégia Mobile-First

Todos os componentes seguem a abordagem mobile-first:

// Exemplo: KPI Card responsivo
className="
  p-4 sm:p-5 md:p-6              // Padding progressivo
  text-2xl sm:text-3xl           // Texto escalável
  grid-cols-1 sm:grid-cols-2     // Grid adaptativo
  lg:grid-cols-3                 // Desktop full
"

Componentes Otimizados

  • SearchBar: Botão mobile (< sm), keyboard hints (≥ sm), max-width expandida (3xl)
  • KPI Cards: Padding/texto escalonados, ícones responsivos
  • Price Distribution: Altura variável, labels ocultas em mobile
  • Stations List: Cards mobile (< md) → Tabela desktop (≥ md)
  • Containers: Max-width progressiva (7xl → 3xl → 4xl)

Acessibilidade Responsiva

  • Touch Targets: Mínimo 44x44px em mobile (WCAG AAA)
  • Fontes: Mínimo 14px (mobile) → 16px (desktop)
  • Contraste: AAA (7:1) em todos breakpoints
  • Navegação: Tab order mantido em todas resoluções

Documentação Completa

Ver RESPONSIVE_DESIGN.md para:

  • Guia detalhado de breakpoints
  • Padrões de classes responsivas
  • Testes de responsividade
  • Troubleshooting comum

🚀 Deploy

Vercel (Recomendado)

# Instalar CLI
npm install -g vercel

# Deploy
vercel

# Deploy para produção
vercel --prod

Docker

FROM node:18-alpine AS base

# Dependências
FROM base AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

# Build
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# Produção
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000
CMD ["node", "server.js"]

Variáveis de Ambiente

Crie .env.local:

# URL do CSV ANP (opcional - usa URL padrão se não definido)
ANP_CSV_URL=https://www.gov.br/anp/pt-br/centrais-de-conteudo/dados-abertos/arquivos/shpc/qus/ultimas-4-semanas-glp.csv

# Site URL (para canonical links e OG images)
NEXT_PUBLIC_SITE_URL=https://gasmaisbarato.com

# Analytics (opcional)
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX

📝 Princípios de Desenvolvimento

1. Type Safety Total

// ✅ Bom
interface GasStation {
  id: string;
  price: number;
}

// ❌ Ruim
const station: any = { ... }

2. Funções Puras

// ✅ Bom - Pure function
function calculateAverage(prices: number[]): number {
  return prices.reduce((a, b) => a + b, 0) / prices.length;
}

// ❌ Ruim - Side effect
let total = 0;
function addPrice(price: number) {
  total += price; // Mutação externa
}

3. Error Handling Robusto

// ✅ Bom
try {
  const data = await fetchData();
  return processData(data);
} catch (error) {
  if (error instanceof TypeError) {
    // Tratamento específico
  }
  throw new Error('Processing failed', { cause: error });
}

// ❌ Ruim
const data = await fetchData(); // Pode quebrar sem try-catch

4. Performance First

// ✅ Bom - Server Component (default)
export default async function Page() {
  const data = await fetchData(); // Executa no servidor
  return <div>{data}</div>;
}

// ❌ Ruim - Client Component desnecessário
'use client';
export default function Page() { ... }

🤝 Contribuindo

Contribuições são bem-vindas! Siga estas diretrizes:

Setup de Desenvolvimento

# 1. Fork o repositório
# 2. Clone seu fork
git clone https://github.com/SEU-USUARIO/webapp_gas_mais_barato.git

# 3. Crie uma branch
git checkout -b feature/minha-feature

# 4. Faça suas alterações
# 5. Execute testes
npm run type-check
npm run lint
npm test

# 6. Commit (use Conventional Commits)
git commit -m "feat: adiciona filtro por bandeira"

# 7. Push
git push origin feature/minha-feature

# 8. Abra um Pull Request

Conventional Commits

feat: nova funcionalidade
fix: correção de bug
docs: documentação
style: formatação
refactor: refatoração
test: testes
chore: tarefas gerais

Code Review Checklist

  • TypeScript strict mode OK
  • Testes passando
  • ESLint sem warnings
  • Funções puras quando possível
  • Error handling adequado
  • Componentes responsivos
  • Acessibilidade (ARIA)
  • Documentação atualizada

📈 Roadmap

v1.2 (Q1 2026)

  • Filtro por bandeira (Ultragaz, Liquigás, etc.)
  • Comparação lado a lado de 2 cidades
  • Exportação de dados (CSV, PDF)
  • Modo escuro (dark mode)

v1.3 (Q2 2026)

  • Histórico de preços (séries temporais)
  • Gráficos de tendência (Chart.js)
  • Alertas de preço (push notifications)
  • Progressive Web App (PWA)

v2.0 (Q3 2026)

  • Área do usuário (login)
  • Favoritos/watchlist de postos
  • API pública REST
  • App mobile (React Native)

📄 Licença

Este projeto está sob a licença MIT. Veja LICENSE para mais detalhes.


🙏 Agradecimentos

  • ANP - Agência Nacional do Petróleo, pelos dados oficiais abertos
  • Vercel - Plataforma de deploy Next.js
  • Comunidade Next.js - Framework incrível
  • Tailwind CSS - Framework CSS utilitário
  • Todos os contribuidores - Obrigado! ❤️

📞 Suporte


Desenvolvido com ❤️ para ajudar brasileiros a economizar no gás de cozinha

🌐 Site · 📖 Docs · 🚀 Deploy

About

Repo código da página simples do "Gás Mais Barato"

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages