"use client"; import { useEffect, useState, useCallback } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { RefreshCw, ChevronDown, Filter } from "lucide-react"; import { useRouter } from "next/navigation"; import { useSession } from "next-auth/react"; interface Task { id: string; headline: string; projectName: string; dueDate: string; status: string; details?: string; } interface TaskGroup { name: string; count: number; tasks: Task[]; } export function Flow() { const [taskGroups, setTaskGroups] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [refreshing, setRefreshing] = useState(false); const [retryTimeout, setRetryTimeout] = useState(null); const router = useRouter(); const { data: session } = useSession(); const fetchTasks = useCallback(async (isRefresh = false, retryCount = 0) => { try { if (isRefresh) { setRefreshing(true); } if (retryTimeout) { clearTimeout(retryTimeout); setRetryTimeout(null); } const response = await fetch('/api/leantime/tasks', { cache: 'no-store', next: { revalidate: 0 }, }); if (response.status === 401) { setError('Session expired. Please sign in again.'); return; } if (response.status === 429) { const retryAfter = response.headers.get('Retry-After'); const waitTime = retryAfter ? parseInt(retryAfter, 10) * 1000 : Math.min(1000 * Math.pow(2, retryCount), 60000); setError(`Rate limit exceeded. Retrying in ${Math.round(waitTime / 1000)} seconds...`); const timeout = setTimeout(() => { fetchTasks(isRefresh, retryCount + 1); }, waitTime); setRetryTimeout(timeout); return; } if (!response.ok) { throw new Error('Failed to fetch tasks'); } const data = await response.json(); // Group tasks by status const groups: { [key: string]: Task[] } = {}; data.tasks.forEach((task: Task) => { const status = task.status || 'No Status'; if (!groups[status]) { groups[status] = []; } groups[status].push(task); }); // Convert to array format with counts const formattedGroups = Object.entries(groups).map(([name, tasks]) => ({ name, count: tasks.length, tasks })); setTaskGroups(formattedGroups); setError(null); } catch (err) { console.error('Error fetching tasks:', err); setError(err instanceof Error ? err.message : 'Failed to fetch tasks'); } finally { setLoading(false); setRefreshing(false); } }, [retryTimeout]); useEffect(() => { if (session) { fetchTasks(); const interval = setInterval(() => fetchTasks(), 300000); return () => { clearInterval(interval); if (retryTimeout) { clearTimeout(retryTimeout); } }; } }, [session, fetchTasks, retryTimeout]); return ( router.push('/flow')} > 📋 My ToDos
{loading &&

Loading tasks...

} {error && (

Error: {error}

{!retryTimeout && ( )}
)} {!loading && !error && (
{taskGroups.length === 0 ? (

No tasks found

) : ( taskGroups.map((group) => (
{group.name === 'overdue' && 🔥}

{group.name.charAt(0).toUpperCase() + group.name.slice(1)} ({group.count})

{group.tasks.map((task) => (
{group.name === 'overdue' && (
)}
{task.projectName}
{task.headline} {task.details && ( // {task.details} )}
🗓️ {new Date(task.dueDate).toLocaleDateString()}
))}
)) )}
)} ); }