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