Files
2024-08-08 18:33:08 +08:00

214 lines
4.5 KiB
TypeScript

export interface WeatherData {
latitude: number;
longitude: number;
generationtime_ms: number;
utc_offset_seconds: number;
timezone: string;
timezone_abbreviation: string;
elevation: number;
current_units: {
time: string;
interval: string;
temperature_2m: string;
weather_code: string;
};
current: {
time: string;
interval: number;
temperature_2m: number;
weather_code: number;
};
hourly_units: {
time: string;
temperature_2m: string;
weather_code: string;
};
hourly: {
time: string[];
temperature_2m: number[];
weather_code: number[];
};
daily_units: {
time: string;
weather_code: string;
};
daily: {
time: string[];
weather_code: number[];
};
}
// Follow WMO Weather interpretation codes (WW)
const weatherCodeDisplayMap: Record<
string,
{
icon: JSX.Element;
status: string;
}
> = {
"0": {
icon: <span>☀️</span>,
status: "Clear sky",
},
"1": {
icon: <span>🌤️</span>,
status: "Mainly clear",
},
"2": {
icon: <span>☁️</span>,
status: "Partly cloudy",
},
"3": {
icon: <span>☁️</span>,
status: "Overcast",
},
"45": {
icon: <span>🌫️</span>,
status: "Fog",
},
"48": {
icon: <span>🌫️</span>,
status: "Depositing rime fog",
},
"51": {
icon: <span>🌧️</span>,
status: "Drizzle",
},
"53": {
icon: <span>🌧️</span>,
status: "Drizzle",
},
"55": {
icon: <span>🌧️</span>,
status: "Drizzle",
},
"56": {
icon: <span>🌧️</span>,
status: "Freezing Drizzle",
},
"57": {
icon: <span>🌧️</span>,
status: "Freezing Drizzle",
},
"61": {
icon: <span>🌧️</span>,
status: "Rain",
},
"63": {
icon: <span>🌧️</span>,
status: "Rain",
},
"65": {
icon: <span>🌧️</span>,
status: "Rain",
},
"66": {
icon: <span>🌧️</span>,
status: "Freezing Rain",
},
"67": {
icon: <span>🌧️</span>,
status: "Freezing Rain",
},
"71": {
icon: <span>❄️</span>,
status: "Snow fall",
},
"73": {
icon: <span>❄️</span>,
status: "Snow fall",
},
"75": {
icon: <span>❄️</span>,
status: "Snow fall",
},
"77": {
icon: <span>❄️</span>,
status: "Snow grains",
},
"80": {
icon: <span>🌧️</span>,
status: "Rain showers",
},
"81": {
icon: <span>🌧️</span>,
status: "Rain showers",
},
"82": {
icon: <span>🌧️</span>,
status: "Rain showers",
},
"85": {
icon: <span>❄️</span>,
status: "Snow showers",
},
"86": {
icon: <span>❄️</span>,
status: "Snow showers",
},
"95": {
icon: <span>⛈️</span>,
status: "Thunderstorm",
},
"96": {
icon: <span>⛈️</span>,
status: "Thunderstorm",
},
"99": {
icon: <span>⛈️</span>,
status: "Thunderstorm",
},
};
const displayDay = (time: string) => {
return new Date(time).toLocaleDateString("en-US", {
weekday: "long",
});
};
export function WeatherCard({ data }: { data: WeatherData }) {
const currentDayString = new Date(data.current.time).toLocaleDateString(
"en-US",
{
weekday: "long",
month: "long",
day: "numeric",
},
);
return (
<div className="bg-[#61B9F2] rounded-2xl shadow-xl p-5 space-y-4 text-white w-fit">
<div className="flex justify-between">
<div className="space-y-2">
<div className="text-xl">{currentDayString}</div>
<div className="text-5xl font-semibold flex gap-4">
<span>
{data.current.temperature_2m} {data.current_units.temperature_2m}
</span>
{weatherCodeDisplayMap[data.current.weather_code].icon}
</div>
</div>
<span className="text-xl">
{weatherCodeDisplayMap[data.current.weather_code].status}
</span>
</div>
<div className="gap-2 grid grid-cols-6">
{data.daily.time.map((time, index) => {
if (index === 0) return null; // skip the current day
return (
<div key={time} className="flex flex-col items-center gap-4">
<span>{displayDay(time)}</span>
<div className="text-4xl">
{weatherCodeDisplayMap[data.daily.weather_code[index]].icon}
</div>
<span className="text-sm">
{weatherCodeDisplayMap[data.daily.weather_code[index]].status}
</span>
</div>
);
})}
</div>
</div>
);
}