{"id":29555642,"url":"https://github.com/gmartins-dev/3d-car","last_synced_at":"2025-07-18T09:05:42.142Z","repository":{"id":304846092,"uuid":"1019636215","full_name":"gmartins-dev/3d-car","owner":"gmartins-dev","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-15T22:10:39.000Z","size":1039,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-16T08:30:59.681Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/gmartins-dev.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}},"created_at":"2025-07-14T16:25:28.000Z","updated_at":"2025-07-15T22:10:42.000Z","dependencies_parsed_at":"2025-07-16T13:16:29.968Z","dependency_job_id":null,"html_url":"https://github.com/gmartins-dev/3d-car","commit_stats":null,"previous_names":["gmartins-dev/3d-car"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/gmartins-dev/3d-car","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmartins-dev%2F3d-car","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmartins-dev%2F3d-car/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmartins-dev%2F3d-car/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmartins-dev%2F3d-car/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gmartins-dev","download_url":"https://codeload.github.com/gmartins-dev/3d-car/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmartins-dev%2F3d-car/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265730426,"owners_count":23818766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2025-07-18T09:05:40.774Z","updated_at":"2025-07-18T09:05:42.130Z","avatar_url":"https://github.com/gmartins-dev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GPS Car Tracker\n\nEste projeto renderiza uma animação de um veículo em um mapa utilizando dados de GPS. A aplicação permite ao usuário selecionar diferentes trajetos, visualizar o progresso da animação e obter detalhes sobre a rota, como distância, duração e velocidade.\n\n## 💻 Demo\n\n- Veja a aplicação funcionando aqui: [https://3d-car-nine.vercel.app/](https://3d-car-nine.vercel.app/)\n\n## 📸 Screenshots\n\n\u003cp  align=\"center\"\u003e\n  \u003ch5 align=\"center\"\u003e🖥 Desktop:\u003c/h5\u003e\n  \u003ckbd\u003e\n\u003cimg width=\"100%\" style=\"border-radius: 5px\" height=\"70%\" src=\"public/demo/desktop-light.png\" alt=\"Light Mode Screenshot 1\"\u003e\n\u003c/kbd\u003e\n  \u003ckbd\u003e\n\u003cimg width=\"100%\" style=\"border-radius: 5px\" height=\"70%\" src=\"public/demo/desktop-dark.png\" alt=\"Dark Mode Screenshot 2\"\u003e\n\u003c/kbd\u003e\n\u003c/p\u003e\n  \u003ch5 align=\"center\"\u003e📱 Mobile:\u003c/h5\u003e\n\u003cp  align=\"center\"\u003e\n\u003ckbd\u003e\n\u003cimg width=\"600\" style=\"border-radius: 5px\" height=\"100%\" src=\"public/demo/mobile-light.png\" alt=\"Mobile Light Mode Screenshot\"\u003e\n\u003c/kbd\u003e\n\u003ckbd\u003e\n\u003cimg width=\"600\" style=\"border-radius: 5px\" height=\"100%\" src=\"public/demo/mobile-dark.png\" alt=\"Mobile Dark Mode Screenshot\"\u003e\n\u003c/kbd\u003e\n\u003c/p\u003e\n\n## ✨ Funcionalidades\n\n-   **Visualização no Mapa:** Exibe um mapa interativo com o trajeto do veículo desenhado.\n-   **Animação do Veículo:** Um ícone de carro se move ao longo da rota, com sua rotação ajustada para indicar a direção do movimento.\n-   **Animação Baseada na Velocidade:** A velocidade da animação no mapa é ajustada com base nos dados de velocidade do veículo para cada ponto do trajeto.\n-   **Seleção de Rotas:** O usuário pode escolher entre diferentes trajetos disponíveis nos dados de GPS.\n-   **Controles de Animação:** Botões para iniciar e reiniciar a animação.\n-   **Internacionalização:** Suporte para múltiplos idiomas (Português, Inglês e Espanhol).\n-   **Tema Dinâmico (Dark/Light Mode):** O usuário pode alternar entre o tema claro e escuro.\n\n## 🧠 Lógica Principal\n\nA animação do veículo é controlada no componente `App.tsx` através de uma combinação dos hooks `useState` e `useEffect` do React.\n\n-   **Estado:** O estado `carIndex` rastreia a posição atual do veículo no array de pontos GPS da rota selecionada. O estado `isPlaying` controla se a animação está ativa.\n-   **Animação com `useEffect`:** Um `useEffect` é acionado sempre que `isPlaying` ou `carIndex` mudam.\n    -   Dentro do hook, a velocidade do veículo no ponto atual é recuperada (`selectedRoute.speeds[carIndex]`).\n    -   Um `setTimeout` é utilizado para agendar a próxima atualização de `carIndex`. O intervalo do timeout é dinâmico e calculado com base na velocidade do carro, fazendo com que o veículo se mova mais rápido no mapa quando os dados de GPS indicam uma velocidade maior.\n    -   Quando a animação termina (o carro chega ao último ponto), o loop é interrompido.\n\n## 🏗️ Estrutura do Projeto\n\nO projeto foi organizado de forma modular para separar responsabilidades e facilitar a manutenção.\n\n```\n/src\n├── api/\n│   └── frontend_data_gps.json   # Dados brutos de GPS\n├── components/\n│   ├── ui/                      # Componentes base do Shadcn UI (Button, Card, etc.)\n│   ├── ActionButton.tsx         # Botão de controle (Iniciar/Reiniciar)\n│   ├── DetailsCard.tsx          # Card com detalhes da rota\n│   ├── LanguageSwitcher.tsx     # Dropdown para troca de idioma\n│   ├── Map.tsx                  # Componente que renderiza o mapa e a animação\n│   ├── ModeToggle.tsx           # Botão para alternar tema (dark/light)\n│   ├── ProgressBar.tsx          # Barra de progresso da animação\n│   ├── RouteSelect.tsx          # Dropdown para seleção de rota\n│   └── ThemeProvider.tsx        # Provedor de contexto para o tema\n├── helpers/\n│   └── gpsData.ts               # Lógica para processar os dados brutos de GPS\n├── lib/\n│   └── utils.ts                 # Função utilitária cn do Shadcn para mesclar classes\n├── locales/\n│   ├── en/common.json           # Textos em Inglês\n│   ├── es/common.json           # Textos em Espanhol\n│   └── pt/common.json           # Textos em Português\n├── App.tsx                      # Componente principal que gerencia o estado da aplicação\n├── i18n.ts                      # Configuração do i18next\n└── main.tsx                     # Ponto de entrada da aplicação\n```\n\n### Detalhes dos Componentes Principais\n\n-   **`Map.tsx`**: Renderiza o mapa usando `react-leaflet`. É responsável por desenhar a polilinha da rota e o marcador do carro. O ícone do carro é um SVG customizado que recebe a direção do veículo e a aplica como uma rotação de CSS para que o ícone aponte para a direção correta do movimento.\n-   **`RouteSelect.tsx`**: Um dropdown controlado que permite ao usuário selecionar uma das rotas processadas a partir dos dados de GPS. Ao mudar a rota, o estado no componente `App` é atualizado, reiniciando a animação.\n-   **`DetailsCard.tsx`**: Exibe informações textuais e dinâmicas sobre o trajeto atual, como endereços, duração, distância, paradas, velocidade atual e progresso.\n-   **`ActionButton.tsx`**: Um botão de ação cujo texto e cor mudam de acordo com o estado da animação (`Iniciar`, `A Caminho`, `Reiniciar`), oferecendo um feedback visual claro ao usuário.\n\n## 🛠️ Tecnologias Utilizadas\n\nA seleção de tecnologias visou criar uma aplicação moderna, performática e de fácil manutenção, seguindo as melhores práticas de desenvolvimento front-end.\n\n-   **Vite:** Utilizado como build tool e servidor de desenvolvimento. Foi escolhido por sua extrema velocidade, proporcionada pelo hot module replacement (HMR) nativo e pelo uso de esbuild.\n-   **React:** Biblioteca principal para a construção da interface de usuário. Sua abordagem baseada em componentes permite a criação de uma UI modular e reutilizável.\n-   **TypeScript:** Adiciona tipagem estática ao JavaScript, o que aumenta a robustez do código, melhora o autocompletar e ajuda a prevenir bugs em tempo de desenvolvimento.\n-   **Tailwind CSS:** Um framework CSS utility-first para estilização rápida e consistente sem a necessidade de escrever CSS customizado. Ele é configurado com a v4, que oferece performance aprimorada.\n-   **Shadcn UI:** Uma coleção de componentes de UI reutilizáveis, construídos com Radix UI e Tailwind CSS. Foi utilizado para compor a interface de forma ágil com componentes acessíveis e customizáveis como `Card`, `Button` e `Select`.\n-   **Leaflet \u0026 React-Leaflet:** Bibliotecas escolhidas para a renderização dos mapas. Leaflet é uma solução leve e poderosa para mapas interativos, e `react-leaflet` fornece bindings para integrá-lo de forma declarativa em aplicações React.\n-   **i18next \u0026 react-i18next:** Utilizadas para a implementação da internacionalização (i18n), permitindo que o texto da aplicação seja traduzido facilmente para múltiplos idiomas.\n-   **Lucide React:** Biblioteca de ícones escolhida por sua simplicidade, consistência e fácil customização.\n\n## 📊 Modelagem dos Dados\n\nOs dados brutos fornecidos no arquivo `frontend_data_gps.json` são processados pelo helper `src/helpers/gpsData.ts`. Esta função mapeia os \"cursos\" (trajetos) para uma estrutura de dados `Route` mais amigável para ser consumida pelos componentes React. Cada objeto `Route` contém informações prontas para uso, como:\n\n-   `points`: Um array de coordenadas `[latitude, longitude]`.\n-   `speeds`: Um array com as velocidades em cada ponto.\n-   `directions`: Um array com as direções em cada ponto.\n-   `startName` e `endName`: Endereços de início e fim da rota.\n-   Outros metadados como `duration`, `distance` e `stops`.\n\nEssa abordagem separa a lógica de transformação dos dados da lógica de apresentação, tornando os componentes mais limpos e focados em sua responsabilidade de renderização.\n\n## 🚀 Como Executar o Projeto\n\nSiga os passos abaixo para rodar a aplicação localmente:\n\n1.  **Clone o repositório:**\n    ```bash\n    git clone https://github.com/gmartins-dev/3d-car\n    cd 3d-car\n    ```\n\n2.  **Instale as dependências:**\n    O projeto utiliza `pnpm` como gerenciador de pacotes.\n    ```bash\n    pnpm install\n    ```\n\n3.  **Inicie o servidor de desenvolvimento:**\n    ```bash\n    pnpm dev\n    ```\n\n4.  Abra o seu navegador e acesse `http://localhost:5173` (ou a porta indicada no seu terminal).\n\n## 🔮 Melhorias Futuras\n\n-   [ ] Adicionar testes unitários e de integração (ex: com Vitest e React Testing Library).\n-   [ ] Implementar um modo \"seguir o carro\" no mapa, onde o centro do mapa se ajusta automaticamente à posição do veículo durante a animação.\n-   [ ] Adicionar mais visualizações de dados, como um gráfico de velocidade vs. tempo.\n-   [ ] Permitir a seleção de diferentes ícones para o veículo.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgmartins-dev%2F3d-car","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgmartins-dev%2F3d-car","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgmartins-dev%2F3d-car/lists"}