PatchList.tsx
⎇
Raw
1import type { PatchRow, RepositoryRow } from "../../db/index.ts";
2import { displayName } from "../../lib/users.ts";
3import type { SessionUser } from "../../middleware/session.ts";
4import { Avatar } from "../Avatar.tsx";
5import { Layout } from "../layout.tsx";
6import { Pagination, type PaginationInfo } from "../Pagination.tsx";
7import { RepoHeader } from "../repos/RepoHeader.tsx";
8import { RepoNav } from "../repos/RepoNav.tsx";
9
10interface PatchListProps {
11 user: SessionUser | null;
12 repo: RepositoryRow;
13 patches: (PatchRow & {
14 author_username: string;
15 author_avatar_version: number | null;
16 })[];
17 status: string;
18 counts: Record<string, number>;
19 pagination: PaginationInfo;
20}
21
22export function PatchList({
23 user,
24 repo,
25 patches,
26 status,
27 counts,
28 pagination,
29}: PatchListProps) {
30 return (
31 <Layout user={user} title={`Patches — ${repo.name}`}>
32 <div class="container">
33 <RepoHeader repo={repo} />
34 <RepoNav repo={repo} active="patches" user={user} />
35 <div class="list-header">
36 <div class="list-header-tabs">
37 <a
38 href={`/${repo.name}/patches?status=open`}
39 class={`list-tab${status === "open" ? " active" : ""}`}
40 >
41 Open{" "}
42 {(counts.open ?? 0) > 0 && (
43 <span class="tab-count">{counts.open}</span>
44 )}
45 </a>
46 <a
47 href={`/${repo.name}/patches?status=merged`}
48 class={`list-tab${status === "merged" ? " active" : ""}`}
49 >
50 Merged{" "}
51 {(counts.merged ?? 0) > 0 && (
52 <span class="tab-count">{counts.merged}</span>
53 )}
54 </a>
55 <a
56 href={`/${repo.name}/patches?status=closed`}
57 class={`list-tab${status === "closed" ? " active" : ""}`}
58 >
59 Closed{" "}
60 {(counts.closed ?? 0) > 0 && (
61 <span class="tab-count">{counts.closed}</span>
62 )}
63 </a>
64 </div>
65 {user && (
66 <a
67 href={`/${repo.name}/patches/new`}
68 class="btn btn-primary btn-sm"
69 >
70 Upload patch
71 </a>
72 )}
73 </div>
74 {patches.length === 0 ? (
75 <div class="empty-state">
76 <p>No {status} patches.</p>
77 </div>
78 ) : (
79 <ul class="issue-list">
80 {patches.map((patch) => (
81 <li class="issue-item">
82 <div class="issue-main">
83 <span
84 class={`patch-status-dot ${patch.status}`}
85 />
86 <a
87 href={`/${repo.name}/patches/${patch.number}`}
88 class="issue-title"
89 >
90 {patch.title}
91 </a>
92 <span class="issue-number">
93 #{patch.number}
94 </span>
95 </div>
96 <div class="issue-meta">
97 <Avatar
98 userId={patch.author_id}
99 version={patch.author_avatar_version}
100 size={20}
101 />
102 <span>
103 by {displayName(patch.author_username)}
104 </span>
105 <time datetime={patch.created_at}>
106 {new Date(
107 patch.created_at,
108 ).toLocaleDateString()}
109 </time>
110 </div>
111 </li>
112 ))}
113 </ul>
114 )}
115 <Pagination {...pagination} />
116 </div>
117 </Layout>
118 );
119}
120