feat(kanban): Seleccionar Aleatorio en columna con ruleta (issue 0090)
Adds a column-level "Seleccionar Aleatorio" context menu entry that picks a card at random from the column with a roulette-style highlight animation that decelerates to the winner. Selection respects existing filters (uses cardsByColumn which is the post-filter view) and always excludes locked cards. Menu entry is disabled when nothing pickable is left. Implementation: - KanbanColumn: new Menu.Item with IconDice5; data-test selector for e2e. - onPickRandom prop wired from KanbanColumn -> App. - handlePickRandom in App.tsx: cryptographically random winner via crypto.getRandomValues, 2 full laps + offset, cubic decay 50ms -> 220ms, follows the active card with scrollIntoView. - src/styles/roulette.css: .kanban-roulette-active (blue pulse, single step) and .kanban-roulette-winner (green pulse + scale, ~1.6s). Imported globally from main.tsx. Manual verification only (visual timing + needs real cards). Backend untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ import {
|
||||
IconChevronDown,
|
||||
IconChevronRight,
|
||||
IconClock,
|
||||
IconDice5,
|
||||
IconDotsVertical,
|
||||
IconGripVertical,
|
||||
IconPencil,
|
||||
@@ -49,6 +50,7 @@ interface Props {
|
||||
onDeleteColumn: (id: string) => void;
|
||||
onSetWIPLimit: (id: string, limit: number) => void;
|
||||
onSetMaxTimeMinutes: (id: string, minutes: number) => void;
|
||||
onPickRandom: (columnId: string) => void;
|
||||
onToggleDone: (id: string, is_done: boolean) => void;
|
||||
onEditCard: (card: Card) => void;
|
||||
onDeleteCard: (id: string) => void;
|
||||
@@ -83,6 +85,7 @@ function KanbanColumnImpl({
|
||||
onDeleteColumn,
|
||||
onSetWIPLimit,
|
||||
onSetMaxTimeMinutes,
|
||||
onPickRandom,
|
||||
onToggleDone,
|
||||
onEditCard,
|
||||
onDeleteCard,
|
||||
@@ -411,6 +414,14 @@ function KanbanColumnImpl({
|
||||
Tiempo maximo
|
||||
{column.max_time_minutes > 0 ? ` (${column.max_time_minutes} min)` : ""}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
leftSection={<IconDice5 size={14} />}
|
||||
data-test="column-random-pick"
|
||||
disabled={cards.filter((c) => !c.locked).length === 0}
|
||||
onClick={() => onPickRandom(column.id)}
|
||||
>
|
||||
Seleccionar Aleatorio
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
leftSection={<ArchiveIcon size={14} />}
|
||||
onClick={() => onMoveColumnLocation(column.id, isInSidebar ? "board" : "sidebar")}
|
||||
|
||||
Reference in New Issue
Block a user