"use client"; import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { RefreshCw, Folder } from "lucide-react"; import { Badge } from "@/components/ui/badge"; interface Task { id: number; headline: string; description: string; dateToFinish: string | null; projectId: number; projectName: string; status: number; editorId?: string; editorFirstname?: string; editorLastname?: string; authorFirstname: string; authorLastname: string; milestoneHeadline?: string; editTo?: string; editFrom?: string; } interface ProjectSummary { name: string; tasks: { status: number; count: number; }[]; } interface TaskWithDate extends Task { validDate?: Date; } export function Duties() { const [tasks, setTasks] = useState([]); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const getStatusLabel = (status: number): string => { switch (status) { case 1: return 'New'; case 2: return 'Ready'; case 3: return 'In Progress'; case 4: return 'Review'; case 5: return 'Done'; default: return 'Unknown'; } }; const getStatusColor = (status: number): string => { switch (status) { case 1: return 'bg-blue-500'; case 2: return 'bg-green-500'; case 3: return 'bg-yellow-500'; case 4: return 'bg-purple-500'; case 5: return 'bg-gray-500'; default: return 'bg-gray-300'; } }; const formatDate = (dateStr: string): string => { if (!dateStr || dateStr === '0000-00-00 00:00:00') return ''; try { const date = new Date(dateStr); if (isNaN(date.getTime())) return ''; return date.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric' }); } catch { return ''; } }; const getValidDate = (task: Task): string | null => { if (task.dateToFinish && task.dateToFinish !== '0000-00-00 00:00:00') { return task.dateToFinish; } return null; }; const fetchTasks = async () => { setLoading(true); setError(null); try { const response = await fetch('/api/leantime/tasks'); if (!response.ok) { throw new Error('Failed to fetch tasks'); } const data = await response.json(); console.log('Raw API response:', data); if (!Array.isArray(data)) { console.warn('No tasks found in response', data as unknown); setTasks([]); return; } // Filter out completed tasks (status 5) and sort by dateToFinish const sortedTasks = data .filter((task: Task) => { const isValid = task.status !== 5; console.log(`Task ${task.id}: status=${task.status}, dateToFinish=${task.dateToFinish}, isValid=${isValid}`); return isValid; }) .sort((a: Task, b: Task) => { // First sort by dateToFinish (oldest first) const dateA = getValidDate(a); const dateB = getValidDate(b); // If both dates are valid, compare them if (dateA && dateB) { const timeA = new Date(dateA).getTime(); const timeB = new Date(dateB).getTime(); if (timeA !== timeB) { return timeA - timeB; } } // If only one date is valid, put the task with a date first if (dateA) return -1; if (dateB) return 1; // If dates are equal or neither has a date, sort by status (4 before others) if (a.status === 4 && b.status !== 4) return -1; if (b.status === 4 && a.status !== 4) return 1; // If status is also equal, maintain original order return 0; }); console.log('Sorted tasks:', sortedTasks.map(t => ({ id: t.id, date: t.dateToFinish, status: t.status }))); setTasks(sortedTasks.slice(0, 7)); } catch (error) { console.error('Error fetching tasks:', error); setError(error instanceof Error ? error.message : 'Failed to fetch tasks'); } finally { setLoading(false); } }; useEffect(() => { fetchTasks(); }, []); // Update the TaskDate component to handle dates better const TaskDate = ({ task }: { task: TaskWithDate }) => { const dateStr = task.dateToFinish; if (!dateStr || dateStr === '0000-00-00 00:00:00') { return (
NO DATE
); } try { const date = new Date(dateStr); if (isNaN(date.getTime())) { throw new Error('Invalid date'); } const today = new Date(); today.setHours(0, 0, 0, 0); const isPastDue = date < today; const month = date.toLocaleString('fr-FR', { month: 'short' }).toUpperCase(); const day = date.getDate(); const year = date.getFullYear(); return (
{month} {day}
{year}
); } catch (error) { console.error('Error formatting date for task', task.id, error); return (
ERR DATE
); } }; return ( Duties {loading ? (
) : error ? (
{error}
) : tasks.length === 0 ? (
No tasks with due dates found
) : (
{tasks.map((task) => (
{task.headline}
{task.projectName}
))}
)} ); }