diff --git a/src/app/(app)/orders/page.tsx b/src/app/(app)/orders/page.tsx index b321ff6..fb6c783 100644 --- a/src/app/(app)/orders/page.tsx +++ b/src/app/(app)/orders/page.tsx @@ -26,6 +26,8 @@ import { import getPocketBase from "@/lib/pocketbase"; import { displayContactName } from "@/lib/utils"; import { isOrderComplete } from "@/lib/server/order-completion"; +import { useAuth } from "@/components/auth-provider"; +import { isRepUser } from "@/lib/rep-visibility"; import type { OrdersDashboardData, OrderWithItems, @@ -112,6 +114,7 @@ async function fetchDashboardJson(url: string): Promise { export default function OrdersPage() { const router = useRouter(); + const { user } = useAuth(); const [orders, setOrders] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); @@ -275,11 +278,27 @@ export default function OrdersPage() { const openReview = (orderId: string) => setReviewOrderId(orderId); const closeReview = () => setReviewOrderId(null); + // Rep-scoped UI filter — reps only see orders tied to them, either + // via the denormalized `orders.rep` text field or via + // `customer.rep`. Everyone else (buyer/quoter/admin/boss/etc.) sees + // the unfiltered list. This filters the already-fetched page of + // orders; it does not change what the server returns, so tab + // counts / pagination totals stay unscoped — see the plan's "Known + // limitation" note. + const visibleOrders = useMemo(() => { + const userType = (user as { user_type?: string[] } | null)?.user_type; + if (!user || !isRepUser(userType)) return orders; + return orders.filter( + ({ order }) => + order.rep === user.id || order.expand?.customer?.rep === user.id, + ); + }, [orders, user]); + // The server already filtered `orders` to those with at least one // item in `activeTab` (via the `tab` query param). No client-side // filter needed — re-applying it would drop orders the server // intended to show. - const totalLoaded = orders.length; + const totalLoaded = visibleOrders.length; const searching = search.trim().length > 0; // Sum of orders across the other active tabs (for the empty-state @@ -387,7 +406,7 @@ export default function OrdersPage() {

{error}

- ) : orders.length === 0 ? ( + ) : visibleOrders.length === 0 ? ( @@ -444,7 +463,7 @@ export default function OrdersPage() { <> {searching && (

- {orders.length} match{orders.length === 1 ? "" : "es"} in + {visibleOrders.length} match{visibleOrders.length === 1 ? "" : "es"} in {" "} {TAB_GROUP_VISUAL[activeTab].label} for {" "} @@ -463,7 +482,7 @@ export default function OrdersPage() {

)}
- {orders.map(({ order, items, repName, tabGroups }) => ( + {visibleOrders.map(({ order, items, repName, tabGroups }) => (