Skip to content

Commit

Permalink
Handle rejections and 429
Browse files Browse the repository at this point in the history
  • Loading branch information
timmo001 committed Sep 3, 2024
1 parent deccd61 commit a1c6152
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 28 deletions.
32 changes: 22 additions & 10 deletions src/app/_components/forecast-hourly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,45 @@ import { useQuery } from "@tanstack/react-query";
import { CloudSun } from "lucide-react";

import { getLocationFromLocalStorage } from "~/lib/localStorage";
import {
type WeatherForecastErrorResponse,
type WeatherForecastHourly,
getWeatherForecastHourly,
} from "~/lib/serverActions/tomorrowio";

export function ForecastHourly() {
const location = useQuery({
queryKey: ["location"],
queryFn: getLocationFromLocalStorage,
});

const forecast = useQuery({
const forecastHourly = useQuery({
staleTime: 1000 * 60 * 20, // 20 minutes
queryKey: [location.data, "forecast", "hourly"],
queryFn: async () => {
return [
22.1, 21.9, 21.6, 21.4, 21.2, 21.1, 21.0, 20.9, 20.8, 20.7, 20.6, 20.5,
];
queryFn: async (): Promise<
WeatherForecastErrorResponse | WeatherForecastHourly
> => {
if (location.isLoading || !location.data)
return Promise.reject("No location data.");
console.log("Get hourly forecast for location:", location.data);
return await getWeatherForecastHourly(location.data);
},
});

if (location.isLoading) return <span>Loading location...</span>;
if (location.isError) return <span>Error loading location...</span>;
if (forecast.isLoading) return <span>Loading forecast...</span>;
if (forecast.isError) return <span>Error loading forecast...</span>;
if (!forecast.data || !Array.isArray(forecast.data))
return <span>No forecast data.</span>;
if (forecastHourly.isLoading) return <span>Loading hourly forecast...</span>;
if (forecastHourly.isError)
return <span>Error loading hourly forecast.</span>;
if (!forecastHourly.data) return <span>No hourly forecast data.</span>;
if ("code" in forecastHourly.data)
return <span>{forecastHourly.data.code}</span>;

return (
<div className="flex max-w-screen-md select-none flex-row gap-4 overflow-y-auto">
{forecast.data.map((temp, index) => (
{[
22.1, 21.9, 21.6, 21.4, 21.2, 21.1, 21.0, 20.9, 20.8, 20.7, 20.6, 20.5,
].map((temp, index) => (
<div key={index} className="flex flex-col items-stretch gap-1">
<div className="flex flex-row items-center gap-1">
<CloudSun className="h-16 w-16" />
Expand Down
18 changes: 14 additions & 4 deletions src/app/_components/forecast-now.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";

import { getLocationFromLocalStorage } from "~/lib/localStorage";
import { getWeatherForecastNow } from "~/lib/serverActions/tomorrowio";
import {
type WeatherForecastErrorResponse,
type WeatherForecastNow,
getWeatherForecastNow,
} from "~/lib/serverActions/tomorrowio";

dayjs.extend(relativeTime);

Expand All @@ -18,17 +22,23 @@ export function ForecastNow() {
const forecastNow = useQuery({
staleTime: 1000 * 60 * 5, // 5 minutes
queryKey: [location.data, "forecast", "now"],
queryFn: async () => {
if (location.isLoading || !location.data) return null;
queryFn: async (): Promise<
WeatherForecastErrorResponse | WeatherForecastNow
> => {
if (location.isLoading || !location.data)
return Promise.reject("No location data.");
console.log("Get forecast now for location:", location.data);
return getWeatherForecastNow(location.data);
},
});

if (location.isLoading) return <span>Loading location...</span>;
if (location.isError) return <span>Error loading location...</span>;
if (forecastNow.isLoading) return <span>Loading forecast...</span>;
if (forecastNow.isError) return <span>Error loading forecast...</span>;
if (forecastNow.isError) return <span>Error loading forecast.</span>;
if (!forecastNow.data) return <span>No forecast data.</span>;
if ("code" in forecastNow.data)
return <span>{forecastNow.data.message}</span>;

return (
<div className="flex select-none flex-col gap-6">
Expand Down
1 change: 0 additions & 1 deletion src/app/_components/location-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { LocateFixed } from "lucide-react";
import { useForm } from "react-hook-form";
import { useQueryClient } from "@tanstack/react-query";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

import { Button } from "~/components/ui/button";
Expand Down
26 changes: 13 additions & 13 deletions src/lib/serverActions/tomorrowio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ export type WeatherForecastNow = {

export async function getWeatherForecastNow(
location: Location,
): Promise<WeatherForecastNow> {
): Promise<WeatherForecastErrorResponse | WeatherForecastNow> {
return unstable_cache(
async (): Promise<WeatherForecastNow> => {
async (): Promise<WeatherForecastErrorResponse | WeatherForecastNow> => {
const response = await fetch(
`${env.WEATHER_BASE_URL}/realtime?${BASE_PARAMS}&location=${location.latitude},${location.longitude}`,
BASE_REQUEST_OPTIONS,
Expand All @@ -88,7 +88,7 @@ export async function getWeatherForecastNow(
| WeatherForecastErrorResponse
| WeatherForecastNowResponse;
console.log("Response:", responseData);
if ("code" in responseData) return Promise.reject(responseData);
if ("code" in responseData) return responseData;

return {
time: responseData.data.time,
Expand All @@ -103,15 +103,15 @@ export async function getWeatherForecastNow(
)();
}

export type WeatherForecastHourlyResponse = {};
export type WeatherForecastHourlyResponse = any;

export type WeatherForecastHourly = {};
export type WeatherForecastHourly = any;

export async function getWeatherForecastHourly(
location: Location,
): Promise<WeatherForecastHourly> {
): Promise<WeatherForecastErrorResponse | WeatherForecastHourly> {
return unstable_cache(
async (): Promise<WeatherForecastHourly> => {
async (): Promise<WeatherForecastErrorResponse | WeatherForecastHourly> => {
const response = await fetch(
`${env.WEATHER_API_KEY}/forecast?${BASE_PARAMS}&location=${location.latitude},${location.longitude}&timesteps=1h`,
BASE_REQUEST_OPTIONS,
Expand All @@ -120,7 +120,7 @@ export async function getWeatherForecastHourly(
| WeatherForecastErrorResponse
| WeatherForecastHourlyResponse;
console.log("Response:", responseData);
if ("code" in responseData) return Promise.reject(responseData);
if ("code" in responseData) return responseData;

return {};
},
Expand All @@ -132,15 +132,15 @@ export async function getWeatherForecastHourly(
)();
}

export type WeatherForecastDailyResponse = {};
export type WeatherForecastDailyResponse = any;

export type WeatherForecastDaily = {};
export type WeatherForecastDaily = any;

export async function getWeatherForecastDaily(
location: Location,
): Promise<WeatherForecastDaily> {
): Promise<WeatherForecastErrorResponse | WeatherForecastDaily> {
return unstable_cache(
async (): Promise<WeatherForecastDaily> => {
async (): Promise<WeatherForecastErrorResponse | WeatherForecastDaily> => {
const response = await fetch(
`${env.WEATHER_API_KEY}/forecast?${BASE_PARAMS}&location=${location.latitude},${location.longitude}&timesteps=1d`,
BASE_REQUEST_OPTIONS,
Expand All @@ -149,7 +149,7 @@ export async function getWeatherForecastDaily(
| WeatherForecastErrorResponse
| WeatherForecastDailyResponse;
console.log("Response:", responseData);
if ("code" in responseData) return Promise.reject(responseData);
if ("code" in responseData) return responseData;

return {};
},
Expand Down

0 comments on commit a1c6152

Please sign in to comment.