78 lines
2.5 KiB
JavaScript
78 lines
2.5 KiB
JavaScript
import { NextResponse } from 'next/server';
|
|
|
|
const ZIP = process.env.WEATHER_ZIP || '16046';
|
|
|
|
export async function GET(request) {
|
|
const { searchParams } = new URL(request.url);
|
|
const location = searchParams.get('location') || ZIP;
|
|
|
|
try {
|
|
const res = await fetch(`https://wttr.in/${encodeURIComponent(location)}?format=j1`, {
|
|
headers: { 'User-Agent': 'HQ-Dashboard/1.0' },
|
|
next: { revalidate: 900 } // cache 15 min
|
|
});
|
|
|
|
if (!res.ok) throw new Error(`wttr.in returned ${res.status}`);
|
|
const data = await res.json();
|
|
|
|
const current = data.current_condition[0];
|
|
const area = data.nearest_area[0];
|
|
const today = data.weather[0];
|
|
const tomorrow = data.weather[1];
|
|
|
|
const city = area.areaName[0].value;
|
|
const state = area.region[0].value;
|
|
|
|
// Hourly forecast for today (3 slots: morning, afternoon, evening)
|
|
const hourly = (today.hourly || []).filter((_, i) => [2, 4, 6].includes(i)).map(h => ({
|
|
time: formatHour(h.time),
|
|
tempF: h.tempF,
|
|
desc: h.weatherDesc[0].value,
|
|
chanceRain: h.chanceofrain,
|
|
}));
|
|
|
|
return NextResponse.json({
|
|
location: `${city}, ${state}`,
|
|
zip: location,
|
|
current: {
|
|
tempF: current.temp_F,
|
|
feelsLikeF: current.FeelsLikeF,
|
|
humidity: current.humidity,
|
|
windMph: current.windspeedMiles,
|
|
windDir: current.winddir16Point,
|
|
visibility: current.visibility,
|
|
uvIndex: current.uvIndex,
|
|
desc: current.weatherDesc[0].value,
|
|
cloudcover: current.cloudcover,
|
|
pressure: current.pressure,
|
|
},
|
|
today: {
|
|
maxF: today.maxtempF,
|
|
minF: today.mintempF,
|
|
sunrise: today.astronomy[0].sunrise,
|
|
sunset: today.astronomy[0].sunset,
|
|
desc: today.hourly[4]?.weatherDesc[0]?.value || '',
|
|
chanceRain: today.hourly[4]?.chanceofrain || '0',
|
|
chanceSnow: today.hourly[4]?.chanceofsnow || '0',
|
|
},
|
|
tomorrow: tomorrow ? {
|
|
maxF: tomorrow.maxtempF,
|
|
minF: tomorrow.mintempF,
|
|
desc: tomorrow.hourly[4]?.weatherDesc[0]?.value || '',
|
|
chanceRain: tomorrow.hourly[4]?.chanceofrain || '0',
|
|
} : null,
|
|
hourly,
|
|
});
|
|
} catch (err) {
|
|
return NextResponse.json({ error: err.message }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
function formatHour(time) {
|
|
const h = parseInt(time) / 100;
|
|
if (h === 0) return '12 AM';
|
|
if (h < 12) return `${h} AM`;
|
|
if (h === 12) return '12 PM';
|
|
return `${h - 12} PM`;
|
|
}
|