From 289d91ef18816c04f739efac9787ee69d523d67c Mon Sep 17 00:00:00 2001 From: ogzhanolguncu Date: Tue, 17 Jun 2025 16:07:41 +0300 Subject: [PATCH 01/11] refactor: move page to client using trpc --- .../_components/ratelimit-client.tsx | 49 +++++++++++------ .../ratelimits/_components/skeletons.tsx | 53 +++++++++++++++++++ apps/dashboard/app/(app)/ratelimits/page.tsx | 28 ++-------- 3 files changed, 88 insertions(+), 42 deletions(-) create mode 100644 apps/dashboard/app/(app)/ratelimits/_components/skeletons.tsx diff --git a/apps/dashboard/app/(app)/ratelimits/_components/ratelimit-client.tsx b/apps/dashboard/app/(app)/ratelimits/_components/ratelimit-client.tsx index 729aa7ef32..6c5d1cf69d 100644 --- a/apps/dashboard/app/(app)/ratelimits/_components/ratelimit-client.tsx +++ b/apps/dashboard/app/(app)/ratelimits/_components/ratelimit-client.tsx @@ -1,11 +1,13 @@ "use client"; import { EmptyComponentSpacer } from "@/components/empty-component-spacer"; +import { trpc } from "@/lib/trpc/client"; import { Button, CopyButton, Empty } from "@unkey/ui"; import { BookOpen } from "lucide-react"; -import { type PropsWithChildren, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { RatelimitListControlCloud } from "./control-cloud"; import { RatelimitListControls } from "./controls"; import { NamespaceCard } from "./namespace-card"; +import { NamespaceCardSkeleton } from "./skeletons"; const EXAMPLE_SNIPPET = `curl -XPOST 'https://api.unkey.dev/v1/ratelimits.limit' \\ -H 'Content-Type: application/json' \\ @@ -17,25 +19,40 @@ const EXAMPLE_SNIPPET = `curl -XPOST 'https://api.unkey.dev/v1/ratelimits.limit' "duration": 10000 }'`; -export const RatelimitClient = ({ - ratelimitNamespaces, -}: PropsWithChildren<{ - ratelimitNamespaces: { - id: string; - name: string; - }[]; -}>) => { - const [namespaces, setNamespaces] = useState(ratelimitNamespaces); +export const RatelimitClient = () => { + const { data: namespacesData, isLoading } = trpc.ratelimit.namespace.query.useInfiniteQuery( + { limit: 10 }, + { + getNextPageParam: (lastPage) => lastPage.nextCursor, + }, + ); + + const allNamespaces = useMemo(() => { + if (!namespacesData?.pages) { + return []; + } + return namespacesData.pages.flatMap((page) => page.namespaceList); + }, [namespacesData]); + + const [namespaces, setNamespaces] = useState(allNamespaces); + + useEffect(() => { + setNamespaces(allNamespaces); + }, [allNamespaces]); return (
- + - {namespaces.length > 0 ? ( + {isLoading ? ( +
+ {Array.from({ length: 10 }).map((_, i) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: it's okay to use index here + + ))} +
+ ) : namespaces.length > 0 ? (
{namespaces.map((namespace) => ( @@ -50,7 +67,6 @@ export const RatelimitClient = ({ You haven't created any Namespaces yet. Create one by performing a limit request as shown below. -
@@ -59,7 +75,6 @@ export const RatelimitClient = ({
                 
               
- -
+ { - const { data: namespacesData, isLoading } = trpc.ratelimit.namespace.query.useInfiniteQuery( + const { + data: namespacesData, + isLoading, + error, + isError, + } = trpc.ratelimit.namespace.query.useInfiniteQuery( { limit: 10 }, { getNextPageParam: (lastPage) => lastPage.nextCursor, @@ -45,7 +50,15 @@ export const RatelimitClient = () => { - {isLoading ? ( + {isError ? ( + + + + Failed to load namespaces + {error?.message ?? "Unknown error"} + + + ) : isLoading ? (
{Array.from({ length: 10 }).map((_, i) => ( // biome-ignore lint/suspicious/noArrayIndexKey: it's okay to use index here