Skip to content

Commit

Permalink
Daily
Browse files Browse the repository at this point in the history
  • Loading branch information
timmo001 committed Sep 3, 2024
1 parent 5792519 commit be81080
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 35 deletions.
35 changes: 18 additions & 17 deletions src/app/_components/forecast-daily.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { CloudSun } from "lucide-react";

import { getLocationFromLocalStorage } from "~/lib/localStorage";
import { getWeatherForecastDaily } from "~/lib/serverActions/accuweather";
import { type AccuweatherHourlyForecast } from "~/lib/types/accuweather";
import { type AccuweatherDailyForecast } from "~/lib/types/accuweather";

export function ForecastDaily() {
const location = useQuery({
Expand All @@ -16,7 +16,7 @@ export function ForecastDaily() {
const forecastDaily = useQuery({
staleTime: 1000 * 60 * 30, // 30 minutes
queryKey: [location.data, "forecast", "daily"],
queryFn: async (): Promise<Array<AccuweatherHourlyForecast>> => {
queryFn: async (): Promise<AccuweatherDailyForecast> => {
if (location.isLoading || !location.data)
return Promise.reject("No location data.");
console.log("Get daily forecast for location:", location.data);
Expand All @@ -37,35 +37,36 @@ export function ForecastDaily() {
) : !forecastDaily.data ? (
<span>No daily forecast data.</span>
) : (
<div className="custom-scrollbar mt-1 flex max-w-96 flex-row flex-nowrap gap-4 overflow-y-auto md:max-w-screen-md lg:max-w-screen-lg">
{forecastDaily.data.map((item) => {
const time = dayjs(item.time);
<div className="custom-scrollbar mt-1 flex max-w-96 flex-row flex-nowrap gap-4 overflow-x-auto overflow-y-hidden md:max-w-screen-md lg:max-w-screen-lg">
{forecastDaily.data.DailyForecasts.map((item) => {
const dateTime = dayjs(item.Date);

return (
<div
key={time.toISOString()}
key={item.EpochDate}
className="flex flex-col items-stretch gap-1"
>
<div className="flex flex-col items-center">
<span className="text-sm font-semibold">
{time.format("ddd")}
{dateTime.format("ddd")}
</span>
</div>
<div className="flex flex-row items-center gap-1">
<CloudSun className="h-16 w-16" />
</div>
<CloudSun className="h-20 w-20" />
<span className="text-xl font-bold">{item.Day.IconPhrase}</span>
<div className="flex flex-row items-center gap-1">
<span className="text-xl font-bold">
{item.temperatureMin.toFixed(1)}
{item.Temperature.Minimum.Value.toFixed(1)}
</span>
<span className="text-sm font-semibold">°C</span>
</div>
<div className="flex flex-row items-center gap-1">
<span className="text-xl font-bold">
{item.temperatureMax.toFixed(1)}
<span className="text-sm font-semibold">
°{item.Temperature.Minimum.Unit}
</span>
<span className="text-sm font-semibold">°C</span>
</div>
<span className="text-xl font-bold">
{item.Temperature.Maximum.Value.toFixed(1)}
<span className="ms-1 pb-1 text-sm font-semibold">
°{item.Temperature.Maximum.Unit}
</span>
</span>
</div>
);
})}
Expand Down
19 changes: 8 additions & 11 deletions src/app/_components/forecast-hourly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ export function ForecastHourly() {
) : !forecastHourly.data ? (
<span>No hourly forecast data.</span>
) : (
<div className="custom-scrollbar mt-1 flex max-w-96 flex-row flex-nowrap gap-4 overflow-y-auto md:max-w-screen-md lg:max-w-screen-lg">
<div className="custom-scrollbar mt-1 flex max-w-96 flex-row flex-nowrap gap-4 overflow-x-auto overflow-y-hidden md:max-w-screen-md lg:max-w-screen-lg">
{forecastHourly.data.map((item) => {
const dateTime = dayjs(item.DateTime);

return (
<div
key={dateTime.toISOString()}
key={item.EpochDateTime}
className="flex flex-col items-stretch gap-1"
>
<div className="flex flex-col items-center">
Expand All @@ -54,17 +54,14 @@ export function ForecastHourly() {
{dateTime.format("HH:mm")}
</span>
</div>
<div className="flex flex-row items-center gap-1">
<CloudSun className="h-16 w-16" />
</div>
<div className="flex flex-row items-center gap-1">
<span className="text-xl font-bold">
{item.Temperature.Value.toFixed(1)}
</span>
<span className="text-sm font-semibold">
<CloudSun className="h-20 w-20" />
<span className="text-sm font-bold">{item.IconPhrase}</span>
<span className="align-top text-xl font-bold">
{item.Temperature.Value.toFixed(1)}
<span className="ms-1 pb-1 text-sm font-semibold">
°{item.Temperature.Unit.toUpperCase()}
</span>
</div>
</span>
</div>
);
})}
Expand Down
4 changes: 2 additions & 2 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CloudSun } from "lucide-react";
// import { ForecastDaily } from "~/app/_components/forecast-daily";
import { ForecastDaily } from "~/app/_components/forecast-daily";
import { ForecastHourly } from "~/app/_components/forecast-hourly";

import { ForecastNow } from "~/app/_components/forecast-now";
Expand All @@ -23,7 +23,7 @@ export default function HomePage() {
<ForecastNow />
<h2 className="mt-3 text-2xl font-bold">Forecast</h2>
<ForecastHourly />
{/* <ForecastDaily /> */}
<ForecastDaily />
</section>
</div>
);
Expand Down
19 changes: 16 additions & 3 deletions src/lib/serverActions/accuweather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
type AccuweatherLocation,
type AccuweatherCurrentConditions,
AccuweatherHourlyForecast,
AccuweatherDailyForecast,
} from "~/lib/types/accuweather";

const BASE_PARAMS = `apikey=${env.WEATHER_API_KEY}&details=true&language=en-gb`;
Expand Down Expand Up @@ -95,10 +96,22 @@ export async function getWeatherForecastHourly(

export async function getWeatherForecastDaily(
location: Location,
): Promise<any> {
): Promise<AccuweatherDailyForecast> {
return unstable_cache(
async (): Promise<any> => {
return Promise.reject("Not implemented.");
async (): Promise<AccuweatherDailyForecast> => {
const weatherLocation = await getWeatherLocation(location);
console.log("Location key:", weatherLocation.Key);

const url = `https://dataservice.accuweather.com/forecasts/v1/daily/5day/${weatherLocation.Key}?${BASE_PARAMS}&metric=true`;
console.log("Get daily forecast:", url);
const response = await fetch(url, BASE_REQUEST_OPTIONS);
const responseData = await response.json();
console.log("Response:", JSON.stringify(responseData));

if (!responseData || responseData.length === 0 || !responseData[0])
return Promise.reject("No data found.");

return responseData;
},
[`${location.latitude},${location.longitude}`],
{
Expand Down
152 changes: 150 additions & 2 deletions src/lib/types/accuweather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,159 @@ export interface AccuweatherHourlyForecast {

export interface Temperature {
Value: number;
Unit: UnitEnum;
Unit: TemperatureUnit | string;
UnitType: number;
}

export enum UnitEnum {
export enum TemperatureUnit {
C = "C",
F = "F",
}

export interface AccuweatherDailyForecast {
Headline: Headline;
DailyForecasts: DailyForecast[];
}

export interface DailyForecast {
Date: Date;
EpochDate: number;
Sun: Sun;
Moon: Moon;
Temperature: RealFeelTemperature;
RealFeelTemperature: RealFeelTemperature;
RealFeelTemperatureShade: RealFeelTemperature;
HoursOfSun: number;
DegreeDaySummary: DegreeDaySummary;
AirAndPollen: AirAndPollen[];
Day: Day;
Night: Day;
Sources: string[];
MobileLink: string;
Link: string;
}

export interface AirAndPollen {
Name: string;
Value: number;
Category: Category | string;
CategoryValue: number;
Type?: string;
}

export enum Category {
Good = "Good",
Moderate = "Moderate",
}

export interface Day {
Icon: number;
IconPhrase: string;
HasPrecipitation: boolean;
PrecipitationType?: string;
PrecipitationIntensity?: string;
ShortPhrase: string;
LongPhrase: string;
PrecipitationProbability: number;
ThunderstormProbability: number;
RainProbability: number;
SnowProbability: number;
IceProbability: number;
Wind: Wind;
WindGust: Wind;
TotalLiquid: Measurement;
Rain: Measurement;
Snow: Measurement;
Ice: Measurement;
HoursOfPrecipitation: number;
HoursOfRain: number;
HoursOfSnow: number;
HoursOfIce: number;
CloudCover: number;
Evapotranspiration: Measurement;
SolarIrradiance: Measurement;
RelativeHumidity: RelativeHumidity;
WetBulbTemperature: WetBulbTemperature;
WetBulbGlobeTemperature: WetBulbTemperature;
}

export interface Measurement {
Value: number;
Unit: TemperatureUnit | MeasurementUnit | string;
UnitType: number;
Phrase?: Phrase | string;
}

export enum Phrase {
Chilly = "Chilly",
Cool = "Cool",
Pleasant = "Pleasant",
}

export enum MeasurementUnit {
CM = "cm",
KMH = "km/h",
Mm = "mm",
WM = "W/m²",
}

export interface RelativeHumidity {
Minimum: number;
Maximum: number;
Average: number;
}

export interface WetBulbTemperature {
Minimum: Measurement;
Maximum: Measurement;
Average: Measurement;
}

export interface Wind {
Speed: Measurement;
Direction: Direction;
}

export interface Direction {
Degrees: number;
Localized: string;
English: string;
}

export interface DegreeDaySummary {
Heating: Measurement;
Cooling: Measurement;
}

export interface Moon {
Rise: Date;
EpochRise: number;
Set: Date;
EpochSet: number;
Phase: string;
Age: number;
}

export interface RealFeelTemperature {
Minimum: Measurement;
Maximum: Measurement;
}

export interface Sun {
Rise: Date;
EpochRise: number;
Set: Date;
EpochSet: number;
}

export interface Headline {
EffectiveDate: Date;
EffectiveEpochDate: number;
Severity: number;
Text: string;
Category: string;
EndDate: Date;
EndEpochDate: number;
MobileLink: string;
Link: string;
}

0 comments on commit be81080

Please sign in to comment.