diff --git a/src/app/(app)/quotes/[id]/process/page.tsx b/src/app/(app)/quotes/[id]/process/page.tsx index 25d43fd..826fd77 100644 --- a/src/app/(app)/quotes/[id]/process/page.tsx +++ b/src/app/(app)/quotes/[id]/process/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect, useCallback, Fragment } from "react"; +import { useState, useEffect, useCallback, useMemo, Fragment } from "react"; import { use } from "react"; import { useRouter } from "next/navigation"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; @@ -67,6 +67,11 @@ export default function QuoteProcessPage({ params }: { params: Promise<{ id: str * auto-switches the lock to it, so the user is never fighting the UI. */ const [pricingLock, setPricingLock] = useState<"cost" | "selling">("cost"); + /** + * Focus mode for the items table: completed items naturally sink to + * the bottom; a one-click toggle drops them from view entirely. + */ + const [showCompleted, setShowCompleted] = useState(true); const [rewriteOpen, setRewriteOpen] = useState(false); const fetchData = useCallback(async () => { @@ -91,6 +96,21 @@ export default function QuoteProcessPage({ params }: { params: Promise<{ id: str useEffect(() => { fetchData(); }, [fetchData]); + /** + * Items to render in the table. Auto-sort: incomplete first, done + * last. Original row number preserved via `originalIdx` so the + * "1, 2, 3…" reference stays stable as items move around. + */ + const displayItems = useMemo(() => { + const annotated = items.map((item, originalIdx) => ({ item, originalIdx })); + const filtered = showCompleted + ? annotated + : annotated.filter(({ item }) => !item.is_processed); + return [...filtered].sort( + (a, b) => Number(a.item.is_processed) - Number(b.item.is_processed) + ); + }, [items, showCompleted]); + const toggleRow = (itemId: string) => { setExpandedRows((prev) => { const next = new Set(prev); @@ -247,7 +267,8 @@ export default function QuoteProcessPage({ params }: { params: Promise<{ id: str const { subtotal, vat_amount, grand_total } = calculateTotals( items.map((i) => ({ selling_price: i.selling_price || 0, quantity: i.quantity || 1 })) ); - const processedCount = items.filter((i) => i.is_processed).length; + const processedCount = items.filter((i) => i.is_processed).length; + const allProcessed = items.length > 0 && items.every((i) => i.is_processed); return (
+ All {items.length} items processed +
+ +