Este projeto é uma aplicação web de previsão meteorológica que permite aos usuários consultar as previsões do tempo para qualquer cidade utilizando um mapa de apoio. A aplicação foi desenvolvida utilizando TypeScript e a biblioteca OpenLayers para o mapa.
- Pesquisa de Cidade: Os usuários podem pesquisar por uma cidade e obter informações detalhadas sobre o clima atual.
- Mapa Interativo: O mapa exibe a localização da cidade pesquisada e atualiza dinamicamente conforme novas pesquisas são realizadas.
- Informações do Clima: Mostra a temperatura atual, temperatura máxima e mínima, tipo do clima e ícones correspondentes.
- Cidades Salvas: Os usuários podem acessar rapidamente as cidades pesquisadas anteriormente através de um menu de seleção.
- Vite
- Typescript
- React
- OpenLayers: Para o mapa.
- OpenWeather Geocoding API: Para obter as coordenadas geográficas das cidades.
- OpenWeather Current weather data: Para obter os dados climáticos.
As APIs utilizadas para esse projeto são gratúitas e infelizmente não possuem dados relacionados às fases da lua ou uma previsão de até 3 dias do clima da região selecionada como foi solicitado
cypress
├── e2e/
│ ├── TestandoApp.cy.js
│
weather-forecast/
├── public/
│ ├── index.html
│
├── src/
│ ├── components/
│ │ ├── CitySearch.tsx
│ │ ├── Popup.tsx
│ │ ├── Map.tsx
│ │ ├── WeatherInfo.tsx
│ │ ├── SavedCities.tsx
│ │
│ ├── service/
│ │ ├── api.ts
│ │
│ ├── styles/
│ │ ├── app.css
│ │ ├── global.css
│ │ ├── index.css
│ │
│ ├── App.tsx
│ ├── main.tsx
│
├── .gitignore
├── package.json
├── tsconfig.json
├── README.md
- Node.js
- npm ou yarn
- Clone o repositório:
git clone https://github.com/JhontanLop/weather-forecast.git
cd weather-forecast/weather-forecast/
- Instale as dependências:
npm install
yarn
- Configure suas chaves de API:
Para conseguir uma api key acesse o site da openWeather e crie uma conta se não tiver. Depois vá para a parte de API keys onde estarão listadas todas as suas chaves.
No arquivo api.ts
coloque a sua chave de acesso
const WEATHER_API_KEY = "YOUR_API_KEY";
- Inicie a aplicação:
npm run dev
yarn dev
A aplicação estará disponível em http://localhost:3000.
Tela inicial
O sistema faz o uso da API externa a partir do campo de pesquisa com input do tipo string e um botão ao lado para fazer a chamada da função.
Pesquisando pelo nome de uma cidade o primeiro endpoint será usado. Este recebe como parâmetro o nome de uma cidade e retorna algumas informações como latitude e longitude
Esses dados são usados em outro endpoint que retorna os dados do clima naquela regial.
Se a consulta for bem sucedida, o mapa será movido em direção à cidade e as informaçãos sserão reenderizadas na tela e a cidade pesquisada vai para a lista no canto superior da página.
Caso pesquise por uma cidade e a mesma não é encontrada haverá um popup de aviso.
Para executar os testes automatizados
- Instalar dependências
npm i cypress --save-dev
- Executar testes
npx cypress run
Esse comando irá rodar os testes e exibir um relatório pelo terminal.
Usando interface do Cypress
- Abrir o cypress
npx cypress open
Este comando irá abrir o cypress, onde executara os testes em tempo real com uma interface para visualização do processo
- Fazer login
- Escolha o tipo de teste
Para esse projeto usaremos a opção E2E
- Escolha do ambiente a ser executado
No meu caso eu acabei usando o firefox pois é o navegador que eu possuo
- Escolha o teste
Ao escolher o teste, o cypress comecará os testes
OpenWeather Geocoding API: Documentação
OpenWeather Current weather data: Documentação)
OpenLayer documentation)
- Obtendo os dados.
Ao pesquisar o nome de uma cidade, usa-se o end-point:
export const getCityCoordinates = async (city: string) => {
const response = await axios.get(`https://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=1&appid=${WEATHER_API_KEY}`);
return response.data[0];
};
Esse endpoint retorna a latitude e longitude da cidade junto com outras informações como estado e país. A latitude e longitude será usado na reenderização do mapa e em outro endpoint, este que retorna os dados do clima
export const getWeather = async (lat: number, lon: number) => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${WEATHER_API_KEY}&lang=pt_br`);
return response.data;
};
função que atualiza a posição do mapa
setMapPosition({ lat: cityData.lat, lon: cityData.lon, zoom: 11 });
- Convertendo os dados
estes dados vem no padrão americano, com exceção da descrição do clima. Sendo assim é necessário fazer a conversão de Fahrenheit para Celsius e alterar a data para o padrão brasileiro.
// weather é o objeto retornado do endpoint
const convertedData = {
date: new Date(weather.date).toLocaleDateString('pt-BR'),
temp: (weather.temp - 273.15).toFixed(2),
tempMax: (weather.tempMax - 273.15).toFixed(2),
tempMin: (weather.tempMin - 273.15).toFixed(2)
};
Depois dessa conversão o commponente é exportado como html
<div className="weather-info">
<header className="weather-header">
<button onClick={onClose} className="close-button">×</button>
<h2>{weather.city}</h2>
</header>
<main className="weather-content">
<p>Data: {convertedData.date}</p>
<p>Temperatura: {convertedData.temp}°C</p>
<p>Temp Max: {convertedData.tempMax}°C</p>
<p>Temp Min: {convertedData.tempMin}°C</p>
<p>Descrição: {weather.description}</p>
<img src={`http://openweathermap.org/img/wn/${weather.icon}.png`} alt={weather.description} />
</main>
</div>
- Reenderizando os dados
Exportado como html, agora é possível chamálo na aplicação, mas para controle do usuário caso ele não queira mais ver essa informação é necessário haver um meio de esconder isso.
function renderWeatherInfo() {
if (!weather) return null; // se não houver dados, retornar null
if (!isWeatherVisible) return null; // se isWeatherVisible for false, retornar null
// montando componente
return (
<div className= "weather-popup" >
<WeatherInfo
weather={ weather }
onClose = { handleCloseWeather } />
</div>
);
}
Com isso o usuário consegue fechar o popup com os dados do clima e continuar pesquisando. Quando uma outra cidade for pesquisada, o componente voltará a aparecer com os novos dados.