Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions WeatherWatch/src/Forecast.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@
box-shadow: 0 14px 36px rgba(27,50,85,0.09);
}

.weather-summary {
margin: 12px auto;
padding: 12px 16px;
max-width: 720px;
border-radius: 12px;
background: rgba(167,216,255,0.15);
border: 1px solid rgba(20,40,70,0.08);
color: var(--sky-deep);
font-weight: 600;
}

@media (max-width: 520px) {
.toggle-buttons button {
min-width: 70px;
Expand Down
43 changes: 40 additions & 3 deletions WeatherWatch/src/Forecast.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import './Forecast.css';
import { getDailyAggregation, geocodeLocation } from './api/openweather';
import { getDailyAggregation, geocodeLocation, getWeatherOverview } from './api/openweather';
import { convertTemperature, getUnitSymbol, useUnit } from './context/UnitContext';

// Convert Kelvin to Fahrenheit
Expand Down Expand Up @@ -46,9 +46,32 @@ function Forecast() {
const [weatherData, setWeatherData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [apiSummary, setApiSummary] = useState(null);
const { unit } = useUnit();
const unitSymbol = getUnitSymbol(unit);

const parseApiSummary = (data) => {
if (!data || typeof data !== 'object') return null;
const candidates = [
data.summary,
data.overview,
data.weather_overview,
data.text,
data.daily?.[0]?.summary,
data.daily_overview?.[0]?.summary,
data.forecast?.[0]?.summary,
];
const found = candidates.find((val) => typeof val === 'string' && val.trim());
return found ? found.trim() : null;
};

const buildFallbackSummary = (info) => {
if (!info) return null;
const high = convertTemperature(info.temperature.max, unit);
const low = convertTemperature(info.temperature.min, unit);
return `High ${high}${unitSymbol}, low ${low}${unitSymbol}. Precipitation ${info.precipitation} mm. Wind ${info.wind.speed} m/s ${info.wind.direction}. Humidity ${info.humidity}%.`;
};

const fetchWeather = async () => {
if (!location) {
setError('Please enter a location.');
Expand All @@ -58,6 +81,7 @@ function Forecast() {
setLoading(true);
setError(null);
setWeatherData([]);
setApiSummary(null);

try {
const geo = await geocodeLocation(location.trim());
Expand All @@ -83,9 +107,16 @@ function Forecast() {
return getDailyAggregation(geo.lat, geo.lon, dateStr);
});

const results = await Promise.all(requests);
const overviewPromise = getWeatherOverview(geo.lat, geo.lon).catch((err) => {
console.error('Could not fetch overview', err);
return null;
});
const resultsPromise = Promise.all(requests);

const [overviewData, results] = await Promise.all([overviewPromise, resultsPromise]);
const mapped = results.map((daily, i) => formatWeather(daily, dates[i]));
setWeatherData(mapped);
setApiSummary(parseApiSummary(overviewData));

} catch (err) {
console.error(err);
Expand All @@ -102,6 +133,8 @@ function Forecast() {
}
}, [view]);

const summaryText = apiSummary || buildFallbackSummary(weatherData[0]);

return (
<section className="page">
<h2>Weather View</h2>
Expand Down Expand Up @@ -144,6 +177,11 @@ function Forecast() {
{/* Loading, error, and weather display */}
{loading && <p className="loading">Loading...</p>}
{error && <p className="error">{error}</p>}
{summaryText && (
<div className="weather-summary">
<strong>Summary:</strong> {summaryText}
</div>
)}

{weatherData.map((info, i) => (
<div key={i} className="weather-card">
Expand All @@ -166,4 +204,3 @@ function Forecast() {
}

export default Forecast;

Loading