refactor(collection-map): drop status / readiness / search filters
This commit is contained in:
parent
a26e7c6312
commit
d876455e41
1 changed files with 2 additions and 92 deletions
|
|
@ -35,7 +35,7 @@ import {
|
|||
useMap,
|
||||
useMapEvents,
|
||||
} from "react-leaflet";
|
||||
import { Calendar, ExternalLink, MapPin, RefreshCw, Search, Truck, User as UserIcon, Users, X, Layers } from "lucide-react";
|
||||
import { Calendar, ExternalLink, MapPin, RefreshCw, Truck, User as UserIcon, Users, X, Layers } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -80,14 +80,6 @@ const DARK_TILE_ATTRIBUTION = '© <a href="https://www.openstreetmap.org/cop
|
|||
// the marker factory call reads naturally without dereferencing the import.
|
||||
const UNASSIGNED_PIN_COLOR = STOP_STATUS_COLOR.unassigned;
|
||||
|
||||
/** Status filter options (matches the segmented control on the sidebar). */
|
||||
type StatusFilter = "all" | "assigned" | "unassigned";
|
||||
const STATUS_FILTERS: ReadonlyArray<{ value: StatusFilter; label: string }> = [
|
||||
{ value: "all", label: "All" },
|
||||
{ value: "assigned", label: "Assigned" },
|
||||
{ value: "unassigned", label: "Unassigned" },
|
||||
];
|
||||
|
||||
/* ============================================================================
|
||||
* Types
|
||||
* ========================================================================= */
|
||||
|
|
@ -309,12 +301,6 @@ export default function CollectionMapPage() {
|
|||
const [suppliersWithoutCoords, setSuppliersWithoutCoords] = useState<string[]>([]);
|
||||
|
||||
const [date, setDate] = useState(ymdToday());
|
||||
const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
|
||||
// Ready-filter — narrows the visible map stops to ready/unready/all.
|
||||
// Default `all` to keep behaviour compatible with existing dashboard
|
||||
// data (every existing pool row is `ready=true` post-migration).
|
||||
const [readyFilter, setReadyFilter] = useState<"all" | "ready" | "unready">("all");
|
||||
const [search, setSearch] = useState("");
|
||||
// Traffic overlay toggle — default OFF to conserve the TomTom
|
||||
// freemium 2,500-tile/day budget. Operators can flip it on for a
|
||||
// single planning session; Leaflet caches tiles client-side so
|
||||
|
|
@ -448,28 +434,7 @@ export default function CollectionMapPage() {
|
|||
return m;
|
||||
}, [allUsers]);
|
||||
|
||||
const filteredItems = useMemo(() => {
|
||||
const query = search.trim().toLowerCase();
|
||||
return items.filter((it) => {
|
||||
if (statusFilter === "assigned" && it.item_status !== "assigned") return false;
|
||||
if (statusFilter === "unassigned" && it.item_status !== "collection_pool") return false;
|
||||
// Ready-filter sits after the status filter so "ready + assigned"
|
||||
// and "unassigned + ready" remain combinable — same logic as the
|
||||
// collection-pool page.
|
||||
if (readyFilter !== "all") {
|
||||
const want = readyFilter === "ready";
|
||||
if (Boolean(it.ready_for_collection) !== want) return false;
|
||||
}
|
||||
if (enabledDriverIds.size > 0) {
|
||||
if (!it.drv_id || !enabledDriverIds.has(it.drv_id)) return false;
|
||||
}
|
||||
if (query) {
|
||||
const hay = `${it.description} ${it.po_number || ""} ${it.supplier_name} ${it.order_number || ""}`.toLowerCase();
|
||||
if (!hay.includes(query)) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, [items, statusFilter, readyFilter, enabledDriverIds, search]);
|
||||
const filteredItems = useMemo(() => items, [items]);
|
||||
|
||||
/* -- grouping by supplier ------------------------------------------------ */
|
||||
const supplierStops = useMemo<SupplierStop[]>(() => {
|
||||
|
|
@ -752,64 +717,9 @@ export default function CollectionMapPage() {
|
|||
);
|
||||
})}
|
||||
</div>
|
||||
{/* Status filter — labelled so it doesn't read as a second copy
|
||||
of the Ready filter that also starts with "All". */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">Status</span>
|
||||
<div className="inline-flex h-9 overflow-hidden rounded-md border bg-background">
|
||||
{STATUS_FILTERS.map((opt) => (
|
||||
<button
|
||||
key={opt.value}
|
||||
type="button"
|
||||
onClick={() => setStatusFilter(opt.value)}
|
||||
className={cn(
|
||||
"px-3 text-xs font-medium transition-colors",
|
||||
statusFilter === opt.value
|
||||
? "bg-primary text-primary-foreground"
|
||||
: "text-muted-foreground hover:bg-muted"
|
||||
)}
|
||||
>
|
||||
{opt.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/* Ready filter — supplier-confirmed gate. Sits next to the
|
||||
status filter so operators can layer them ("assigned + not
|
||||
yet ready" is the most useful debug combo). */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">Readiness</span>
|
||||
<div className="inline-flex h-9 overflow-hidden rounded-md border bg-background">
|
||||
{(["all", "ready", "unready"] as const).map((opt) => (
|
||||
<button
|
||||
key={opt}
|
||||
type="button"
|
||||
aria-pressed={readyFilter === opt}
|
||||
onClick={() => setReadyFilter(opt)}
|
||||
className={cn(
|
||||
"px-3 text-xs font-medium transition-colors",
|
||||
readyFilter === opt
|
||||
? "bg-primary text-primary-foreground"
|
||||
: "text-muted-foreground hover:bg-muted"
|
||||
)}
|
||||
>
|
||||
{opt === "all" ? "All" : opt === "ready" ? "Ready" : "Unready"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<div className="relative w-full sm:w-64">
|
||||
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
value={search}
|
||||
onChange={(event) => setSearch(event.target.value)}
|
||||
placeholder="Search PO, supplier, item..."
|
||||
className="h-9 pl-9 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" className="h-9" onClick={fetchRows} disabled={loading}>
|
||||
<RefreshCw className={cn("mr-1.5 h-4 w-4", loading && "animate-spin")} />
|
||||
Refresh
|
||||
|
|
|
|||
Loading…
Reference in a new issue