m/cup
1
0
mirror of https://github.com/sergi0g/cup.git synced 2025-11-08 05:03:49 -05:00

refactor: better data fetching (#100)

This commit is contained in:
Raphaël Catarino
2025-05-02 18:12:19 +02:00
committed by GitHub
parent 2ac036d353
commit 5ea924c5ad
4 changed files with 76 additions and 14 deletions

View File

@@ -4,11 +4,12 @@ import Statistic from "./components/Statistic";
import Image from "./components/Image";
import { LastChecked } from "./components/LastChecked";
import Loading from "./components/Loading";
import { Data } from "./types";
import { theme } from "./theme";
import RefreshButton from "./components/RefreshButton";
import Search from "./components/Search";
import { Server } from "./components/Server";
import { useData } from "./hooks/use-data";
import DataLoadingError from "./components/DataLoadingError";
const SORT_ORDER = [
"monitored_images",
@@ -22,10 +23,11 @@ const SORT_ORDER = [
];
function App() {
const [data, setData] = useState<Data | null>(null);
const { data, isLoading, isError } = useData();
const [searchQuery, setSearchQuery] = useState("");
if (!data) return <Loading onLoad={setData} />;
if (isLoading) return <Loading />;
if (isError || !data) return <DataLoadingError />;
return (
<div
className={`flex min-h-screen justify-center bg-white dark:bg-${theme}-950`}

View File

@@ -0,0 +1,30 @@
import Logo from "./Logo";
import { theme } from "../theme";
const DataLoadingError = () => {
return (
<div
className={`flex min-h-screen justify-center bg-${theme}-50 dark:bg-${theme}-950`}
>
<div className="absolute mx-auto h-full w-full max-w-[80rem] overflow-hidden px-4 sm:px-6 lg:px-8">
<div className="mx-auto my-8 flex h-full max-w-[48rem] flex-col">
<div className="flex items-center gap-1">
<h1 className="text-5xl font-bold lg:text-6xl dark:text-white">
Cup
</h1>
<Logo />
</div>
<div
className={`flex h-full flex-col items-center justify-center gap-1 text-${theme}-500 dark:text-${theme}-400`}
>
<div className="mb-8 flex gap-1">
An error occurred, please try again.
</div>
</div>
</div>
</div>
</div>
);
};
export default DataLoadingError;

View File

@@ -1,18 +1,8 @@
import { Data } from "../types";
import Logo from "./Logo";
import { theme } from "../theme";
import { LoaderCircle } from "lucide-react";
export default function Loading({ onLoad }: { onLoad: (data: Data) => void }) {
fetch(
process.env.NODE_ENV === "production"
? "./api/v3/json"
: `http://${window.location.hostname}:8000/api/v3/json`,
).then((response) =>
response.json().then((data) => {
onLoad(data as Data);
}),
);
export default function Loading() {
return (
<div
className={`flex min-h-screen justify-center bg-${theme}-50 dark:bg-${theme}-950`}

View File

@@ -0,0 +1,40 @@
import { useEffect, useState } from "react";
import type { Data } from "../types";
export const useData = () => {
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const [data, setData] = useState<Data | null>(null);
useEffect(() => {
if (isLoading || isError || !!data) return;
setIsLoading(true);
setIsError(false);
setData(null);
fetch(
process.env.NODE_ENV === "production"
? "./api/v3/json"
: `http://${window.location.hostname}:8000/api/v3/json`,
)
.then((response) => {
if (response.ok) return response.json();
throw new Error("Failed to fetch data");
})
.then((data) => {
setData(data as Data);
})
.catch((error: unknown) => {
setIsError(true);
console.error(error);
})
.finally(() => {
setIsLoading(false);
});
}, [data, isError, isLoading]);
return {
data,
isLoading,
isError,
};
};