Sorted workflow sources

X-Lovable-Edit-ID: edt-1973a40b-6a11-4f30-8315-0ba6bb393059
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-19 00:04:56 +00:00
co-authored by renee-png
6 changed files with 77 additions and 10 deletions
@@ -50,6 +50,7 @@ export function ApplyCollectionWorkflowDialog({
supabase
.from("workflow_templates")
.select("id, name")
.eq("kind", "collection")
.order("name")
.then(({ data }) => setTemplates((data ?? []) as Template[]));
setTemplateId(null);
@@ -51,6 +51,7 @@ export function ApplyWorkflowDialog({
supabase
.from("workflow_templates")
.select("id, name")
.eq("kind", "task")
.order("name")
.then(({ data }) => setTemplates((data ?? []) as Template[]));
setTemplateId(null);
@@ -61,7 +61,7 @@ export function ApplyWorkflowPickerDialog({
setCaseId(null);
setStartDate(new Date());
Promise.all([
supabase.from("workflow_templates").select("id, name").order("name"),
supabase.from("workflow_templates").select("id, name").eq("kind", "task").order("name"),
supabase
.from("cases")
.select("id, case_number, title")
+3
View File
@@ -3013,6 +3013,7 @@ export type Database = {
created_by: string | null
description: string | null
id: string
kind: string
name: string
updated_at: string
}
@@ -3021,6 +3022,7 @@ export type Database = {
created_by?: string | null
description?: string | null
id?: string
kind?: string
name: string
updated_at?: string
}
@@ -3029,6 +3031,7 @@ export type Database = {
created_by?: string | null
description?: string | null
id?: string
kind?: string
name?: string
updated_at?: string
}
+59 -9
View File
@@ -32,6 +32,7 @@ interface Template {
name: string;
description: string | null;
created_by: string | null;
kind: "task" | "collection";
}
interface TemplateTask {
id: string;
@@ -58,6 +59,7 @@ function WorkflowsPage() {
const [newOpen, setNewOpen] = useState(false);
const [newName, setNewName] = useState("");
const [newDesc, setNewDesc] = useState("");
const [newKind, setNewKind] = useState<"task" | "collection">("task");
const [newTask, setNewTask] = useState({ title: "", days: 7, priority: "normal" as const });
const loadTemplates = useCallback(async () => {
@@ -95,7 +97,12 @@ function WorkflowsPage() {
if (!user || !newName.trim()) return;
const { data, error } = await supabase
.from("workflow_templates")
.insert({ name: newName.trim(), description: newDesc.trim() || null, created_by: user.id })
.insert({
name: newName.trim(),
description: newDesc.trim() || null,
kind: newKind,
created_by: user.id,
})
.select()
.single();
if (error) {
@@ -104,11 +111,18 @@ function WorkflowsPage() {
}
setNewName("");
setNewDesc("");
setNewKind("task");
setNewOpen(false);
await loadTemplates();
setSelected(data as Template);
};
const updateTemplateKind = async (id: string, kind: "task" | "collection") => {
await supabase.from("workflow_templates").update({ kind }).eq("id", id);
await loadTemplates();
if (selected?.id === id) setSelected({ ...selected, kind });
};
const deleteTemplate = async (id: string) => {
if (!confirm("Delete this workflow template?")) return;
await supabase.from("workflow_templates").delete().eq("id", id);
@@ -167,7 +181,16 @@ function WorkflowsPage() {
selected?.id === t.id ? "bg-accent" : ""
}`}
>
<div className="font-medium text-sm">{t.name}</div>
<div className="flex items-center justify-between gap-2">
<div className="font-medium text-sm truncate">{t.name}</div>
<span className={`text-[10px] px-1.5 py-0.5 rounded shrink-0 ${
t.kind === "collection"
? "bg-amber-500/15 text-amber-700 dark:text-amber-300"
: "bg-blue-500/15 text-blue-700 dark:text-blue-300"
}`}>
{t.kind === "collection" ? "Collection" : "Task"}
</span>
</div>
{t.description && <div className="text-xs text-muted-foreground truncate">{t.description}</div>}
</button>
))}
@@ -181,16 +204,31 @@ function WorkflowsPage() {
</div>
) : (
<div className="rounded-md border bg-card">
<div className="px-4 py-3 border-b flex items-center justify-between">
<div>
<div className="font-semibold">{selected.name}</div>
<div className="px-4 py-3 border-b flex items-center justify-between gap-3">
<div className="min-w-0">
<div className="font-semibold truncate">{selected.name}</div>
{selected.description && (
<div className="text-xs text-muted-foreground">{selected.description}</div>
<div className="text-xs text-muted-foreground truncate">{selected.description}</div>
)}
</div>
<Button variant="ghost" size="sm" onClick={() => deleteTemplate(selected.id)}>
<Trash2 className="h-3.5 w-3.5 text-destructive" />
</Button>
<div className="flex items-center gap-2 shrink-0">
<Label className="text-xs text-muted-foreground">Type</Label>
<Select
value={selected.kind}
onValueChange={(v) => updateTemplateKind(selected.id, v as "task" | "collection")}
>
<SelectTrigger className="w-36 h-8">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="task">Task workflow</SelectItem>
<SelectItem value="collection">Collection workflow</SelectItem>
</SelectContent>
</Select>
<Button variant="ghost" size="sm" onClick={() => deleteTemplate(selected.id)}>
<Trash2 className="h-3.5 w-3.5 text-destructive" />
</Button>
</div>
</div>
<div className="divide-y">
{tasks.map((t) => (
@@ -283,6 +321,18 @@ function WorkflowsPage() {
<Label className="text-xs">Description</Label>
<Textarea value={newDesc} onChange={(e) => setNewDesc(e.target.value)} rows={2} />
</div>
<div>
<Label className="text-xs">Type</Label>
<Select value={newKind} onValueChange={(v) => setNewKind(v as "task" | "collection")}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="task">Task workflow — applied to cases & tasks</SelectItem>
<SelectItem value="collection">Collection workflow — applied to collections</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setNewOpen(false)}>Cancel</Button>
@@ -0,0 +1,12 @@
ALTER TABLE public.workflow_templates
ADD COLUMN IF NOT EXISTS kind text NOT NULL DEFAULT 'task';
ALTER TABLE public.workflow_templates
DROP CONSTRAINT IF EXISTS workflow_templates_kind_check;
ALTER TABLE public.workflow_templates
ADD CONSTRAINT workflow_templates_kind_check
CHECK (kind IN ('task','collection'));
CREATE INDEX IF NOT EXISTS workflow_templates_kind_idx
ON public.workflow_templates (kind);