Skip to content

agent: @U0AJM7X8FBR Admin - please update the mono/admin repo with a table show#8

Open
sweetmantech wants to merge 1 commit intomainfrom
agent/-u0ajm7x8fbr-admin---please-up-1773626328197
Open

agent: @U0AJM7X8FBR Admin - please update the mono/admin repo with a table show#8
sweetmantech wants to merge 1 commit intomainfrom
agent/-u0ajm7x8fbr-admin---please-up-1773626328197

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented Mar 16, 2026

Automated PR from coding agent.

Summary by CodeRabbit

  • New Features
    • Added a new admin dashboard page to view and analyze GitHub organization repositories with commit statistics.
    • Repositories table includes sortable columns for total commits, commit messages, and commit date ranges.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
admin Ready Ready Preview Mar 16, 2026 2:00am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

Introduces a new admin sandbox feature for viewing GitHub organization repositories with commit statistics. Adds a page route, React components for data display, a TanStack Query hook for fetching org repo data, a fetch utility for API calls, and TypeScript types for the org repository domain.

Changes

Cohort / File(s) Summary
Page Setup
app/sandboxes/orgs/page.tsx
Exports a new Next.js page component with metadata for the org repos view.
Type Definitions
types/org.ts
Defines OrgRepoRow and AdminSandboxOrgsResponse interfaces for org repository data structure.
Data Fetching
lib/fetchAdminSandboxOrgs.ts, hooks/useAdminSandboxOrgs.ts
Implements API utility to fetch org repos and a TanStack Query hook for client-side data fetching with Privy authentication.
UI Components
components/Orgs/OrgsPage.tsx, components/Orgs/OrgsTableContainer.tsx, components/Orgs/OrgsTable.tsx, components/Orgs/orgsColumns.tsx
Creates page layout component, data-fetching container, TanStack Table-based table component with sortable columns, and column definitions for repo name, commits, messages, dates, and account repo count.

Sequence Diagram

sequenceDiagram
    actor User
    participant OrgsTableContainer
    participant useAdminSandboxOrgs
    participant Privy as Privy Auth
    participant fetchUtil as fetchAdminSandboxOrgs
    participant API as API Endpoint
    participant OrgsTable

    User->>OrgsTableContainer: Page loads
    OrgsTableContainer->>useAdminSandboxOrgs: Hook executes
    useAdminSandboxOrgs->>Privy: Get access token
    Privy-->>useAdminSandboxOrgs: Return token
    useAdminSandboxOrgs->>fetchUtil: Call with token
    fetchUtil->>API: GET /api/admins/sandboxes/orgs
    API-->>fetchUtil: Return OrgRepoRow[]
    fetchUtil-->>useAdminSandboxOrgs: Return repos
    useAdminSandboxOrgs-->>OrgsTableContainer: Return data via TanStack Query
    OrgsTableContainer->>OrgsTable: Pass repos
    OrgsTable-->>User: Render sortable table
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A table springs to life, so neat and bright,
With org repos sorted, all aligned just right,
Each commit counted, dates arranged with care,
The sandbox admin's stats are now laid bare! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is incomplete and unclear. It starts with 'agent: @U0AJM7X8FBR Admin - please update the mono/admin repo with a table show' but cuts off mid-sentence, making it vague about what feature is actually being added. Complete and clarify the title to describe the actual changes. For example: 'Add organization repositories table with commit statistics' or 'Add OrgsPage with sortable repository table.'
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch agent/-u0ajm7x8fbr-admin---please-up-1773626328197
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
components/Orgs/orgsColumns.tsx (1)

22-38: Consider extracting a reusable sortable-header renderer.
The sort button/icon block is repeated across columns; extracting a small helper would reduce duplication and future drift.

