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+ }
0 commit comments