diff --git a/src/app/api/weather/route.ts b/src/app/api/weather/route.ts index afaf8a6..0a201b2 100644 --- a/src/app/api/weather/route.ts +++ b/src/app/api/weather/route.ts @@ -1,3 +1,12 @@ +const CACHE_TTL_MS = 1000 * 60 * 20; // 20 minutes + +type CacheEntry = { + ts: number; + weather: any; +}; + +const weatherCache = new Map(); + export const POST = async (req: Request) => { try { const body: { @@ -15,6 +24,16 @@ export const POST = async (req: Request) => { ); } + const cacheKey = `${body.lat.toFixed(4)},${body.lng.toFixed(4)},${body.measureUnit}`; + + // Return cached entry if fresh + const cached = weatherCache.get(cacheKey); + if (cached && Date.now() - cached.ts < CACHE_TTL_MS) { + console.log('Returning cached weather data for ', cacheKey); + return Response.json(cached.weather); + } + console.log('Fetching new weather data for ', cacheKey); + const res = await fetch( `https://api.open-meteo.com/v1/forecast?latitude=${body.lat}&longitude=${body.lng}¤t=weather_code,temperature_2m,is_day,relative_humidity_2m,wind_speed_10m&timezone=auto${ body.measureUnit === 'Metric' ? '' : '&temperature_unit=fahrenheit' @@ -159,6 +178,13 @@ export const POST = async (req: Request) => { break; } + // store in cache + try { + weatherCache.set(cacheKey, { ts: Date.now(), weather }); + } catch (e) { + // ignore cache failures + } + return Response.json(weather); } catch (err) { console.error('An error occurred while getting home widgets', err); diff --git a/src/components/WeatherWidget.tsx b/src/components/WeatherWidget.tsx index 1728c49..f9efd3f 100644 --- a/src/components/WeatherWidget.tsx +++ b/src/components/WeatherWidget.tsx @@ -16,15 +16,42 @@ const WeatherWidget = () => { const [loading, setLoading] = useState(true); useEffect(() => { - const getApproxLocation = async () => { - const res = await fetch('https://ipwhois.app/json/'); - const data = await res.json(); + const IPWHOIS_CACHE_KEY = 'ipwhois_cache_v1'; + const IPWHOIS_TTL_MS = 1000 * 60 * 20; // 20 minutes - return { - latitude: data.latitude, - longitude: data.longitude, - city: data.city, - }; + const getApproxLocation = async () => { + try { + const raw = sessionStorage.getItem(IPWHOIS_CACHE_KEY); + if (raw) { + const parsed = JSON.parse(raw); + if (parsed?.ts && Date.now() - parsed.ts < IPWHOIS_TTL_MS && parsed?.data) { + return parsed.data; + } + } + + const res = await fetch('https://ipwhois.app/json/'); + const data = await res.json(); + + const payload = { + ts: Date.now(), + data: { + latitude: data.latitude, + longitude: data.longitude, + city: data.city, + }, + }; + + try { + sessionStorage.setItem(IPWHOIS_CACHE_KEY, JSON.stringify(payload)); + } catch (e) { + // ignore storage errors (e.g., quota) + } + + return payload.data; + } catch (err) { + // If anything goes wrong, fall back to a safe default + return { latitude: 0, longitude: 0, city: '' }; + } }; const getLocation = async (