From 2a5a7a0d7768e22beaf2780ae40ba0786c87a990 Mon Sep 17 00:00:00 2001 From: Benson Cho <100653148+choden-dev@users.noreply.github.com> Date: Sat, 25 Apr 2026 18:44:59 +1200 Subject: [PATCH 1/7] fix: change pickup routes to pickup step & add timeslot pagination - Fix 'Change Pickup' routing: AWAITING_PICKUP status now maps to the PICKUP step instead of COMPLETE, so users can actually re-select their pickup timeslot instead of being sent to the confirmed screen. - Add pagination to TimeslotSelector: timeslots are grouped by date and paginated 3 dates per page with Previous/Next controls, so the list doesn't get cut off when many slots are available. --- components/ordercontainer/OrderContainer.tsx | 2 +- components/pickup/TimeslotSelector.tsx | 254 ++++++++++++------- 2 files changed, 163 insertions(+), 93 deletions(-) diff --git a/components/ordercontainer/OrderContainer.tsx b/components/ordercontainer/OrderContainer.tsx index 1e54554..040316d 100644 --- a/components/ordercontainer/OrderContainer.tsx +++ b/components/ordercontainer/OrderContainer.tsx @@ -83,8 +83,8 @@ const OrderContainerInner = ({ case OrderStatus.AWAITING_PAYMENT: return OrderStep.PAYMENT; case OrderStatus.PAID: - return OrderStep.PICKUP; case OrderStatus.AWAITING_PICKUP: + return OrderStep.PICKUP; case OrderStatus.PRINTED: case OrderStatus.PICKED_UP: return OrderStep.COMPLETE; diff --git a/components/pickup/TimeslotSelector.tsx b/components/pickup/TimeslotSelector.tsx index a84fa3e..873f6f5 100644 --- a/components/pickup/TimeslotSelector.tsx +++ b/components/pickup/TimeslotSelector.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; interface PickupProfileInfo { id: string; @@ -29,6 +29,9 @@ interface TimeslotSelectorProps { onCancel: () => void; } +/** Number of date-groups to show per page. */ +const DATES_PER_PAGE = 3; + /** Group timeslots by date for display. */ function groupByDate(slots: Timeslot[]): Map { const map = new Map(); @@ -61,7 +64,8 @@ function formatDateHeading(dateStr: string): string { /** * Component to select a pickup timeslot for an order. - * Fetches available timeslots and displays them grouped by date. + * Fetches available timeslots and displays them grouped by date + * with pagination so the list doesn't get cut off. * Shows capacity info and pickup instruction profile names. */ export function TimeslotSelector({ @@ -74,6 +78,7 @@ export function TimeslotSelector({ const [error, setError] = useState(null); const [selectedId, setSelectedId] = useState(null); const [submitting, setSubmitting] = useState(false); + const [page, setPage] = useState(0); // Fetch available timeslots useEffect(() => { @@ -97,6 +102,16 @@ export function TimeslotSelector({ fetchTimeslots(); }, []); + // Group timeslots by date and paginate by date-groups + const grouped = useMemo(() => groupByDate(timeslots), [timeslots]); + const dateKeys = useMemo(() => Array.from(grouped.keys()), [grouped]); + const totalPages = Math.max(1, Math.ceil(dateKeys.length / DATES_PER_PAGE)); + + const visibleDateKeys = useMemo(() => { + const start = page * DATES_PER_PAGE; + return dateKeys.slice(start, start + DATES_PER_PAGE); + }, [dateKeys, page]); + // Handle timeslot selection submission const handleSubmit = useCallback(async () => { if (!selectedId) return; @@ -164,108 +179,154 @@ export function TimeslotSelector({ ); } - const grouped = groupByDate(timeslots); - return (

Select a Pickup Timeslot

- {Array.from(grouped.entries()).map(([dateKey, slots]) => ( -
-

- {formatDateHeading(dateKey)} -

-
- {slots.map((slot) => { - const isSelected = selectedId === slot.id; - return ( -