From a93614ffa6828a1faafb44be5a35b63fcb1c204e Mon Sep 17 00:00:00 2001 From: Brace Sproul Date: Thu, 19 Jun 2025 12:28:06 -0700 Subject: [PATCH] feat: Implement a loading and empty state for recent & running threads (#257) * feat: Implement a loading and empty state for recent & running threads * cr --- apps/web/src/app/(v2)/chat/page.tsx | 7 ++-- apps/web/src/components/v2/default-view.tsx | 39 +++++++++++++++------ apps/web/src/components/v2/thread-card.tsx | 35 ++++++++++++++++++ 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/apps/web/src/app/(v2)/chat/page.tsx b/apps/web/src/app/(v2)/chat/page.tsx index 4d04aefc..fe08a95b 100644 --- a/apps/web/src/app/(v2)/chat/page.tsx +++ b/apps/web/src/app/(v2)/chat/page.tsx @@ -9,7 +9,7 @@ import { Toaster } from "@/components/ui/sonner"; import { Suspense } from "react"; export default function ChatPage() { - const { threads } = useThreads( + const { threads, threadsLoading } = useThreads( process.env.NEXT_PUBLIC_MANAGER_ASSISTANT_ID, ); @@ -22,7 +22,10 @@ export default function ChatPage() { - + diff --git a/apps/web/src/components/v2/default-view.tsx b/apps/web/src/components/v2/default-view.tsx index b2850471..dd20d535 100644 --- a/apps/web/src/components/v2/default-view.tsx +++ b/apps/web/src/components/v2/default-view.tsx @@ -17,6 +17,7 @@ import { GitPullRequest, Bug, FilePlus2, + Archive, } from "lucide-react"; import { useRouter } from "next/navigation"; import { ThreadDisplayInfo } from "./types"; @@ -33,13 +34,14 @@ import { Label } from "../ui/label"; import { ContentBlocksPreview } from "../thread/ContentBlocksPreview"; import { TooltipIconButton } from "../ui/tooltip-icon-button"; import { ThemeToggle } from "../theme-toggle"; -import { ThreadCard } from "./thread-card"; +import { ThreadCard, ThreadCardLoading } from "./thread-card"; interface DefaultViewProps { threads: ThreadDisplayInfo[]; + threadsLoading: boolean; } -export function DefaultView({ threads }: DefaultViewProps) { +export function DefaultView({ threads, threadsLoading }: DefaultViewProps) { const router = useRouter(); const apiUrl: string | undefined = process.env.NEXT_PUBLIC_API_URL ?? ""; const assistantId: string | undefined = @@ -149,14 +151,31 @@ export function DefaultView({ threads }: DefaultViewProps) { -
- {threads.slice(0, 4).map((thread) => ( - - ))} -
+ {threadsLoading || threads.length ? ( +
+ {threadsLoading && threads.length === 0 && ( + <> + + + + + + )} + {threads.slice(0, 4).map((thread) => ( + + ))} +
+ ) : ( +
+ + + No threads found + +
+ )} {/* Quick Actions */} diff --git a/apps/web/src/components/v2/thread-card.tsx b/apps/web/src/components/v2/thread-card.tsx index c8aa5a1b..f9b3e53f 100644 --- a/apps/web/src/components/v2/thread-card.tsx +++ b/apps/web/src/components/v2/thread-card.tsx @@ -11,6 +11,7 @@ import { ThreadDisplayInfo } from "./types"; import { useRouter } from "next/navigation"; import { Badge } from "../ui/badge"; import { Button } from "../ui/button"; +import { Skeleton } from "../ui/skeleton"; export function ThreadCard({ thread }: { thread: ThreadDisplayInfo }) { const router = useRouter(); @@ -136,3 +137,37 @@ export function ThreadCard({ thread }: { thread: ThreadDisplayInfo }) { ); } + +export function ThreadCardLoading() { + return ( + + +
+
+ + + +
+ + +
+
+ +
+
+ +
+
+ + + +
+
+ + +
+
+
+
+ ); +}