Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
Commit1aef949unknown_key

feat(pr-list): review status badges (Approved / Changes requested)

feat(pr-list): review status badges (Approved / Changes requested)

Batch-load review states for all PRs in the list in a single query,
then render color-coded badges per row:
- Green "✓ Approved" badge when the PR has at least one approval
- Red "✗ Changes" badge when changes have been requested
Also adds inArray to drizzle-orm imports and CSS for both badge variants.

https://claude.ai/code/session_01ACsT2Pc8GRoZwZRF8SK68Y
Claude committed on May 28, 2026Parent: a164a6d
1 file changed+3411aef94958c9e1134e34c5820c01a07bcad6383b6
1 changed file+34−1
Modifiedsrc/routes/pulls.tsx+34−1View fileUnifiedSplit
1414 */
1515
1616import { Hono } from "hono";
17import { eq, and, desc, asc, sql } from "drizzle-orm";
17import { eq, and, desc, asc, sql, inArray } from "drizzle-orm";
1818import { db } from "../db";
1919import {
2020 pullRequests,
320320 border-color: rgba(140,109,255,0.45);
321321 background: rgba(140,109,255,0.10);
322322 }
323 .prs-tag.is-approved {
324 color: #34d399;
325 border-color: rgba(52,211,153,0.40);
326 background: rgba(52,211,153,0.08);
327 }
328 .prs-tag.is-changes {
329 color: #f87171;
330 border-color: rgba(248,113,113,0.40);
331 background: rgba(248,113,113,0.08);
332 }
323333
324334 .prs-empty {
325335 position: relative;
17741784 )
17751785 .orderBy(desc(pullRequests.createdAt));
17761786
1787 // Batch-load review states for all PRs in the list (approved / changes_requested badges)
1788 const reviewMap = new Map<string, { approved: boolean; changesRequested: boolean }>();
1789 if (prList.length > 0) {
1790 const prIds = prList.map(({ pr }) => pr.id);
1791 const reviewRows = await db
1792 .select({ prId: prReviews.pullRequestId, state: prReviews.state })
1793 .from(prReviews)
1794 .where(inArray(prReviews.pullRequestId, prIds));
1795 for (const r of reviewRows) {
1796 const entry = reviewMap.get(r.prId) ?? { approved: false, changesRequested: false };
1797 if (r.state === "approved") entry.approved = true;
1798 if (r.state === "changes_requested") entry.changesRequested = true;
1799 reviewMap.set(r.prId, entry);
1800 }
1801 }
1802
17771803 const [counts] = await db
17781804 .select({
17791805 open: sql<number>`count(*) filter (where ${pullRequests.state} = 'open')`,
19161942 : pr.state === "merged"
19171943 ? "⮌"
19181944 : "✓";
1945 const rv = reviewMap.get(pr.id);
19191946 return (
19201947 <a
19211948 href={`/${ownerName}/${repoName}/pulls/${pr.number}`}
19511978 {pr.state === "merged" && (
19521979 <span class="prs-tag is-merged">Merged</span>
19531980 )}
1981 {rv?.approved && !rv.changesRequested && (
1982 <span class="prs-tag is-approved" title="Approved by reviewer">✓ Approved</span>
1983 )}
1984 {rv?.changesRequested && (
1985 <span class="prs-tag is-changes" title="Changes requested">✗ Changes</span>
1986 )}
19541987 </span>
19551988 </div>
19561989 </div>
19571990