diff --git a/src/components/pipelines/deal-form.tsx b/src/components/pipelines/deal-form.tsx index 52fa0a5..1027a6f 100644 --- a/src/components/pipelines/deal-form.tsx +++ b/src/components/pipelines/deal-form.tsx @@ -69,10 +69,12 @@ export function DealForm({ const [saving, setSaving] = useState(false); const [statusAction, setStatusAction] = useState(null); const [deleting, setDeleting] = useState(false); + const [confirmDelete, setConfirmDelete] = useState(false); // Reset when opening useEffect(() => { if (!open) return; + setConfirmDelete(false); if (deal) { setTitle(deal.title); setValue(String(deal.value ?? "")); @@ -211,10 +213,6 @@ export function DealForm({ async function handleDelete() { if (!deal) return; - const confirmed = window.confirm( - "Delete this deal? This cannot be undone.", - ); - if (!confirmed) return; setDeleting(true); const { error } = await supabase.from("deals").delete().eq("id", deal.id); setDeleting(false); @@ -223,6 +221,7 @@ export function DealForm({ return; } toast.success("Deal deleted"); + setConfirmDelete(false); onOpenChange(false); onSaved(); } @@ -426,17 +425,39 @@ export function DealForm({ - {deal && ( - - )} + {deal && + (confirmDelete ? ( +
+ Delete this deal? +
+ + +
+
+ ) : ( + + ))} diff --git a/src/components/pipelines/pipeline-analytics.tsx b/src/components/pipelines/pipeline-analytics.tsx index 769ce2f..f13f135 100644 --- a/src/components/pipelines/pipeline-analytics.tsx +++ b/src/components/pipelines/pipeline-analytics.tsx @@ -99,7 +99,7 @@ export function PipelineAnalytics({ stages, deals }: PipelineAnalyticsProps) { return ( -
+
} label="Total Deals" diff --git a/src/components/pipelines/pipeline-board.tsx b/src/components/pipelines/pipeline-board.tsx index dee50ca..ddfa1d9 100644 --- a/src/components/pipelines/pipeline-board.tsx +++ b/src/components/pipelines/pipeline-board.tsx @@ -4,6 +4,7 @@ import { useMemo, useState } from "react"; import { DndContext, DragOverlay, + KeyboardSensor, PointerSensor, useSensor, useSensors, @@ -62,6 +63,9 @@ export function PipelineBoard({ const sensors = useSensors( // 5px activation distance avoids clicks being interpreted as drags. useSensor(PointerSensor, { activationConstraint: { distance: 5 } }), + // Keyboard drag support: focus a card, Space to pick up, arrows to move, + // Space to drop, Escape to cancel. + useSensor(KeyboardSensor), ); const activeDeal = activeDealId @@ -172,7 +176,7 @@ function StageColumn({ const { setNodeRef, isOver } = useDroppable({ id: stage.id }); return ( -
+
{/* 3px colored top border — sits above the column's padding */}
({ + id: s.id, + pipeline_id: s.pipeline_id, + name: s.name, + color: s.color, + position: i, + })); + + const [renameRes, stagesRes] = await Promise.all([ + supabase + .from("pipelines") + .update({ name: name.trim() }) + .eq("id", pipeline.id), + supabase.from("pipeline_stages").upsert(stageRows, { onConflict: "id" }), + ]); + + setSaving(false); + + if (renameRes.error || stagesRes.error) { + toast.error("Failed to save pipeline"); return; } - // Persist each stage's name/color/position - for (let i = 0; i < localStages.length; i++) { - const s = localStages[i]; - await supabase - .from("pipeline_stages") - .update({ name: s.name, color: s.color, position: i }) - .eq("id", s.id); - } - - setSaving(false); onOpenChange(false); onPipelinesChanged(); onStagesChanged();