Erik Sarriegui
first push
588462f
import { useState, useEffect } from 'react';
import axios from 'axios';
import { Calendar, RefreshCw } from 'lucide-react';
import ClusterCard from './ClusterCard';
import { cn } from '../lib/utils';
import { motion } from 'framer-motion';
export default function Aggregator() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [selectedDayIndex, setSelectedDayIndex] = useState(0);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
try {
setLoading(true);
setError(null);
const response = await axios.get('/api/clusters');
// Sort daysdescending just in case or keep as valid from API
// API returns top 3 days. We'll use them as is.
setData(response.data);
} catch (err) {
console.error(err);
setError("Failed to load clusters. Please try again.");
} finally {
setLoading(false);
}
};
if (loading) {
return (
<div className="flex flex-col items-center justify-center py-20 text-slate-500">
<RefreshCw className="w-8 h-8 animate-spin mb-4 text-blue-500" />
<p>Loading intelligence stream...</p>
</div>
);
}
if (error) {
return (
<div className="text-center py-20 text-red-400 bg-red-900/10 rounded-xl border border-red-900/20">
<p className="mb-4">{error}</p>
<button
onClick={fetchData}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-500 transition-colors"
>
Retry
</button>
</div>
);
}
if (!data || data.length === 0) {
return <div className="text-center py-20 text-slate-500">No data available.</div>;
}
const currentDay = data[selectedDayIndex];
return (
<div className="space-y-6">
{/* Day Tabs */}
<div className="flex justify-center gap-4">
{data.map((dayItem, index) => (
<button
key={dayItem.date}
onClick={() => setSelectedDayIndex(index)}
className={cn(
"flex flex-col items-center p-3 rounded-xl border transition-all duration-300 w-32",
selectedDayIndex === index
? "bg-slate-800 border-blue-500/50 shadow-lg shadow-blue-500/10 text-white"
: "bg-slate-900/50 border-slate-800 text-slate-400 hover:bg-slate-800 hover:border-slate-700"
)}
>
<span className="text-xs font-medium uppercase tracking-wider text-slate-500 mb-1">
{new Date(dayItem.date).toLocaleDateString(undefined, { weekday: 'short' })}
</span>
<span className="text-lg font-bold">
{new Date(dayItem.date).toLocaleDateString(undefined, { day: '2-digit', month: 'short' })}
</span>
</button>
))}
</div>
{/* Stats for the day */}
<div className="flex items-center justify-between px-4 pb-2 text-slate-400 text-sm border-b border-slate-800">
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4" />
<span>Events for {new Date(currentDay.date).toLocaleDateString()}</span>
</div>
<div>
{currentDay.clusters.length} Event Clusters
</div>
</div>
{/* Clusters Grid */}
<div className="grid grid-cols-1 md:grid-cols-1 gap-4">
{currentDay.clusters.map((cluster) => (
<ClusterCard key={cluster.cluster_id} cluster={cluster} />
))}
</div>
</div>
);
}