forked from op7418/CodePilot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGitHistorySection.tsx
More file actions
86 lines (75 loc) · 2.7 KB
/
GitHistorySection.tsx
File metadata and controls
86 lines (75 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"use client";
import { useState, useEffect, useCallback } from "react";
import { useTranslation } from "@/hooks/useTranslation";
import type { GitLogEntry } from "@/types";
interface GitHistorySectionProps {
cwd: string;
onSelectCommit: (sha: string) => void;
}
export function GitHistorySection({ cwd, onSelectCommit }: GitHistorySectionProps) {
const { t } = useTranslation();
const [entries, setEntries] = useState<GitLogEntry[]>([]);
const [loading, setLoading] = useState(false);
const fetchHistory = useCallback(async () => {
if (!cwd) return;
setLoading(true);
try {
const res = await fetch(`/api/git/log?cwd=${encodeURIComponent(cwd)}&limit=30`);
const data = await res.json();
setEntries(data.entries || []);
} catch {
// ignore
} finally {
setLoading(false);
}
}, [cwd]);
useEffect(() => {
void fetchHistory();
}, [fetchHistory]);
// Refresh on git-refresh events (commit, checkout, etc.)
useEffect(() => {
const handler = () => void fetchHistory();
window.addEventListener('git-refresh', handler);
return () => window.removeEventListener('git-refresh', handler);
}, [fetchHistory]);
if (loading) {
return <div className="px-3 py-2 text-[11px] text-muted-foreground">{t('git.loading')}</div>;
}
if (entries.length === 0) {
return <div className="px-3 py-2 text-[11px] text-muted-foreground">{t('git.noChanges')}</div>;
}
return (
<div className="max-h-[300px] overflow-y-auto">
{entries.map(entry => (
<button
key={entry.sha}
className="flex items-start gap-2 w-full px-3 py-1.5 text-left hover:bg-muted/50"
onClick={() => onSelectCommit(entry.sha)}
>
<span className="shrink-0 text-[10px] font-mono text-muted-foreground mt-0.5">
{entry.sha.substring(0, 7)}
</span>
<div className="min-w-0 flex-1">
<p className="text-[12px] truncate text-foreground/80">{entry.message}</p>
<p className="text-[10px] text-muted-foreground">
{entry.authorName} · {formatRelativeTime(entry.timestamp)}
</p>
</div>
</button>
))}
</div>
);
}
function formatRelativeTime(timestamp: string): string {
const date = new Date(timestamp);
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffMin = Math.floor(diffMs / 60000);
const diffHour = Math.floor(diffMs / 3600000);
const diffDay = Math.floor(diffMs / 86400000);
if (diffMin < 1) return 'just now';
if (diffMin < 60) return `${diffMin}m ago`;
if (diffHour < 24) return `${diffHour}h ago`;
if (diffDay < 30) return `${diffDay}d ago`;
return date.toLocaleDateString();
}