返回 CodeWhale
feed-card.tsx
根目录 / web / components / feed-card.tsx
1 import Link from "next/link";
2 import type { FeedItem } from "@/lib/types";
3 import { relativeTime } from "@/lib/github";
4 import { Status, type StatusTone } from "./status-badge";
5
6 const KIND_LABEL: Record<FeedItem["kind"], string> = {
7 issue: "Issue",
8 pull: "Pull request",
9 release: "Release",
10 discussion: "Discussion",
11 };
12
13 // State is a mark and a word; the word is GitHub's own state.
14 const STATE_TONE: Record<FeedItem["state"], StatusTone> = {
15 open: "ready",
16 closed: "idle",
17 merged: "accent",
18 draft: "idle",
19 published: "ready",
20 };
21
22 /** One GitHub item: its state, title, labels and who opened it. */
23 export function FeedCard({ item }: { item: FeedItem; dense?: boolean }) {
24 return (
25 <article className="feed-card">
26 <div className="feed-card-meta">
27 <Status tone={STATE_TONE[item.state]}>{item.state}</Status>
28 <span>{KIND_LABEL[item.kind]}</span>
29 <span className="tabular">#{item.number}</span>
30 <span className="feed-card-time tabular">{relativeTime(item.updatedAt)}</span>
31 </div>
32 <h3 className="feed-card-title">
33 <Link href={item.url}>{item.title}</Link>
34 </h3>
35 <div className="feed-card-foot">
36 {item.labels.slice(0, 3).map((l) => (
37 <span key={l.name} className="pill">{l.name}</span>
38 ))}
39 <span className="feed-card-author">
40 @{item.author}
41 {item.comments > 0 && <span className="tabular"> · {item.comments} {item.comments === 1 ? "reply" : "replies"}</span>}
42 </span>
43 </div>
44 </article>
45 );
46 }
47
47 lines Plain Text