From 1cc2e9366dd2cc13652b9defc69a708fb2c16102 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 07:10:21 +0000 Subject: [PATCH 1/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/collections.index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/collections.index.tsx b/src/routes/collections.index.tsx index e87b9bc..fc00e93 100644 --- a/src/routes/collections.index.tsx +++ b/src/routes/collections.index.tsx @@ -1,5 +1,5 @@ import { createFileRoute, Link } from "@tanstack/react-router"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { ProtectedLayout } from "@/components/protected-layout"; import { PageContainer, PageHeader } from "@/components/app-shell"; import { supabase } from "@/integrations/supabase/client"; @@ -22,7 +22,7 @@ import { TableRow, } from "@/components/ui/table"; import { formatCurrency, formatDate } from "@/lib/format"; -import { ChevronRight, Wallet, Search } from "lucide-react"; +import { ChevronRight, Wallet, Search, ArrowUp, ArrowDown, ArrowUpDown } from "lucide-react"; export const Route = createFileRoute("/collections/")({ component: CollectionsIndexPage, From e08df7b15a8af129a04eb7ee7a8b06ecca75cb06 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 07:10:31 +0000 Subject: [PATCH 2/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/collections.index.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/routes/collections.index.tsx b/src/routes/collections.index.tsx index fc00e93..6e2205c 100644 --- a/src/routes/collections.index.tsx +++ b/src/routes/collections.index.tsx @@ -42,6 +42,13 @@ function CollectionsIndexPage() { const [loading, setLoading] = useState(true); const [search, setSearch] = useState(""); const [stageFilter, setStageFilter] = useState("all"); + const [sortKey, setSortKey] = useState<"homeowner" | "case" | "stage" | "tasks" | "opened" | "balance">("opened"); + const [sortDir, setSortDir] = useState<"asc" | "desc">("desc"); + + const toggleSort = (key: typeof sortKey) => { + if (sortKey === key) setSortDir((d) => (d === "asc" ? "desc" : "asc")); + else { setSortKey(key); setSortDir("asc"); } + }; const load = async () => { setLoading(true); From b11bbad7ed4dee1f4b5fbb35f1cc5752ab7a06c4 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 07:10:43 +0000 Subject: [PATCH 3/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/collections.index.tsx | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/routes/collections.index.tsx b/src/routes/collections.index.tsx index 6e2205c..8e56dc0 100644 --- a/src/routes/collections.index.tsx +++ b/src/routes/collections.index.tsx @@ -121,6 +121,47 @@ function CollectionsIndexPage() { ); }); + const sorted = useMemo(() => { + const getVal = (r: any): string | number => { + switch (sortKey) { + case "homeowner": + return `${r.homeowner?.last_name ?? ""} ${r.homeowner?.first_name ?? ""}`.toLowerCase(); + case "case": + return (r.case?.client?.name ?? "").toLowerCase(); + case "stage": + return (stages.find((s) => s.key === r.current_stage)?.label ?? "").toLowerCase(); + case "tasks": + return openTaskCounts[r.id] ?? 0; + case "opened": + return r.opened_at ? new Date(r.opened_at).getTime() : 0; + case "balance": + return balances[r.id] ?? 0; + } + }; + return [...filtered].sort((a, b) => { + const av = getVal(a); + const bv = getVal(b); + if (av < bv) return sortDir === "asc" ? -1 : 1; + if (av > bv) return sortDir === "asc" ? 1 : -1; + return 0; + }); + }, [filtered, sortKey, sortDir, balances, openTaskCounts, stages]); + + const SortHeader = ({ k, label, className }: { k: typeof sortKey; label: string; className?: string }) => { + const Icon = sortKey !== k ? ArrowUpDown : sortDir === "asc" ? ArrowUp : ArrowDown; + return ( + + + + ); + }; + return ( From 4d6ea0ed85e4fd8dbd8c2e13f6425f87bac6526e 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 07:10:54 +0000 Subject: [PATCH 4/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/collections.index.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/routes/collections.index.tsx b/src/routes/collections.index.tsx index 8e56dc0..d522b41 100644 --- a/src/routes/collections.index.tsx +++ b/src/routes/collections.index.tsx @@ -209,17 +209,17 @@ function CollectionsIndexPage() { - Homeowner - HOA / Case - Stage - Open tasks - Opened - Balance + + + + + + - {filtered.map((r) => { + {sorted.map((r) => { const bal = balances[r.id] ?? 0; const tcount = openTaskCounts[r.id] ?? 0; return ( From 7bb01320fa60e0c9d84337d23ec6bfea9ae65ff6 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 07:11:02 +0000 Subject: [PATCH 5/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/documents-tab.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/cases/documents-tab.tsx b/src/components/cases/documents-tab.tsx index 544ec93..26b44e4 100644 --- a/src/components/cases/documents-tab.tsx +++ b/src/components/cases/documents-tab.tsx @@ -16,6 +16,7 @@ import { Home, Eye, ExternalLink, + Pencil, } from "lucide-react"; import { formatDate } from "@/lib/format"; import { toast } from "sonner"; From 5ba2208cd44167a280e63992024fd1dd45c2046b 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 07:11:20 +0000 Subject: [PATCH 6/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/documents-tab.tsx | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/components/cases/documents-tab.tsx b/src/components/cases/documents-tab.tsx index 26b44e4..73d6c26 100644 --- a/src/components/cases/documents-tab.tsx +++ b/src/components/cases/documents-tab.tsx @@ -255,6 +255,56 @@ export function CaseDocumentsTab({ caseId }: { caseId: string }) { load(); }; + const renameFolder = async (full: string) => { + const parts = full.split("/"); + const currentName = parts[parts.length - 1]; + const parent = parts.slice(0, -1).join("/"); + const raw = window.prompt(`Rename folder "${currentName}" to:`, currentName); + if (raw === null) return; + const trimmed = raw.trim(); + if (!trimmed || trimmed === currentName) return; + const safe = sanitizeName(trimmed); + const newFull = parent ? `${parent}/${safe}` : safe; + if (folders.includes(newFull)) { + toast.error("A folder with that name already exists here"); + return; + } + + // Update all document rows whose folder == full or starts with full + "/" + const affectedDocs = docs.filter( + (d) => (d.folder || "") === full || (d.folder || "").startsWith(`${full}/`), + ); + for (const d of affectedDocs) { + const next = d.folder === full ? newFull : `${newFull}${d.folder.slice(full.length)}`; + const { error } = await supabase.from("documents").update({ folder: next }).eq("id", d.id); + if (error) { toast.error("Rename failed", { description: error.message }); return; } + } + + // Update folder rows (this folder + all descendants) + const affectedFolders = folders.filter((f) => f === full || f.startsWith(`${full}/`)); + for (const f of affectedFolders) { + const next = f === full ? newFull : `${newFull}${f.slice(full.length)}`; + // Try update; if conflict (rare), delete old row instead + const { error } = await supabase + .from("document_folders") + .update({ path: next }) + .eq("case_id", caseId) + .eq("path", f); + if (error) { + await supabase.from("document_folders").delete().eq("case_id", caseId).eq("path", f); + await ensureFolder(next); + } + } + + // If we are currently inside the renamed folder, update the breadcrumb path + if (path === full || path.startsWith(`${full}/`)) { + setPath(newFull + path.slice(full.length)); + } + + toast.success("Folder renamed"); + load(); + }; + const crumbs = path ? path.split("/") : []; return ( From dda8ef8234283c210b133a882b298d3e7e520aea 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 07:11:30 +0000 Subject: [PATCH 7/7] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/cases/documents-tab.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/cases/documents-tab.tsx b/src/components/cases/documents-tab.tsx index 73d6c26..4f8c8ff 100644 --- a/src/components/cases/documents-tab.tsx +++ b/src/components/cases/documents-tab.tsx @@ -399,8 +399,11 @@ export function CaseDocumentsTab({ caseId }: { caseId: string }) { -
Folder - + +