From 624be051c176e0b44e7628a4336cbc765d872672 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 15 Feb 2026 18:49:20 +0200 Subject: [PATCH] feat: add card thumbnails with label dots, due dates, and checklist progress bar --- src/components/board/CardThumbnail.tsx | 57 ++++++++++++++++++++++++++ src/components/board/ChecklistBar.tsx | 22 ++++++++++ src/components/board/LabelDots.tsx | 37 +++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 src/components/board/CardThumbnail.tsx create mode 100644 src/components/board/ChecklistBar.tsx create mode 100644 src/components/board/LabelDots.tsx diff --git a/src/components/board/CardThumbnail.tsx b/src/components/board/CardThumbnail.tsx new file mode 100644 index 0000000..d5e66b2 --- /dev/null +++ b/src/components/board/CardThumbnail.tsx @@ -0,0 +1,57 @@ +import { format, isPast, isToday } from "date-fns"; +import type { Card, Label } from "@/types/board"; +import { LabelDots } from "@/components/board/LabelDots"; +import { ChecklistBar } from "@/components/board/ChecklistBar"; + +interface CardThumbnailProps { + card: Card; + boardLabels: Label[]; +} + +export function CardThumbnail({ card, boardLabels }: CardThumbnailProps) { + const hasDueDate = card.dueDate != null; + const dueDate = hasDueDate ? new Date(card.dueDate!) : null; + const overdue = dueDate != null && isPast(dueDate) && !isToday(dueDate); + + function handleClick() { + // Card detail modal will be wired in Task 11 + console.log("Card clicked:", card.id); + } + + return ( + + ); +} diff --git a/src/components/board/ChecklistBar.tsx b/src/components/board/ChecklistBar.tsx new file mode 100644 index 0000000..bdeb045 --- /dev/null +++ b/src/components/board/ChecklistBar.tsx @@ -0,0 +1,22 @@ +import type { ChecklistItem } from "@/types/board"; + +interface ChecklistBarProps { + checklist: ChecklistItem[]; +} + +export function ChecklistBar({ checklist }: ChecklistBarProps) { + if (checklist.length === 0) return null; + + return ( +
+ {checklist.map((item) => ( + + ))} +
+ ); +} diff --git a/src/components/board/LabelDots.tsx b/src/components/board/LabelDots.tsx new file mode 100644 index 0000000..6c76b25 --- /dev/null +++ b/src/components/board/LabelDots.tsx @@ -0,0 +1,37 @@ +import { + Tooltip, + TooltipTrigger, + TooltipContent, +} from "@/components/ui/tooltip"; +import type { Label } from "@/types/board"; + +interface LabelDotsProps { + labelIds: string[]; + boardLabels: Label[]; +} + +export function LabelDots({ labelIds, boardLabels }: LabelDotsProps) { + if (labelIds.length === 0) return null; + + const labels = labelIds + .map((id) => boardLabels.find((l) => l.id === id)) + .filter((l): l is Label => l != null); + + if (labels.length === 0) return null; + + return ( +
+ {labels.map((label) => ( + + + + + {label.name} + + ))} +
+ ); +}