Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 52 additions & 16 deletions src/app/(app)/prs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ function PRRow({ c, appUrl, isLast }: { c: Claim; appUrl: string; isLast: boolea
export default function PRsPage() {
const [claims, setClaims] = useState<Claim[]>([]);
const [filter, setFilter] = useState<"all" | "pending" | "claimed">("all");
const [search, setSearch] = useState("");

const load = async () => {
try {
Expand All @@ -143,37 +144,72 @@ export default function PRsPage() {
}, []);

const filtered = claims.filter((c) => {
if (filter === "pending") return !c.claimed;
if (filter === "claimed") return c.claimed;
if (filter === "pending" && c.claimed) return false;
if (filter === "claimed" && !c.claimed) return false;
if (search) {
const q = search.toLowerCase();
return c.githubUsername.toLowerCase().includes(q) || c.repo.toLowerCase().includes(q) || c.prTitle.toLowerCase().includes(q);
}
return true;
});

const avgScore = claims.length ? Math.round(claims.reduce((s, c) => s + c.score, 0) / claims.length) : 0;
const appUrl = typeof window !== "undefined" ? window.location.origin : "";

return (
<>
<Topbar />
<div style={{ flex: 1, overflowY: "auto", padding: "28px 40px 48px" }}>
<div style={{ display: "flex", gap: "4px", marginBottom: "20px" }}>
{(["all", "pending", "claimed"] as const).map((f) => (
<button key={f} onClick={() => setFilter(f)} style={{
padding: "6px 14px", borderRadius: "7px", border: "1px solid",
borderColor: filter === f ? "#000" : "#e4e4e7",
background: filter === f ? "#000" : "#fff",
color: filter === f ? "#fff" : "#71717a",
fontSize: "12px", fontWeight: 500, cursor: "pointer", fontFamily: "inherit",
textTransform: "capitalize",
}}>
{f}
</button>
))}

{/* Stats row */}
{claims.length > 0 && (
<div style={{ display: "flex", gap: "12px", marginBottom: "24px", maxWidth: "800px" }}>
{[
{ label: "Total PRs", value: claims.length },
{ label: "Pending", value: claims.filter(c => !c.claimed).length },
{ label: "Claimed", value: claims.filter(c => c.claimed).length },
{ label: "Avg Score", value: avgScore },
].map(({ label, value }) => (
<div key={label} style={{ flex: 1, border: "1px solid #e4e4e7", borderRadius: "10px", padding: "12px 16px" }}>
<div style={{ fontSize: "11px", color: "#a1a1aa", fontWeight: 500, marginBottom: "4px" }}>{label}</div>
<div style={{ fontSize: "20px", fontWeight: 700, color: "#000" }}>{value}</div>
</div>
))}
</div>
)}

{/* Toolbar */}
<div style={{ display: "flex", gap: "8px", marginBottom: "16px", maxWidth: "800px" }}>
<div style={{ display: "flex", gap: "4px" }}>
{(["all", "pending", "claimed"] as const).map((f) => (
<button key={f} onClick={() => setFilter(f)} style={{
padding: "6px 14px", borderRadius: "7px", border: "1px solid",
borderColor: filter === f ? "#000" : "#e4e4e7",
background: filter === f ? "#000" : "#fff",
color: filter === f ? "#fff" : "#71717a",
fontSize: "12px", fontWeight: 500, cursor: "pointer", fontFamily: "inherit",
textTransform: "capitalize",
}}>
{f}
</button>
))}
</div>
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search by contributor, repo, or title…"
style={{
flex: 1, padding: "6px 12px", border: "1px solid #e4e4e7", borderRadius: "7px",
fontSize: "12px", fontFamily: "inherit", color: "#000", outline: "none", background: "#fff",
}}
/>
Comment on lines +197 to +205
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add aria-label for accessibility.

The search input relies solely on placeholder for context, which is not announced by all screen readers. Adding an aria-label improves accessibility.

♿ Proposed fix
           <input
             value={search}
             onChange={(e) => setSearch(e.target.value)}
             placeholder="Search by contributor, repo, or title…"
+            aria-label="Search pull requests"
             style={{
📝 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
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search by contributor, repo, or title…"
style={{
flex: 1, padding: "6px 12px", border: "1px solid #e4e4e7", borderRadius: "7px",
fontSize: "12px", fontFamily: "inherit", color: "#000", outline: "none", background: "#fff",
}}
/>
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search by contributor, repo, or title…"
aria-label="Search pull requests"
style={{
flex: 1, padding: "6px 12px", border: "1px solid `#e4e4e7`", borderRadius: "7px",
fontSize: "12px", fontFamily: "inherit", color: "#000", outline: "none", background: "#fff",
}}
/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(app)/prs/page.tsx around lines 197 - 205, The search input
currently uses only a placeholder for context (the <input> with value={search}
and onChange={(e) => setSearch(e.target.value)}), which is not reliably
announced by screen readers; add an accessible label by adding an aria-label
attribute (e.g., aria-label="Search PRs by contributor, repo, or title") to the
same <input> element so assistive technologies get explicit context while
preserving the existing placeholder and behavior.

</div>

<div style={{ maxWidth: "800px" }}>
{filtered.length === 0 ? (
<div style={{ border: "1px dashed #e4e4e7", borderRadius: "12px", padding: "48px 24px", textAlign: "center" }}>
<GitMerge size={28} strokeWidth={1.5} color="#d4d4d8" style={{ display: "inline-block", marginBottom: "10px" }} />
<p style={{ fontSize: "14px", color: "#71717a" }}>No pull requests yet</p>
<p style={{ fontSize: "14px", color: "#71717a" }}>{search ? "No results matched your search" : "No pull requests yet"}</p>
</div>
Comment on lines 209 to 213
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider filter state in the empty message.

The message distinguishes between search and no-data, but doesn't account for filter state. If a user filters to "claimed" but all PRs are pending, they see "No pull requests yet" which is misleading since PRs exist.

💡 Suggested improvement
-              <p style={{ fontSize: "14px", color: "#71717a" }}>{search ? "No results matched your search" : "No pull requests yet"}</p>
+              <p style={{ fontSize: "14px", color: "#71717a" }}>
+                {search || filter !== "all"
+                  ? "No results matched your filters"
+                  : "No pull requests yet"}
+              </p>
📝 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
{filtered.length === 0 ? (
<div style={{ border: "1px dashed #e4e4e7", borderRadius: "12px", padding: "48px 24px", textAlign: "center" }}>
<GitMerge size={28} strokeWidth={1.5} color="#d4d4d8" style={{ display: "inline-block", marginBottom: "10px" }} />
<p style={{ fontSize: "14px", color: "#71717a" }}>No pull requests yet</p>
<p style={{ fontSize: "14px", color: "#71717a" }}>{search ? "No results matched your search" : "No pull requests yet"}</p>
</div>
{filtered.length === 0 ? (
<div style={{ border: "1px dashed `#e4e4e7`", borderRadius: "12px", padding: "48px 24px", textAlign: "center" }}>
<GitMerge size={28} strokeWidth={1.5} color="#d4d4d8" style={{ display: "inline-block", marginBottom: "10px" }} />
<p style={{ fontSize: "14px", color: "#71717a" }}>
{search || filter !== "all"
? "No results matched your filters"
: "No pull requests yet"}
</p>
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(app)/prs/page.tsx around lines 209 - 213, The empty-state message
currently only checks filtered and search; update the JSX where filtered and
search are used to also consider the active filter state (e.g., selectedFilter /
statusFilter / filters) so the message reflects whether there are no results
because of a search, an active filter, or truly no PRs; change the conditional
that renders the <div> to branch: if filtered.length === 0 and search show "No
results matched your search", else if filtered.length === 0 and a filter is
active show "No pull requests match the selected filter" (ideally including the
filter name), otherwise show "No pull requests yet". Use the existing symbols
filtered and search and the app's filter state variable to locate and implement
the logic in page.tsx.

) : (
<div style={{ border: "1px solid #e4e4e7", borderRadius: "12px", overflow: "hidden" }}>
Expand Down