- Calendar: move view selector left, inline EventDetailPanel with view/edit/create modes, fix resize on panel close, remove all Sheet/Dialog usage - Todos: add TodoDetailPanel with inline view/edit/create, replace CategoryFilterBar with shared component (drag-and-drop categories), 55/45 split layout - Reminders: add ReminderDetailPanel with inline view/edit/create, 55/45 split layout - Dashboard: all widget items now deep-link to destination page AND open the relevant item's detail panel (events, todos, reminders) - Fix TS errors: unused imports, undefined→null coalescing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
42 lines
1.6 KiB
TypeScript
42 lines
1.6 KiB
TypeScript
import { differenceInCalendarDays, format } from 'date-fns';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { Star } from 'lucide-react';
|
|
|
|
interface CountdownWidgetProps {
|
|
events: Array<{
|
|
id: number;
|
|
title: string;
|
|
start_datetime: string;
|
|
}>;
|
|
}
|
|
|
|
export default function CountdownWidget({ events }: CountdownWidgetProps) {
|
|
const navigate = useNavigate();
|
|
const visible = events.filter((e) => differenceInCalendarDays(new Date(e.start_datetime), new Date()) >= 0);
|
|
if (visible.length === 0) return null;
|
|
|
|
return (
|
|
<div className="rounded-lg bg-amber-500/[0.07] border border-amber-500/10 px-3.5 py-2 space-y-1">
|
|
{visible.map((event) => {
|
|
const days = differenceInCalendarDays(new Date(event.start_datetime), new Date());
|
|
const label = days === 0 ? 'Today' : days === 1 ? '1 day' : `${days} days`;
|
|
const dateStr = format(new Date(event.start_datetime), 'yyyy-MM-dd');
|
|
return (
|
|
<div
|
|
key={event.id}
|
|
onClick={() => navigate('/calendar', { state: { date: dateStr, view: 'timeGridDay', eventId: event.id } })}
|
|
className="flex items-center gap-2 cursor-pointer hover:bg-amber-500/10 rounded px-1 -mx-1 transition-colors duration-150"
|
|
>
|
|
<Star className="h-3 w-3 text-amber-400 fill-amber-400 shrink-0" />
|
|
<span className="text-sm text-amber-200/90 truncate">
|
|
<span className="font-semibold tabular-nums">{label}</span>
|
|
{days > 0 ? ' until ' : ' — '}
|
|
<span className="font-medium text-foreground">{event.title}</span>
|
|
</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|