Also applies to: 58-73, 80-95, 102-117

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Orgs/orgsColumns.tsx` around lines 22 - 38, The header render for
sortable columns is duplicated: extract a reusable SortableHeader component or
helper function (e.g., SortableHeader or renderSortableHeader) that accepts the
column object and a title, and replace each header: ({ column }) => (...) block
(currently tied to accessorKey like "total_commits" and using
column.toggleSorting, column.getIsSorted, Button, ArrowUp, ArrowDown,
ArrowUpDown) with a call to that helper; the helper should render the same
Button, call column.toggleSorting(column.getIsSorted() === "asc"), and display
the correct icon based on column.getIsSorted() to eliminate repetition across
the headers at the referenced locations.
lib/fetchAdminSandboxOrgs.ts (1)

23-24: Harden response parsing before returning repos.
Current JSON parsing assumes repos is an array; a malformed payload can propagate invalid data into the table.

♻️ Proposed refactor
 import { API_BASE_URL } from "@/lib/consts";
-import type { OrgRepoRow } from "@/types/org";
+import type { AdminSandboxOrgsResponse, OrgRepoRow } from "@/types/org";
@@
-  const data = await res.json();
-  return data.repos ?? [];
+  const data: Partial<AdminSandboxOrgsResponse> = await res.json();
+  return Array.isArray(data.repos) ? data.repos : [];
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/fetchAdminSandboxOrgs.ts` around lines 23 - 24, The JSON parsing in
fetchAdminSandboxOrgs currently returns data.repos unchecked which can propagate
malformed values; after awaiting res.json(), validate that the parsed value is
an object and that data.repos is an array before returning it (e.g., check
typeof data === "object" && Array.isArray(data.repos")), and if validation fails
return an empty array (or safely map/filter to produce an array of expected repo
shapes). Update the function around the lines using res.json(), data, and repos
to perform this defensive check and avoid returning non-array values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Orgs/OrgsTableContainer.tsx`:
- Around line 25-31: The empty-state branch in OrgsTableContainer currently only
checks repos and shows "No org repo data found."—update the component to
explicitly handle the Privy/query disabled state by checking the hook's ready
and authenticated flags (or accepting them as props) before showing the empty
message: if !ready show a loading/placeholder, if ready && !authenticated show
an auth prompt/message, if authenticated && !isLoading && !error &&
repos?.length === 0 show the "No org repo data found" message; reference the
OrgsTableContainer component and the repos/isLoading/error/ready/authenticated
values from the query hook to implement these conditional returns.

In `@hooks/useAdminSandboxOrgs.ts`:
- Around line 15-21: The query cache key in useAdminSandboxOrgs is too generic
(queryKey: ["admin","sandboxes","orgs"]) and can return another user's data
after logout/sign-in; change the query key to include the authenticated identity
(for example include getAccessToken() result or a stable user id) so cache is
scoped per user, or alternatively ensure you invalidate related queries on auth
changes (see LoginButton logout flow) by calling queryClient.invalidateQueries
or queryClient.removeQueries for the keys used by useAdminSandboxOrgs and other
auth-bound hooks (useAdminSandboxes, useIsAdmin).

---

Nitpick comments:
In `@components/Orgs/orgsColumns.tsx`:
- Around line 22-38: The header render for sortable columns is duplicated:
extract a reusable SortableHeader component or helper function (e.g.,
SortableHeader or renderSortableHeader) that accepts the column object and a
title, and replace each header: ({ column }) => (...) block (currently tied to
accessorKey like "total_commits" and using column.toggleSorting,
column.getIsSorted, Button, ArrowUp, ArrowDown, ArrowUpDown) with a call to that
helper; the helper should render the same Button, call
column.toggleSorting(column.getIsSorted() === "asc"), and display the correct
icon based on column.getIsSorted() to eliminate repetition across the headers at
the referenced locations.

In `@lib/fetchAdminSandboxOrgs.ts`:
- Around line 23-24: The JSON parsing in fetchAdminSandboxOrgs currently returns
data.repos unchecked which can propagate malformed values; after awaiting
res.json(), validate that the parsed value is an object and that data.repos is
an array before returning it (e.g., check typeof data === "object" &&
Array.isArray(data.repos")), and if validation fails return an empty array (or
safely map/filter to produce an array of expected repo shapes). Update the
function around the lines using res.json(), data, and repos to perform this
defensive check and avoid returning non-array values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e02d4192-ecab-4948-b410-4ed475294d24

📥 Commits

Reviewing files that changed from the base of the PR and between 3fcd006 and 2c00b49.

📒 Files selected for processing (8)
  • app/sandboxes/orgs/page.tsx
  • components/Orgs/OrgsPage.tsx
  • components/Orgs/OrgsTable.tsx
  • components/Orgs/OrgsTableContainer.tsx
  • components/Orgs/orgsColumns.tsx
  • hooks/useAdminSandboxOrgs.ts
  • lib/fetchAdminSandboxOrgs.ts
  • types/org.ts

Comment on lines +25 to +31
if (!repos || repos.length === 0) {
return (
<div className="flex items-center justify-center py-12 text-sm text-gray-400">
No org repo data found.
</div>
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether auth-gating exists before rendering this container and whether disabled-query states are handled.
rg -nP --type=tsx 'useAdminSandboxOrgs\(' -C2
rg -nP --type=tsx 'No org repo data found' -C2
rg -nP --type=ts --type=tsx 'usePrivy\(|authenticated|ready|redirect\(' -C2

Repository: recoupable/admin

Length of output: 143


🏁 Script executed:

#!/bin/bash
# Find TypeScript/TSX files and search for relevant patterns
fd -e tsx -e ts | head -20

# Search for the component and hook usage
rg "useAdminSandboxOrgs" -A 5 -B 2

# Search for auth-related patterns
rg "usePrivy\|authenticated\|ready" -A 2 -B 2

# Find the specific error message
rg "No org repo data found"

# Check if route has auth protection
rg "middleware\|auth\|redirect" | grep -E "(middleware|auth|route)" | head -20

Repository: recoupable/admin

Length of output: 2137


🏁 Script executed:

#!/bin/bash
# Read the hook implementation
echo "=== Hook Implementation ==="
cat -n hooks/useAdminSandboxOrgs.ts

echo ""
echo "=== Component Implementation ==="
cat -n components/Orgs/OrgsTableContainer.tsx

echo ""
echo "=== Parent page that uses this component ==="
cat -n components/Orgs/OrgsPage.tsx

Repository: recoupable/admin

Length of output: 2830


🏁 Script executed:

#!/bin/bash
# Check the route page
echo "=== Route page ==="
cat -n app/sandboxes/orgs/page.tsx

echo ""
echo "=== Check for middleware ==="
find . -name "middleware.*" -o -name "*middleware*" | grep -v node_modules

echo ""
echo "=== Check for auth guards in app layout ==="
cat -n app/layout.tsx | head -50

Repository: recoupable/admin

Length of output: 1682


Handle disabled query state explicitly in OrgsTableContainer.

When the query is disabled (user not authenticated or Privy not ready), isLoading and error are both falsy, causing the component to display "No org repo data found." This is misleading UX that masks authentication state instead of indicating why data cannot be loaded.

Add explicit ready and authenticated checks before showing the empty state. The hook already has access to Privy state; the container needs to mirror these checks or pass them through.

Suggested approach
 "use client";
 
 import { useAdminSandboxOrgs } from "@/hooks/useAdminSandboxOrgs";
 import OrgsTable from "@/components/Orgs/OrgsTable";
+import { usePrivy } from "@privy-io/react-auth";
 
 export default function OrgsTableContainer() {
+  const { ready, authenticated } = usePrivy();
   const { data: repos, isLoading, error } = useAdminSandboxOrgs();
+
+  if (!ready) {
+    return <div className="flex items-center justify-center py-12 text-sm text-gray-500">Loading…</div>;
+  }
+
+  if (!authenticated) {
+    return <div className="flex items-center justify-center py-12 text-sm text-gray-400">Sign in to view org repos.</div>;
+  }
 
   if (isLoading) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!repos || repos.length === 0) {
return (
<div className="flex items-center justify-center py-12 text-sm text-gray-400">
No org repo data found.
</div>
);
}
"use client";
import { useAdminSandboxOrgs } from "@/hooks/useAdminSandboxOrgs";
import OrgsTable from "@/components/Orgs/OrgsTable";
import { usePrivy } from "@privy-io/react-auth";
export default function OrgsTableContainer() {
const { ready, authenticated } = usePrivy();
const { data: repos, isLoading, error } = useAdminSandboxOrgs();
if (!ready) {
return <div className="flex items-center justify-center py-12 text-sm text-gray-500">Loading…</div>;
}
if (!authenticated) {
return <div className="flex items-center justify-center py-12 text-sm text-gray-400">Sign in to view org repos.</div>;
}
if (isLoading) {
return (
<div className="flex items-center justify-center py-12 text-sm text-gray-500">
Loading org repos...
</div>
);
}
if (error) {
return (
<div className="flex items-center justify-center py-12 text-sm text-red-400">
Error loading org repos.
</div>
);
}
if (!repos || repos.length === 0) {
return (
<div className="flex items-center justify-center py-12 text-sm text-gray-400">
No org repo data found.
</div>
);
}
return <OrgsTable repos={repos} />;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Orgs/OrgsTableContainer.tsx` around lines 25 - 31, The empty-state
branch in OrgsTableContainer currently only checks repos and shows "No org repo
data found."—update the component to explicitly handle the Privy/query disabled
state by checking the hook's ready and authenticated flags (or accepting them as
props) before showing the empty message: if !ready show a loading/placeholder,
if ready && !authenticated show an auth prompt/message, if authenticated &&
!isLoading && !error && repos?.length === 0 show the "No org repo data found"
message; reference the OrgsTableContainer component and the
repos/isLoading/error/ready/authenticated values from the query hook to
implement these conditional returns.

Comment on lines +15 to +21
queryKey: ["admin", "sandboxes", "orgs"],
queryFn: async () => {
const token = await getAccessToken();
if (!token) throw new Error("Not authenticated");
return fetchAdminSandboxOrgs(token);
},
enabled: ready && authenticated,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether query cache is user-scoped or explicitly cleared on auth transitions.
rg -nP --type=ts --type=tsx 'queryKey:\s*\[\s*"admin"\s*,\s*"sandboxes"(?:\s*,\s*"orgs")?' -C2
rg -nP --type=ts --type=tsx 'removeQueries|resetQueries|clear\(|invalidateQueries|signOut|logout|logOut' -C2

Repository: recoupable/admin

Length of output: 115


🏁 Script executed:

#!/bin/bash
# Find the target file and understand the codebase structure
find . -name "useAdminSandboxOrgs.ts" -o -name "useAdminSandboxOrgs.tsx" 2>/dev/null

# Also look for hooks directory
fd -type f 'useAdmin' . 2>/dev/null | head -20

Repository: recoupable/admin

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Search for cache clearing patterns without type restrictions
rg "queryKey.*admin.*sandbox" -B 2 -A 5 2>/dev/null
rg "invalidateQueries|removeQueries|resetQueries|clearCache|signOut|logout" -B 1 -A 2 2>/dev/null | head -50

Repository: recoupable/admin

Length of output: 1483


🏁 Script executed:

#!/bin/bash
# Look for Privy auth setup and cache clearing
rg "usePrivy|signOut|logout|authentication" -B 1 -A 1 2>/dev/null | head -80

Repository: recoupable/admin

Length of output: 2343


🏁 Script executed:

#!/bin/bash
# Check query client setup and cache clearing handlers
rg "QueryClient|new QueryClient" -B 2 -A 5 2>/dev/null
rg "logout|signOut" -B 3 -A 5 2>/dev/null | grep -A 5 -B 3 "logout\|signOut"

Repository: recoupable/admin

Length of output: 1844


🏁 Script executed:

#!/bin/bash
# Check useIsAdmin.ts for same pattern
cat hooks/useIsAdmin.ts 2>/dev/null

Repository: recoupable/admin

Length of output: 869


🏁 Script executed:

#!/bin/bash
# Check where useAdminSandboxOrgs is used and if there's cache invalidation nearby
rg "useAdminSandboxOrgs" -B 2 -A 2 2>/dev/null

Repository: recoupable/admin

Length of output: 1004


🏁 Script executed:

#!/bin/bash
# Check PrivyProvider for logout handlers or cache clearing
cat providers/PrivyProvider.tsx 2>/dev/null

Repository: recoupable/admin

Length of output: 973


🏁 Script executed:

#!/bin/bash
# Check full useAdminSandboxOrgs.ts implementation
cat hooks/useAdminSandboxOrgs.ts 2>/dev/null

Repository: recoupable/admin

Length of output: 785


Scope the query cache key to the authenticated identity.

Using a static key for authenticated data risks serving stale cached data after logout/sign-in/user-switch in the same browser session. When logout() is called in LoginButton, the query cache is not cleared, so subsequent logins will retrieve data cached under the previous user's session.

This pattern affects multiple auth-bound queries (useAdminSandboxOrgs, useAdminSandboxes, useIsAdmin). Either scope query keys to user identity or implement explicit cache invalidation on auth state changes.

🔐 Proposed fix
 export function useAdminSandboxOrgs() {
-  const { ready, authenticated, getAccessToken } = usePrivy();
+  const { ready, authenticated, user, getAccessToken } = usePrivy();
 
   return useQuery({
-    queryKey: ["admin", "sandboxes", "orgs"],
+    queryKey: ["admin", "sandboxes", "orgs", user?.id],
     queryFn: async () => {
       const token = await getAccessToken();
       if (!token) throw new Error("Not authenticated");
       return fetchAdminSandboxOrgs(token);
     },
-    enabled: ready && authenticated,
+    enabled: ready && authenticated && !!user?.id,
   });
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useAdminSandboxOrgs.ts` around lines 15 - 21, The query cache key in
useAdminSandboxOrgs is too generic (queryKey: ["admin","sandboxes","orgs"]) and
can return another user's data after logout/sign-in; change the query key to
include the authenticated identity (for example include getAccessToken() result
or a stable user id) so cache is scoped per user, or alternatively ensure you
invalidate related queries on auth changes (see LoginButton logout flow) by
calling queryClient.invalidateQueries or queryClient.removeQueries for the keys
used by useAdminSandboxOrgs and other auth-bound hooks (useAdminSandboxes,
useIsAdmin).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant