'use client'; import { Anchor, Bell, Calendar, CheckCircle2, Clock, FileText, MoreHorizontal, User, XCircle, } from 'lucide-react'; import { format } from 'date-fns'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { ListCard, ListCardAvatar, ListCardMeta } from '@/components/shared/list-card'; import { cn } from '@/lib/utils'; interface Reminder { id: string; title: string; note: string | null; dueAt: string; priority: 'low' | 'medium' | 'high' | 'urgent'; status: 'pending' | 'snoozed' | 'completed' | 'dismissed'; assignedTo: string | null; createdBy: string; clientId: string | null; interestId: string | null; berthId: string | null; autoGenerated: boolean; snoozedUntil: string | null; completedAt: string | null; createdAt: string; client?: { id: string; fullName: string } | null; interest?: { id: string; pipelineStage: string } | null; berth?: { id: string; mooringNumber: string } | null; } const STATUS_CONFIG = { pending: { label: 'Pending', icon: Bell }, snoozed: { label: 'Snoozed', icon: Clock }, completed: { label: 'Completed', icon: CheckCircle2 }, dismissed: { label: 'Dismissed', icon: XCircle }, } as const; const STATUS_PILL: Record = { pending: 'bg-amber-100 text-amber-700', snoozed: 'bg-slate-100 text-slate-700', completed: 'bg-emerald-100 text-emerald-700', dismissed: 'bg-emerald-100 text-emerald-700', }; const PRIORITY_CONFIG = { urgent: { label: 'Urgent', className: 'bg-red-600 text-white' }, high: { label: 'High', className: 'bg-orange-500 text-white' }, medium: { label: 'Medium', className: 'bg-blue-500 text-white' }, low: { label: 'Low', className: 'bg-gray-400 text-white' }, } as const; function accentForReminder(status: string, isPastDue: boolean): string { if (isPastDue) return 'bg-rose-400'; if (status === 'pending') return 'bg-amber-400'; if (status === 'snoozed') return 'bg-slate-400'; if (status === 'completed' || status === 'dismissed') return 'bg-emerald-400'; return 'bg-slate-300'; } interface ReminderCardProps { reminder: Reminder; portSlug: string; onComplete: (id: string) => void; onSnooze: (id: string) => void; onDismiss: (id: string) => void; onEdit: (reminder: Reminder) => void; } export function ReminderCard({ reminder, portSlug: _portSlug, onComplete, onSnooze, onDismiss, onEdit, }: ReminderCardProps) { const isPastDue = (reminder.status === 'pending' || reminder.status === 'snoozed') && new Date(reminder.dueAt) < new Date(); const accentClass = accentForReminder(reminder.status, isPastDue); const statusConfig = STATUS_CONFIG[reminder.status]; const StatusIcon = statusConfig.icon; const statusPill = STATUS_PILL[reminder.status] ?? 'bg-slate-100 text-slate-700'; const priorityConfig = PRIORITY_CONFIG[reminder.priority]; const isResolved = reminder.status === 'completed' || reminder.status === 'dismissed'; // Subtitle: related-entity context let subtitleIcon: React.ReactNode = null; let subtitleText: string | null = null; if (reminder.client) { subtitleIcon = ; subtitleText = reminder.client.fullName; } else if (reminder.berth) { subtitleIcon = ; subtitleText = `Berth ${reminder.berth.mooringNumber}`; } else if (reminder.interest) { subtitleIcon = ( ); subtitleText = `Interest (${reminder.interest.pipelineStage})`; } const hasActions = !isResolved; return ( { e.preventDefault(); onComplete(reminder.id); }} > Complete { e.preventDefault(); onSnooze(reminder.id); }} > Snooze { e.preventDefault(); onEdit(reminder); }} > Edit { e.preventDefault(); onDismiss(reminder.id); }} > Dismiss ) : undefined } >
} />
{/* Title row + spacer for actions button */}

{reminder.title}

{hasActions ? : null}
{/* Related entity subtitle */} {subtitleText ? (

{subtitleIcon} {subtitleText}

) : null} {/* Due date meta line */}
} > Due {format(new Date(reminder.dueAt), 'MMM d, yyyy')}
{/* Pills row: status + priority + past-due flag */}
{/* Status pill */} {statusConfig.label} {/* Priority pill */} {priorityConfig.label} {/* Past-due flag */} {isPastDue ? ( Past due ) : null}
); }