fix(collections): keep stop expanded while working through its items
When a driver collects or reports a problem on an item, the supplier group they were working through used to collapse — forcing them to re-expand it for every single item in the stop. Root cause was a useCallback dep cycle: - loadItems had items.length in its dep array - handleCollect / handleProblem filter the processed item out of state - items.length decreasing rebuilt loadItems (new identity) - the consuming useEffect([loadItems]) re-fired loadItems - loadItems's setExpandedSuppliers(new Set()) wiped every group Fix: mirror items.length into a useRef so loadItems can read the current count for the loading-skeleton decision without subscribing to it. loadItems now only rebuilds when statusFilter changes (mount, filter chip tap, refresh), so processing an item no longer resets the expansion state. Drivers can work through every item in a stop without re-expanding. Behavior preserved on real refreshes / tab switches / filter changes — those still reset to collapsed, which matches the new 'flat list of stops on open' UX.
This commit is contained in:
parent
04d56fa1fb
commit
85a40a76bf
1 changed files with 21 additions and 5 deletions
26
app/page.tsx
26
app/page.tsx
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { OrderItem } from '@/lib/types';
|
||||
import { useAuth } from '@/components/AuthProvider';
|
||||
|
|
@ -100,6 +100,21 @@ export default function CollectionsPage() {
|
|||
// collapsed independently of the supplier they're inside.
|
||||
const [expandedPOs, setExpandedPOs] = useState<Set<string>>(new Set());
|
||||
|
||||
// Mirror items.length into a ref so loadItems can decide whether to
|
||||
// flash the loading skeleton WITHOUT making items.length a callback
|
||||
// dependency. If items.length WERE a dep, every successful collect
|
||||
// (which filters the collected item out of state) would rebuild
|
||||
// loadItems, the auto-fire useEffect below would re-run loadItems,
|
||||
// and the setExpandedSuppliers(new Set()) call inside it would
|
||||
// collapse the supplier the driver is currently working through —
|
||||
// forcing them to re-expand for every single item. The ref lets us
|
||||
// keep the "don't flash a skeleton when items are already on screen"
|
||||
// behavior while breaking the collapse loop.
|
||||
const itemsLengthRef = useRef(0);
|
||||
useEffect(() => {
|
||||
itemsLengthRef.current = items.length;
|
||||
}, [items.length]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!authLoading && !isLoggedIn) router.push('/login/');
|
||||
}, [isLoggedIn, authLoading, router]);
|
||||
|
|
@ -116,9 +131,10 @@ export default function CollectionsPage() {
|
|||
const loadItems = useCallback(async (showLoading = true) => {
|
||||
if (!isAuthenticated()) return;
|
||||
// Only show the loading skeleton when we genuinely have nothing
|
||||
// to render. If cached data is on screen, the re-fetch happens
|
||||
// silently and the user sees fresh data appear without a flash.
|
||||
if (showLoading && items.length === 0) setIsLoading(true);
|
||||
// to render. Read items.length from the ref so this stays a
|
||||
// current-value check, not a subscription — see the comment on
|
||||
// itemsLengthRef above for why.
|
||||
if (showLoading && itemsLengthRef.current === 0) setIsLoading(true);
|
||||
setError('');
|
||||
try {
|
||||
let data: OrderItem[] = [];
|
||||
|
|
@ -162,7 +178,7 @@ const loadItems = useCallback(async (showLoading = true) => {
|
|||
setIsLoading(false);
|
||||
setIsRefreshing(false);
|
||||
}
|
||||
}, [statusFilter, items.length]);
|
||||
}, [statusFilter]);
|
||||
|
||||
useEffect(() => { loadItems(); }, [loadItems]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue