feat(kanban): deadlines en cards (context menu, badges, calendario, history)

- migration 009 + columna deadline TEXT en cards
- backend: CardPatch.HasDeadline, eventos deadline_set/deadline_cleared
- KanbanCard: menu derecho con DatePicker, badge countdown con colores por ratio (azul>=50%, amarillo<50%, rojo<10%, red.9 overdue)
- App.tsx: filtro "Con deadline", handleSetCardDeadline optimista, jump-to-card + highlight
- CalendarView: popover por dia con seq_num + titulo, click navega a card en tablero
- HistoryModal: render eventos deadline_set/deadline_cleared
- .gitignore: *.log

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 03:45:36 +02:00
parent 5ba0254e57
commit 7ce227ddea
54 changed files with 3066 additions and 496 deletions
+15
View File
@@ -54,6 +54,10 @@ interface Props {
onShowHistory: (card: Card) => void;
onToggleCardLock: (id: string, locked: boolean) => void;
onAssignCard: (id: string, assignee_id: string | null) => void;
onSetCardDeadline?: (id: string, deadline: string | null) => void;
onSetRequester?: (id: string, requester: string) => void;
requesterOptions?: string[];
onOpenCustomCardColor?: (cardId: string, current: string) => void;
activeSticker?: string | null;
onAddSticker?: (cardId: string, x: number, y: number) => void;
onRemoveSticker?: (cardId: string, index: number) => void;
@@ -61,6 +65,7 @@ interface Props {
onCommitSticker?: (cardId: string) => void;
users: User[];
usersById: Map<string, User>;
highlightCardId?: string | null;
}
function KanbanColumnImpl({
@@ -81,6 +86,10 @@ function KanbanColumnImpl({
onShowHistory,
onToggleCardLock,
onAssignCard,
onSetCardDeadline,
onSetRequester,
requesterOptions,
onOpenCustomCardColor,
activeSticker,
onAddSticker,
onRemoveSticker,
@@ -88,6 +97,7 @@ function KanbanColumnImpl({
onCommitSticker,
users,
usersById,
highlightCardId,
}: Props) {
const [renaming, setRenaming] = useState(false);
const [name, setName] = useState(column.name);
@@ -415,9 +425,14 @@ function KanbanColumnImpl({
onShowHistory={onShowHistory}
onToggleLock={onToggleCardLock}
onAssign={onAssignCard}
onSetDeadline={onSetCardDeadline}
onSetRequester={onSetRequester}
requesterOptions={requesterOptions}
onOpenCustomColor={onOpenCustomCardColor}
users={users}
assignee={c.assignee_id ? usersById.get(c.assignee_id) : undefined}
inDoneColumn={column.is_done}
highlight={highlightCardId === c.id}
activeSticker={activeSticker}
onAddSticker={onAddSticker}
onRemoveSticker={onRemoveSticker}