CommitDetail.tsx
⎇
Raw
1import type { RepositoryRow } from "../../db/index.ts";
2import type { SessionUser } from "../../middleware/session.ts";
3import type { RenderedDiffFile } from "../../services/diffHighlight.ts";
4import type { CommitMeta } from "../../services/git.ts";
5import { DiffView } from "../DiffView.tsx";
6import { Layout } from "../layout.tsx";
7import { RepoHeader } from "../repos/RepoHeader.tsx";
8import { RepoNav } from "./RepoNav.tsx";
9
10interface CommitDetailProps {
11 user: SessionUser | null;
12 repo: RepositoryRow;
13 sha: string;
14 meta: CommitMeta;
15 files: RenderedDiffFile[];
16}
17
18function formatDate(iso: string): string {
19 try {
20 return new Date(iso).toLocaleString(undefined, {
21 dateStyle: "medium",
22 timeStyle: "short",
23 });
24 } catch {
25 return iso;
26 }
27}
28
29export function CommitDetail({
30 user,
31 repo,
32 sha,
33 meta,
34 files,
35}: CommitDetailProps) {
36 return (
37 <Layout user={user} title={`${sha.slice(0, 7)} — ${repo.name}`}>
38 <div class="container">
39 <RepoHeader repo={repo} />
40 <RepoNav repo={repo} active="commits" user={user} />
41
42 {/* Back link */}
43 <div class="commit-page-top">
44 <a
45 href={`/${repo.name}/commits/${repo.default_branch}`}
46 class="btn btn-ghost btn-sm"
47 >
48 ← Back to log
49 </a>
50 <a
51 href={`/${repo.name}/tree/${sha}`}
52 class="btn btn-secondary btn-sm"
53 title={`Browse tree at ${sha.slice(0, 7)}`}
54 >
55 @ {sha.slice(0, 7)}
56 </a>
57 </div>
58
59 {/* Commit metadata card */}
60 <div class="commit-card">
61 <h2 class="commit-card-subject">{meta.subject}</h2>
62 {meta.body && (
63 <pre class="commit-card-body">{meta.body}</pre>
64 )}
65 <div class="commit-card-meta">
66 <div class="commit-card-meta-row">
67 <span class="commit-meta-label">Author</span>
68 <span class="commit-meta-value">
69 {meta.author} &lt;{meta.email}&gt;
70 </span>
71 </div>
72 <div class="commit-card-meta-row">
73 <span class="commit-meta-label">Date</span>
74 <time
75 class="commit-meta-value"
76 datetime={meta.date}
77 >
78 {formatDate(meta.date)}
79 </time>
80 </div>
81 <div class="commit-card-meta-row">
82 <span class="commit-meta-label">Commit</span>
83 <code class="commit-meta-value commit-sha-full mono">
84 {meta.hash}
85 </code>
86 </div>
87 {meta.parents.length > 0 && (
88 <div class="commit-card-meta-row">
89 <span class="commit-meta-label">
90 Parent{meta.parents.length > 1 ? "s" : ""}
91 </span>
92 <span class="commit-meta-value">
93 {meta.parents.map((p) => (
94 <a
95 href={`/${repo.name}/commit/${p}`}
96 class="commit-hash mono"
97 >
98 {p.slice(0, 7)}
99 </a>
100 ))}
101 </span>
102 </div>
103 )}
104 </div>
105 </div>
106
107 <DiffView files={files} repo={repo} sha={sha} />
108 </div>
109 </Layout>
110 );
111}
112