"use client"; import { useState } from "react"; import { toast } from "sonner"; import { useSortable } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { Card, CardContent, CardTitle, CardDescription, CardHeader, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, } from "@/components/ui/dropdown-menu"; import { TodoForm } from "@/components/todo-form"; import { Icons } from "@/components/icons"; import { cn } from "@/lib/utils"; import type { Todo, Tag } from "@/services/api-types"; import Image from "next/image"; interface TodoCardProps { todo: Todo; tags: Tag[]; onUpdate: (todo: Partial) => void; onDelete: () => void; isDraggable?: boolean; } export function TodoCard({ todo, tags, onUpdate, onDelete, isDraggable = false, }: TodoCardProps) { const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); const [isViewDialogOpen, setIsViewDialogOpen] = useState(false); // Drag and drop logic const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: todo.id, disabled: !isDraggable, }); const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1, }; // Style helpers const getStatusColor = (status: string) => { switch (status) { case "pending": return "border-l-4 border-l-amber-500"; case "in-progress": return "border-l-4 border-l-sky-500"; case "completed": return "border-l-4 border-l-emerald-500"; default: return "border-l-4 border-l-slate-400"; } }; const getStatusIcon = (status: string) => { switch (status) { case "pending": return ; case "in-progress": return ; case "completed": return ; default: return ; } }; const todoTags = tags.filter((tag) => todo.tagIds.includes(tag.id)); const hasImage = !!todo.image; const hasAttachments = todo.attachments && todo.attachments.length > 0; const hasSubtasks = todo.subtasks && todo.subtasks.length > 0; const completedSubtasks = todo.subtasks ? todo.subtasks.filter((subtask) => subtask.completed).length : 0; const handleStatusToggle = () => { const newStatus = todo.status === "completed" ? "pending" : "completed"; onUpdate({ status: newStatus }); }; const formatDate = (dateString?: string | null) => { if (!dateString) return ""; const date = new Date(dateString); return date.toLocaleDateString(); }; return ( <> {/* Left icon, like notification card */}
{getStatusIcon(todo.status)}
{/* Main content */}
{todo.title} {!isDraggable && ( setIsViewDialogOpen(true)} > View details setIsEditDialogOpen(true)} > Edit Delete )}
{/* Actions and deadline on a new line */}
{todo.deadline && ( {formatDate(todo.deadline)} )}
{todo.description} {/* Tags and indicators */}
{todoTags.map((tag) => ( {tag.name} ))} {hasSubtasks && ( {completedSubtasks}/{todo.subtasks.length} )} {hasAttachments && ( {todo.attachments.length} )} {hasImage && ( )}
{/* Bottom row: created date and status toggle */}
{todo.createdAt ? formatDate(todo.createdAt) : ""}
{/* Edit Dialog */} Edit Todo Make changes to your task and save when you're done { onUpdate(updatedTodo); setIsEditDialogOpen(false); toast.success("Todo updated successfully"); }} /> {/* View Dialog */}
{todo.status.replace("-", " ")} {todo.deadline && ( {formatDate(todo.deadline)} )}
{todo.title} Created {formatDate(todo.createdAt)} {hasImage && (
{todo.title}
)}
{todo.description && (
{todo.description}
)} {todoTags.length > 0 && (

Tags

{todoTags.map((tag) => ( {tag.name} ))}
)} {hasAttachments && (

Attachments

{todo.attachments.map((a, i) => (
{a}
))}
)} {hasSubtasks && (

Subtasks ({completedSubtasks}/{todo.subtasks.length})

    {todo.subtasks.map((subtask) => (
  • {subtask.completed && ( )}
    {subtask.description}
  • ))}
)}
); }