From 8faa4437b6acdddd607f0ed751c19d76c31731cf Mon Sep 17 00:00:00 2001 From: Dave Date: Mon, 31 Aug 2026 23:26:42 +0200 Subject: [PATCH] feat(quotes): filter list to the logged-in rep's own quotes --- src/app/(app)/quotes/page.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/app/(app)/quotes/page.tsx b/src/app/(app)/quotes/page.tsx index 1eebeaa..64f1dec 100644 --- a/src/app/(app)/quotes/page.tsx +++ b/src/app/(app)/quotes/page.tsx @@ -32,6 +32,8 @@ import { import { toast } from "sonner"; import { cn } from "@/lib/utils"; import getPocketBase from "@/lib/pocketbase"; +import { useAuth } from "@/components/auth-provider"; +import { isRepUser } from "@/lib/rep-visibility"; import { getQuoteItems, fetchQuoteItemCounts, @@ -140,6 +142,7 @@ const AGED_STATUSES: ReadonlySet = new Set(["new", "claimed"]); export default function QuotesPage() { const router = useRouter(); + const { user } = useAuth(); const [quotes, setQuotes] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); @@ -439,6 +442,15 @@ export default function QuotesPage() { return map; }, [users]); + // Rep-scoped UI filter — same rationale as the Orders page (see + // src/lib/rep-visibility.ts). Quotes only carry rep via the + // customer relation (no denormalized text field like orders.rep). + const visibleQuotes = useMemo(() => { + const userType = (user as { user_type?: string[] } | null)?.user_type; + if (!user || !isRepUser(userType)) return quotes; + return quotes.filter((quote) => quote.expand?.customer?.rep === user.id); + }, [quotes, user]); + /** * Toggle a row's expanded state. The first time a row opens we kick * off a `getQuoteItems(id)` fetch; subsequent toggles use the cache. @@ -867,7 +879,7 @@ export default function QuotesPage() { }, }, ]} - data={quotes} + data={visibleQuotes} loading={loading} error={error} // Placeholder lists every surface the pushdown actually hits @@ -898,7 +910,7 @@ export default function QuotesPage() { "text-xs whitespace-nowrap", loading ? "text-muted-foreground/60" - : quotes.length === 0 + : visibleQuotes.length === 0 ? "text-warn font-medium" : "text-muted-foreground", )} @@ -906,11 +918,11 @@ export default function QuotesPage() { > {loading ? ( <>Searching… - ) : quotes.length === 0 ? ( + ) : visibleQuotes.length === 0 ? ( <>0 matches for “{searchInput.trim()}” ) : ( <> - {quotes.length} match{quotes.length === 1 ? "" : "es"} for{" "} + {visibleQuotes.length} match{visibleQuotes.length === 1 ? "" : "es"} for{" "} “{searchInput.trim()}”