4.2 KB128 lines
Blame
1import type { Metadata } from "next";
2import Link from "next/link";
3import { groveApiUrl, timeAgo } from "@/lib/utils";
4
5interface Props {
6 params: Promise<{ owner: string; repo: string }>;
7 searchParams: Promise<{ ref?: string }>;
8}
9
10export async function generateMetadata({ params }: Props): Promise<Metadata> {
11 const { repo } = await params;
12 return { title: `Commits · ${repo}` };
13}
14
15async function getCommits(owner: string, repo: string, ref: string) {
16 const res = await fetch(
17 `${groveApiUrl}/api/repos/${owner}/${repo}/commits/${ref}?limit=50`,
18 { cache: "no-store" }
19 );
20 if (!res.ok) return null;
21 return res.json();
22}
23
24export default async function CommitsPage({ params, searchParams }: Props) {
25 const { owner, repo } = await params;
26 const { ref: refParam } = await searchParams;
27 const ref = refParam ?? "main";
28
29 const data = await getCommits(owner, repo, ref);
30
31 if (!data) {
32 return (
33 <div className="py-10">
34 <h1 className="text-lg" style={{ color: "var(--text-secondary)" }}>
35 Could not load commits
36 </h1>
37 </div>
38 );
39 }
40
41 if (data.commits.length === 0) {
42 return (
43 <div className="py-12 text-center">
44 <p className="text-sm" style={{ color: "var(--text-faint)" }}>
45 No commits yet on <span className="font-mono">{ref}</span>.
46 </p>
47 <p className="text-xs mt-1" style={{ color: "var(--text-faint)" }}>
48 Push your first commit to see history here.
49 </p>
50 </div>
51 );
52 }
53
54 return (
55 <>
56 <div style={{ border: "1px solid var(--border-subtle)" }}>
57 <table className="w-full text-sm">
58 <tbody>
59 {data.commits.map((commit: any, i: number) => {
60 const hash = commit.hash;
61 const subject = commit.subject ?? "";
62 const authorName = commit.author?.split("<")[0]?.trim() ?? commit.author;
63 const initial = authorName?.[0]?.toUpperCase() ?? "?";
64 return (
65 <tr
66 key={commit.hash}
67 className="hover-row"
68 style={{
69 borderTop:
70 i > 0 ? "1px solid var(--divide)" : undefined,
71 }}
72 >
73 <td className="py-2 pl-3 pr-2 w-8">
74 <span
75 title={commit.author}
76 style={{
77 display: "inline-flex",
78 alignItems: "center",
79 justifyContent: "center",
80 width: 22,
81 height: 22,
82 borderRadius: "50%",
83 backgroundColor: "var(--bg-inset)",
84 border: "1px solid var(--border-subtle)",
85 color: "var(--text-muted)",
86 fontSize: "0.65rem",
87 cursor: "default",
88 }}
89 >
90 {initial}
91 </span>
92 </td>
93 <td className="py-2 pr-3 truncate" style={{ maxWidth: 0 }}>
94 <Link
95 href={`/${owner}/${repo}/commit/${hash}`}
96 className="hover:underline"
97 style={{ color: "var(--text-primary)" }}
98 >
99 {subject}
100 </Link>
101 </td>
102 <td
103 className="py-2 pr-3 font-mono text-xs w-16 hidden sm:table-cell"
104 >
105 <Link
106 href={`/${owner}/${repo}/commit/${hash}`}
107 style={{ color: "var(--accent)" }}
108 className="hover:underline"
109 >
110 {hash.slice(0, 7)}
111 </Link>
112 </td>
113 <td
114 className="py-2 pr-3 text-xs w-20 text-right"
115 style={{ color: "var(--text-faint)" }}
116 >
117 {timeAgo(commit.timestamp)}
118 </td>
119 </tr>
120 );
121 })}
122 </tbody>
123 </table>
124 </div>
125 </>
126 );
127}
128