Skip to content

Commit f7c551c

Browse files
feat: added live GitHub activity feed with UI and time tracking
1 parent 56e17a3 commit f7c551c

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

src/components/ActivityFeed.tsx

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { useEffect, useState } from "react";
2+
3+
interface EventType {
4+
id: string;
5+
type: string;
6+
created_at: string;
7+
repo?: {
8+
name: string;
9+
};
10+
}
11+
12+
export default function ActivityFeed({ username }: { username: string }) {
13+
const [events, setEvents] = useState<EventType[]>([]);
14+
const [loading, setLoading] = useState(true);
15+
16+
// 🕒 time ago function
17+
const getTimeAgo = (dateString: string) => {
18+
const diff = Math.floor(
19+
(Date.now() - new Date(dateString).getTime()) / 1000
20+
);
21+
22+
if (diff < 60) return `${diff}s ago`;
23+
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
24+
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
25+
return `${Math.floor(diff / 86400)}d ago`;
26+
};
27+
28+
useEffect(() => {
29+
const fetchEvents = async () => {
30+
try {
31+
setLoading(true);
32+
33+
const res = await fetch(
34+
`https://api.github.com/users/${username}/events`
35+
);
36+
const data = await res.json();
37+
38+
setEvents(data);
39+
setLoading(false);
40+
} catch (err) {
41+
console.error(err);
42+
setLoading(false);
43+
}
44+
};
45+
46+
fetchEvents();
47+
48+
const interval = setInterval(fetchEvents, 30000);
49+
return () => clearInterval(interval);
50+
}, [username]);
51+
52+
return (
53+
<div className="p-4">
54+
<h2 className="text-xl font-bold mb-4 text-center">
55+
Activity Feed
56+
</h2>
57+
58+
{loading ? (
59+
<p className="text-center">Loading...</p>
60+
) : events.length === 0 ? (
61+
<p className="text-center">No activity found</p>
62+
) : (
63+
events.slice(0, 10).map((event) => (
64+
<div
65+
key={event.id}
66+
className="border rounded-lg p-3 mb-3 shadow-sm bg-white dark:bg-gray-700"
67+
>
68+
<p className="text-sm font-semibold">
69+
{event.type === "PushEvent" && "🚀 Commit pushed"}
70+
{event.type === "PullRequestEvent" && "🔀 Pull Request"}
71+
{event.type === "IssuesEvent" && "🐛 Issue"}
72+
{event.type === "WatchEvent" && "⭐ Starred repo"}
73+
{![
74+
"PushEvent",
75+
"PullRequestEvent",
76+
"IssuesEvent",
77+
"WatchEvent",
78+
].includes(event.type) && event.type}
79+
</p>
80+
81+
<p className="text-xs text-gray-500 mt-1">
82+
{event.repo?.name}{getTimeAgo(event.created_at)}
83+
</p>
84+
</div>
85+
))
86+
)}
87+
</div>
88+
);
89+
}

src/pages/ctivity.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import ActivityFeed from "../components/ActivityFeed";
2+
export default function Activity() {
3+
return (
4+
<div className="w-full h-full p-6 bg-gray-50 dark:bg-gray-800">
5+
<div className="max-w-2xl mx-auto">
6+
<h1 className="text-2xl font-bold mb-4 text-center">
7+
Live GitHub Activity
8+
</h1>
9+
10+
<ActivityFeed username="aparna24bce11388" />
11+
</div>
12+
</div>
13+
);
14+
}

0 commit comments

Comments
 (0)