22
33import { useEffect , useState , useCallback } from "react" ;
44import { Badge } from "@/components/ui/badge" ;
5- import { Lightbulb , FileVideo , Handshake , Clock } from "lucide-react" ;
6-
7- interface ActivityItem {
8- _id : string ;
9- _type : string ;
10- _updatedAt : string ;
11- title ?: string ;
12- companyName ?: string ;
13- status ?: string ;
14- }
5+ import { Lightbulb , FileVideo , Handshake , Clock , Loader2 } from "lucide-react" ;
6+ import { POLL_INTERVAL_MS , type ActivityItem } from "@/lib/types/dashboard" ;
157
168const typeConfig : Record <
179 string ,
@@ -20,20 +12,17 @@ const typeConfig: Record<
2012 contentIdea : {
2113 icon : Lightbulb ,
2214 label : "Idea" ,
23- color :
24- "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300" ,
15+ color : "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300" ,
2516 } ,
2617 automatedVideo : {
2718 icon : FileVideo ,
2819 label : "Video" ,
29- color :
30- "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300" ,
20+ color : "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300" ,
3121 } ,
3222 sponsorLead : {
3323 icon : Handshake ,
3424 label : "Sponsor" ,
35- color :
36- "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300" ,
25+ color : "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300" ,
3726 } ,
3827} ;
3928
@@ -49,6 +38,7 @@ function formatTimeAgo(dateString: string) {
4938
5039export function RecentActivity ( ) {
5140 const [ items , setItems ] = useState < ActivityItem [ ] > ( [ ] ) ;
41+ const [ isLoading , setIsLoading ] = useState ( true ) ;
5242
5343 const fetchActivity = useCallback ( async ( ) => {
5444 try {
@@ -59,52 +49,45 @@ export function RecentActivity() {
5949 }
6050 } catch ( error ) {
6151 console . error ( "Failed to fetch activity:" , error ) ;
52+ } finally {
53+ setIsLoading ( false ) ;
6254 }
6355 } , [ ] ) ;
6456
6557 useEffect ( ( ) => {
6658 fetchActivity ( ) ;
67- const interval = setInterval ( fetchActivity , 30000 ) ;
59+ const interval = setInterval ( fetchActivity , POLL_INTERVAL_MS ) ;
6860 return ( ) => clearInterval ( interval ) ;
6961 } , [ fetchActivity ] ) ;
7062
7163 return (
7264 < div className = "rounded-lg border p-6" >
7365 < h2 className = "text-lg font-semibold" > Recent Activity</ h2 >
74- { items . length === 0 ? (
66+ { isLoading ? (
67+ < div className = "mt-4 flex items-center justify-center py-8" >
68+ < Loader2 className = "h-6 w-6 animate-spin text-muted-foreground" />
69+ </ div >
70+ ) : items . length === 0 ? (
7571 < p className = "mt-4 text-sm text-muted-foreground" >
76- No activity yet \u2014 content will appear here as the pipeline
77- runs.
72+ No activity yet \u2014 content will appear here as the pipeline runs.
7873 </ p >
7974 ) : (
8075 < div className = "mt-4 space-y-3" >
8176 { items . map ( ( item ) => {
82- const config =
83- typeConfig [ item . _type ] ?? typeConfig . contentIdea ;
77+ const config = typeConfig [ item . _type ] ?? typeConfig . contentIdea ;
8478 const Icon = config . icon ;
85- const name =
86- item . title || item . companyName || "Untitled" ;
79+ const name = item . title || item . companyName || "Untitled" ;
8780 return (
88- < div
89- key = { item . _id }
90- className = "flex items-center gap-3"
91- >
81+ < div key = { item . _id } className = "flex items-center gap-3" >
9282 < Icon className = "h-4 w-4 shrink-0 text-muted-foreground" />
9383 < div className = "min-w-0 flex-1" >
94- < p className = "truncate text-sm font-medium" >
95- { name }
96- </ p >
84+ < p className = "truncate text-sm font-medium" > { name } </ p >
9785 < div className = "flex items-center gap-2" >
98- < Badge
99- variant = "outline"
100- className = { `text-xs ${ config . color } ` }
101- >
86+ < Badge variant = "outline" className = { `text-xs ${ config . color } ` } >
10287 { config . label }
10388 </ Badge >
10489 { item . status && (
105- < span className = "text-xs text-muted-foreground" >
106- { item . status }
107- </ span >
90+ < span className = "text-xs text-muted-foreground" > { item . status } </ span >
10891 ) }
10992 </ div >
11093 </ div >
0 commit comments