Add right-click context menus for task and calendar interactions

Integrates context menus on the task card and calendar views, providing options to edit, start/stop timers, and change task status.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ceced2fc-aa46-458d-ba87-ddd4b7bb1518
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/659922a9-0087-461c-90dd-6d9a58b81d4d/ceced2fc-aa46-458d-ba87-ddd4b7bb1518/R3zkvYP
This commit is contained in:
paul-nothaft
2025-10-24 08:50:06 +00:00
parent 94bb2b599d
commit 037d3f4d73
3 changed files with 260 additions and 40 deletions
+115 -11
View File
@@ -9,6 +9,13 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu";
import { Clock, Calendar, Play, Pause, MoreHorizontal, Edit, Trash2, Timer, CheckCircle, X } from "lucide-react";
import { Task, Label } from '@shared/schema';
import { useQuery } from '@tanstack/react-query';
@@ -90,17 +97,19 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
};
return (
<Card
className={`p-4 hover-elevate active-elevate-2 transition-all duration-200 relative ${
isDragging ? 'rotate-1 scale-105 shadow-lg' : ''
} ${task.status === 'done' ? 'opacity-60' : ''}`}
style={taskLabel ? {
borderColor: taskLabel.color,
borderWidth: '2px',
borderStyle: 'solid'
} : {}}
data-testid={`card-task-${task.id}`}
>
<ContextMenu>
<ContextMenuTrigger asChild>
<Card
className={`p-4 hover-elevate active-elevate-2 transition-all duration-200 relative ${
isDragging ? 'rotate-1 scale-105 shadow-lg' : ''
} ${task.status === 'done' ? 'opacity-60' : ''}`}
style={taskLabel ? {
borderColor: taskLabel.color,
borderWidth: '2px',
borderStyle: 'solid'
} : {}}
data-testid={`card-task-${task.id}`}
>
<div className="flex items-start gap-3">
{/* Checkbox for quick completion */}
<Tooltip>
@@ -313,5 +322,100 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
</div>
</div>
</Card>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
onEdit?.();
}}
data-testid={`context-menu-edit-${task.id}`}
>
<Edit className="w-4 h-4 mr-2" />
{t('taskCard.editTask')}
</ContextMenuItem>
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
handleToggleTimer();
}}
data-testid={`context-menu-timer-${task.id}`}
>
<Timer className="w-4 h-4 mr-2" />
{task.isTracking ? t('taskCard.stopTimer') : t('taskCard.startTimer')}
</ContextMenuItem>
<ContextMenuSeparator />
{task.status !== 'done' && (
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
onStatusChange?.('done');
}}
data-testid={`context-menu-complete-${task.id}`}
>
<CheckCircle className="w-4 h-4 mr-2" />
{t('taskCard.markAsDone')}
</ContextMenuItem>
)}
{task.status === 'todo' && (
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
onStatusChange?.('inProgress');
}}
data-testid={`context-menu-start-${task.id}`}
>
<Play className="w-4 h-4 mr-2" />
{t('taskCard.startWorking')}
</ContextMenuItem>
)}
{task.status === 'inProgress' && (
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
onStatusChange?.('todo');
}}
data-testid={`context-menu-todo-${task.id}`}
>
<Clock className="w-4 h-4 mr-2" />
{t('taskCard.moveToTodo')}
</ContextMenuItem>
)}
{task.status === 'done' && (
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
onStatusChange?.('inProgress');
}}
data-testid={`context-menu-reopen-${task.id}`}
>
<Play className="w-4 h-4 mr-2" />
{t('taskCard.reopenTask')}
</ContextMenuItem>
)}
<ContextMenuSeparator />
{onDelete && (
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
className="text-destructive"
data-testid={`context-menu-delete-${task.id}`}
>
<Trash2 className="w-4 h-4 mr-2" />
{t('taskCard.deleteTask')}
</ContextMenuItem>
)}
</ContextMenuContent>
</ContextMenu>
);
}