because I got bored of customising my CV for every job
1import { Card, StatusDot } from "@cv/ui";
2import type { QueueStatsQuery } from "@/generated/graphql";
3
4type Stats = NonNullable<QueueStatsQuery["queueStats"]>;
5
6const formatDuration = (seconds: number): string => {
7 if (seconds < 60) return `${Math.round(seconds)}s`;
8 const minutes = Math.floor(seconds / 60);
9 if (minutes < 60) return `${minutes}m ${Math.round(seconds % 60)}s`;
10 const hours = Math.floor(minutes / 60);
11 return `${hours}h ${minutes % 60}m`;
12};
13
14const DetailRow = ({
15 label,
16 value,
17}: {
18 label: string;
19 value: React.ReactNode;
20}) => (
21 <div className="flex justify-between py-1.5 border-b border-ctp-surface1 last:border-b-0">
22 <span className="text-sm text-ctp-subtext0">{label}</span>
23 <span className="text-sm font-medium text-ctp-text">{value}</span>
24 </div>
25);
26
27interface QueueStatsCardProps {
28 stats: Stats;
29}
30
31export const QueueStatsCard = ({ stats }: QueueStatsCardProps) => (
32 <Card>
33 <h3 className="mb-3 text-lg font-medium text-ctp-text">Queue</h3>
34 <div className="space-y-0">
35 <DetailRow
36 label="Pending"
37 value={
38 <span className="flex items-center gap-2">
39 <StatusDot color={stats.pending === 0 ? "green" : "yellow"} />
40 {stats.pending}
41 </span>
42 }
43 />
44 <DetailRow label="Scheduled" value={stats.scheduled} />
45 <DetailRow label="Processing" value={stats.processing} />
46 <DetailRow
47 label="Oldest Pending"
48 value={
49 stats.oldestPendingSeconds != null
50 ? formatDuration(stats.oldestPendingSeconds)
51 : "none"
52 }
53 />
54 </div>
55 </Card>
56);