76 lines
2.6 KiB
TypeScript
76 lines
2.6 KiB
TypeScript
import { format, isPast } from 'date-fns';
|
|
import { Calendar, CheckCircle2 } from 'lucide-react';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
interface DashboardTodo {
|
|
id: number;
|
|
title: string;
|
|
due_date: string;
|
|
priority: string;
|
|
category?: string;
|
|
}
|
|
|
|
interface TodoWidgetProps {
|
|
todos: DashboardTodo[];
|
|
}
|
|
|
|
const priorityColors: Record<string, string> = {
|
|
low: 'bg-green-500/10 text-green-500 border-green-500/20',
|
|
medium: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/20',
|
|
high: 'bg-red-500/10 text-red-500 border-red-500/20',
|
|
};
|
|
|
|
export default function TodoWidget({ todos }: TodoWidgetProps) {
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-5 w-5" />
|
|
Upcoming Todos
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{todos.length === 0 ? (
|
|
<p className="text-sm text-muted-foreground text-center py-8">
|
|
No upcoming todos. You're all caught up!
|
|
</p>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{todos.slice(0, 5).map((todo) => {
|
|
const isOverdue = isPast(new Date(todo.due_date));
|
|
return (
|
|
<div
|
|
key={todo.id}
|
|
className="flex items-center gap-3 p-3 rounded-lg border bg-card hover:bg-accent/5 transition-colors"
|
|
>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="font-medium">{todo.title}</p>
|
|
<div className="flex items-center gap-2 mt-1">
|
|
<div className={cn(
|
|
"flex items-center gap-1 text-xs",
|
|
isOverdue ? "text-destructive" : "text-muted-foreground"
|
|
)}>
|
|
<Calendar className="h-3 w-3" />
|
|
{format(new Date(todo.due_date), 'MMM d, yyyy')}
|
|
{isOverdue && <span className="font-medium">(Overdue)</span>}
|
|
</div>
|
|
{todo.category && (
|
|
<Badge variant="outline" className="text-xs">{todo.category}</Badge>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<Badge className={priorityColors[todo.priority] || priorityColors.medium}>
|
|
{todo.priority}
|
|
</Badge>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|