refactor(web): preload user profile initial query in route loader

Quentin Gliech and Claude Opus 4.6 (1M context) created

preload the first page of the user profile (open issues, no cursor)
in the route loader so the router waits before transitioning.

subsequent pagination and status filter changes still use useQuery
which either serves from Apollo cache or fetches fresh.

add pendingComponent skeleton and remove the manual loading guard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Change summary

webui2/src/routes/$repo/_issues/user/$id.tsx | 26 +++++++++++++++++++--
1 file changed, 23 insertions(+), 3 deletions(-)

Detailed changes

webui2/src/routes/$repo/_issues/user/$id.tsx 🔗

@@ -18,7 +18,12 @@ import {
 } from "lucide-react";
 import { useState } from "react";
 
-import { Status, useUserProfileQuery } from "@/__generated__/graphql";
+import {
+  Status,
+  useUserProfileQuery,
+  type UserProfileQuery,
+  UserProfileDocument,
+} from "@/__generated__/graphql";
 import { LabelBadge } from "@/components/bugs/LabelBadge";
 import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
 import { BackLink } from "@/components/ui/back-link";
@@ -28,6 +33,23 @@ import { cn } from "@/lib/utils";
 
 export const Route = createFileRoute("/$repo/_issues/user/$id")({
   component: RouteComponent,
+  pendingComponent: ProfileSkeleton,
+  loader: async ({ context: { preloadQuery, ref }, params: { id } }) => {
+    // Preload the initial page (open issues, no cursor) so the router
+    // waits before transitioning. Subsequent pagination/filter changes
+    // use useQuery which hits the Apollo cache or fetches fresh.
+    const profileRef = preloadQuery<UserProfileQuery>(UserProfileDocument, {
+      variables: {
+        ref,
+        prefix: id,
+        openQuery: `author:${id} status:open`,
+        closedQuery: `author:${id} status:closed`,
+        listQuery: `author:${id} status:open`,
+        after: undefined,
+      },
+    });
+    return { profileRef: await preloadQuery.toPromise(profileRef) };
+  },
 });
 
 const PAGE_SIZE = 25;
@@ -70,8 +92,6 @@ function RouteComponent() {
     );
   }
 
-  if (loading && !data) return <ProfileSkeleton />;
-
   const identity = data?.repository?.identity;
   if (!identity) {
     return <div className="text-muted-foreground py-16 text-center text-sm">User not found.</div>;