Skip to content
26 changes: 17 additions & 9 deletions web/src/hooks/useCoinPrice.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import { useQuery } from "@tanstack/react-query";

const fetchCoinPrices = async (...coinIds) => {
const response = await fetch(`https://coins.llama.fi/prices/current/${coinIds.join(",")}?searchWidth=1h`);
const fetchCoinPrices = async (coinIds: readonly string[]): Promise<Prices> => {
const ids = Array.from(new Set(coinIds)).filter(Boolean).sort().map(encodeURIComponent).join(",");
if (!ids) return {};
const response = await fetch(`https://coins.llama.fi/prices/current/${ids}?searchWidth=1h`);
if (!response.ok) throw new Error(`Failed to fetch coin prices (${response.status})`);
const data = await response.json();
return data.coins;
return (data?.coins ?? {}) as Prices;
};

export type Prices = {
[coinId: string]: { price: number };
};

export const useCoinPrice = (coinIds: string[]) => {
const isEnabled = coinIds !== undefined;

const { data: prices, isError } = useQuery<Prices>({
queryKey: [`coinPrice${coinIds}`],
enabled: isEnabled,
queryFn: async () => fetchCoinPrices(coinIds),
const {
data: prices,
isError,
isLoading,
error,
} = useQuery<Prices>({
queryKey: ["coinPrice", coinIds],
enabled: Array.isArray(coinIds) && coinIds.length > 0,
queryFn: () => fetchCoinPrices(coinIds),
});
return {
prices,
isError,
isLoading,
error,
};
};
25 changes: 22 additions & 3 deletions web/src/pages/Courts/CourtDetails/Stats/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useCourtDetails } from "queries/useCourtDetails";
import { landscapeStyle } from "styles/landscapeStyle";

import StatsContent from "./StatsContent";
import Spinner from "components/Spinner";

const Container = styled.div`
padding: 0 24px 12px 24px;
Expand Down Expand Up @@ -50,13 +51,31 @@ const StyledAccordion = styled(Accordion)`
)}
`;

const ErrorMessage = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
color: ${({ theme }) => theme.error};
font-size: 16px;
font-weight: 500;
`;

const Stats = () => {
const { id } = useParams();
const { data } = useCourtDetails(id);
const { data, isLoading: isLoadingCourt, error: courtError } = useCourtDetails(id);
const coinIds = [CoinIds.PNK, CoinIds.ETH];
const { prices: pricesData } = useCoinPrice(coinIds);
const { prices: pricesData, isLoading: isLoadingPrices, error: pricesError } = useCoinPrice(coinIds);
const isDesktop = useIsDesktop();

if (isLoadingCourt || isLoadingPrices) {
return <Spinner />;
}

if (courtError || pricesError) {
return <ErrorMessage>Failed to load statistics</ErrorMessage>;
}

return isDesktop ? (
<Container>
<Header>Statistics</Header>
Expand All @@ -75,4 +94,4 @@ const Stats = () => {
);
};

export default Stats;
export default Stats;