From bb0cd38520bf85db6f9e672aefb6b4bb8132b20a Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:48:35 +0000 Subject: [PATCH 1/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- .../tasks/apply-workflow-picker-dialog.tsx | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/components/tasks/apply-workflow-picker-dialog.tsx diff --git a/src/components/tasks/apply-workflow-picker-dialog.tsx b/src/components/tasks/apply-workflow-picker-dialog.tsx new file mode 100644 index 0000000..cf84d08 --- /dev/null +++ b/src/components/tasks/apply-workflow-picker-dialog.tsx @@ -0,0 +1,205 @@ +import { useState, useEffect } from "react"; +import { supabase } from "@/integrations/supabase/client"; +import { useAuth } from "@/lib/auth"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; +import { Calendar } from "@/components/ui/calendar"; +import { CalendarIcon, Loader2 } from "lucide-react"; +import { format, addDays } from "date-fns"; +import { toast } from "sonner"; +import { createNotifications } from "@/lib/notifications"; + +interface Template { + id: string; + name: string; +} +interface CaseRow { + id: string; + case_number: string; + title: string; +} + +/** + * Standalone "apply workflow" dialog for the Tasks page — lets the user + * pick BOTH a case and a template before sequentially spawning the first task. + */ +export function ApplyWorkflowPickerDialog({ + open, + onOpenChange, + onApplied, +}: { + open: boolean; + onOpenChange: (v: boolean) => void; + onApplied?: () => void; +}) { + const { user } = useAuth(); + const [templates, setTemplates] = useState([]); + const [cases, setCases] = useState([]); + const [templateId, setTemplateId] = useState(null); + const [caseId, setCaseId] = useState(null); + const [startDate, setStartDate] = useState(new Date()); + const [submitting, setSubmitting] = useState(false); + + useEffect(() => { + if (!open) return; + setTemplateId(null); + setCaseId(null); + setStartDate(new Date()); + Promise.all([ + supabase.from("workflow_templates").select("id, name").order("name"), + supabase + .from("cases") + .select("id, case_number, title") + .is("archived_at", null) + .order("case_number"), + ]).then(([t, c]) => { + setTemplates((t.data ?? []) as Template[]); + setCases((c.data ?? []) as CaseRow[]); + }); + }, [open]); + + const apply = async () => { + if (!user || !templateId || !caseId) return; + setSubmitting(true); + const { data: tpl } = await supabase + .from("workflow_template_tasks") + .select("*") + .eq("template_id", templateId) + .order("sort_order"); + const items = tpl ?? []; + if (!items.length) { + setSubmitting(false); + toast.error("Template has no tasks."); + return; + } + const first = items[0]; + const { data: created, error } = await supabase + .from("tasks") + .insert({ + title: first.title, + description: first.description, + priority: first.priority, + due_date: format(addDays(startDate, first.days_from_start), "yyyy-MM-dd"), + case_id: caseId, + workflow_template_id: templateId, + template_task_id: first.id, + created_by: user.id, + sort_order: 0, + }) + .select("id") + .single(); + if (error || !created) { + setSubmitting(false); + toast.error(error?.message || "Failed to apply"); + return; + } + if (first.default_assignee_id) { + await supabase.from("task_assignees").insert({ + task_id: created.id, + user_id: first.default_assignee_id, + assigned_by: user.id, + }); + if (first.default_assignee_id !== user.id) { + await createNotifications([ + { + user_id: first.default_assignee_id, + kind: "task_assigned", + title: `Assigned: ${first.title}`, + link: `/tasks?task=${created.id}`, + task_id: created.id, + case_id: caseId, + created_by: user.id, + }, + ]); + } + } + await supabase.from("task_history").insert({ + task_id: created.id, + actor_id: user.id, + event: "created_from_workflow", + detail: { template_id: templateId, sequential: true, total_steps: items.length }, + }); + setSubmitting(false); + toast.success( + `Workflow started — ${items.length} step${items.length === 1 ? "" : "s"} will run sequentially.`, + ); + onApplied?.(); + onOpenChange(false); + }; + + return ( + + + + Apply workflow template + +
+
+ + +
+
+ + +
+
+ + + + + + + d && setStartDate(d)} /> + + +
+
+ + + + +
+
+ ); +} From e4812565bc0891b3df8b47875443c232c505e80e Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:48:46 +0000 Subject: [PATCH 2/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/tasks.index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/tasks.index.tsx b/src/routes/tasks.index.tsx index 7a20614..9f28d8d 100644 --- a/src/routes/tasks.index.tsx +++ b/src/routes/tasks.index.tsx @@ -17,10 +17,11 @@ import { } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Label } from "@/components/ui/label"; -import { Plus, Search, Calendar as CalIcon, AlertCircle } from "lucide-react"; +import { Plus, Search, Calendar as CalIcon, AlertCircle, GitFork } from "lucide-react"; import { format, isBefore, startOfDay, isSameDay, addDays, differenceInCalendarDays } from "date-fns"; import { TaskDetailPanel } from "@/components/tasks/task-detail-panel"; import { NewTaskDialog } from "@/components/tasks/new-task-dialog"; +import { ApplyWorkflowPickerDialog } from "@/components/tasks/apply-workflow-picker-dialog"; import { cn } from "@/lib/utils"; import { spawnNextWorkflowTask } from "@/lib/workflow-chain"; From 3a74322ca1bbefaeebb1dc5ca7cac53d0e64822f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:48:58 +0000 Subject: [PATCH 3/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/tasks.index.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/routes/tasks.index.tsx b/src/routes/tasks.index.tsx index 9f28d8d..7d94710 100644 --- a/src/routes/tasks.index.tsx +++ b/src/routes/tasks.index.tsx @@ -83,6 +83,7 @@ function TasksPage() { const [query, setQuery] = useState(""); const [newOpen, setNewOpen] = useState(false); + const [wfOpen, setWfOpen] = useState(false); const [openTaskId, setOpenTaskId] = useState(search.task ?? null); const load = useCallback(async () => { @@ -205,9 +206,14 @@ function TasksPage() { title="Tasks" description="Workflow tasks, due dates, assignments, and comments." actions={ - +
+ + +
} /> From 44d4544d4d81f5e5323571b3294f97f23ced2cc6 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:49:12 +0000 Subject: [PATCH 4/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/tasks.index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/tasks.index.tsx b/src/routes/tasks.index.tsx index 7d94710..75f1ca6 100644 --- a/src/routes/tasks.index.tsx +++ b/src/routes/tasks.index.tsx @@ -384,6 +384,7 @@ function TasksPage() { setOpenTaskId(id)} /> + Date: Sat, 18 Apr 2026 23:49:20 +0000 Subject: [PATCH 5/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/collections-tab.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/cases/collections-tab.tsx b/src/components/cases/collections-tab.tsx index 65dceac..347b345 100644 --- a/src/components/cases/collections-tab.tsx +++ b/src/components/cases/collections-tab.tsx @@ -37,6 +37,7 @@ import { Calculator, ChevronRight, Download, + GitFork, Loader2, Plus, RefreshCw, From 38a9e7c5917e040afd18a9a50a53e080b7b54d22 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:49:32 +0000 Subject: [PATCH 6/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/collections-tab.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/cases/collections-tab.tsx b/src/components/cases/collections-tab.tsx index 347b345..98609bf 100644 --- a/src/components/cases/collections-tab.tsx +++ b/src/components/cases/collections-tab.tsx @@ -70,6 +70,7 @@ import { verticalListSortingStrategy, } from "@dnd-kit/sortable"; import { SortableLedgerRow } from "./ledger-row"; +import { ApplyCollectionWorkflowDialog } from "@/components/collections/apply-collection-workflow-dialog"; const TXN_TYPES = [ { value: "assessment", label: "Assessment" }, @@ -141,6 +142,7 @@ export function CaseCollectionsTab({ // dialogs const [addOpen, setAddOpen] = useState(false); const [newHomeownerOpen, setNewHomeownerOpen] = useState(false); + const [wfCollectionId, setWfCollectionId] = useState(null); const load = async () => { setLoading(true); From 7b9bc93d7ba51cbe3aadbf0be11f99fdce168acc Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:49:41 +0000 Subject: [PATCH 7/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/collections-tab.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/cases/collections-tab.tsx b/src/components/cases/collections-tab.tsx index 98609bf..0515986 100644 --- a/src/components/cases/collections-tab.tsx +++ b/src/components/cases/collections-tab.tsx @@ -306,7 +306,21 @@ export function CaseCollectionsTab({ {bal < 0 ? " CR" : ""} - +
+ + +
); From 422bbae31c3fd044e1eea0843223d9d7344f164d Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:49:52 +0000 Subject: [PATCH 8/8] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/collections-tab.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/cases/collections-tab.tsx b/src/components/cases/collections-tab.tsx index 0515986..c66d7db 100644 --- a/src/components/cases/collections-tab.tsx +++ b/src/components/cases/collections-tab.tsx @@ -348,6 +348,18 @@ export function CaseCollectionsTab({ clientId={clientId} onCreated={load} /> + + {wfCollectionId && ( + !v && setWfCollectionId(null)} + collectionId={wfCollectionId} + onApplied={() => { + setWfCollectionId(null); + load(); + }} + /> + )} ); }