diff --git a/src/apis/picking.ts b/src/apis/picking.ts index e726a1ea..c6d97191 100644 --- a/src/apis/picking.ts +++ b/src/apis/picking.ts @@ -50,16 +50,20 @@ export function getPickTasksApi(facilityId: string, params?: Partial `status=${encodeURIComponent(status)}`); - return ApiClient.get( - `/facilities/${facilityId}/pick-tasks?${statuses.map((status) => `status=${encodeURIComponent(status)}`).join('&')}` - ); + if (excludeAssignedRequisitions !== undefined) { + query.push(`excludeAssignedRequisitions=${excludeAssignedRequisitions}`); + } + + return ApiClient.get(`/facilities/${facilityId}/pick-tasks?${query.join('&')}`); } export function getPickTaskCountsApi(facilityId: string) { - return ApiClient.get(`/facilities/${facilityId}/pick-tasks/counts`); + return ApiClient.get(`/facilities/${facilityId}/pick-tasks/counts?excludeAssignedRequisitions=true`); } export function patchPickTaskApi(facilityId: string, taskId: string, params: PickTaskActionParams) { diff --git a/src/redux/actions/picking.ts b/src/redux/actions/picking.ts index e80fb8b3..90a79972 100644 --- a/src/redux/actions/picking.ts +++ b/src/redux/actions/picking.ts @@ -71,6 +71,7 @@ export function getPickTasksAction( } export function getOpenPickTasksAction( + excludeAssignedRequisitions: boolean, callback: (response: { response?: { data: PickTask[]; @@ -85,6 +86,7 @@ export function getOpenPickTasksAction( ) { return { type: GET_OPEN_PICK_TASKS_REQUEST, + payload: { excludeAssignedRequisitions }, callback }; } diff --git a/src/redux/sagas/picking.ts b/src/redux/sagas/picking.ts index 3c636642..c32785de 100644 --- a/src/redux/sagas/picking.ts +++ b/src/redux/sagas/picking.ts @@ -75,7 +75,11 @@ function* getOpenPickTasksAction(action: any) { // No full-screen loading indicator here on purpose: the list screen renders its own // inline skeleton / pull-to-refresh state so the screen never blocks on the fetch. // @ts-ignore - const response = yield call(api.getOpenPickTasksApi, currentLocation.id); + const response = yield call( + api.getOpenPickTasksApi, + currentLocation.id, + action.payload?.excludeAssignedRequisitions + ); yield action.callback({ response }); yield put({ type: GET_OPEN_PICK_TASKS_REQUEST_SUCCESS, payload: response.data }); } catch (error) { diff --git a/src/screens/Picking/DiscretePickingListScreen.tsx b/src/screens/Picking/DiscretePickingListScreen.tsx index 5f46eb53..8d037117 100644 --- a/src/screens/Picking/DiscretePickingListScreen.tsx +++ b/src/screens/Picking/DiscretePickingListScreen.tsx @@ -11,6 +11,7 @@ import { navigate } from '../../NavigationService'; import { getOpenPickTasksAction } from '../../redux/actions/picking'; import { DiscretePickingOrder, PickTask } from '../../types/picking'; import { emptyStateMessage } from '../../utils/emptyStateMessage'; +import { ToggleRow } from '../Dashboard/ToggleRow'; import { DELIVERY_TYPES } from './constants'; import DiscretePickingCardSkeleton from './DiscretePickingCardSkeleton'; import DiscretePickingFilterSkeleton from './DiscretePickingFilterSkeleton'; @@ -33,18 +34,19 @@ export default function DiscretePickingListScreen() { const [tasks, setTasks] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const [selectedQueueType, setSelectedQueueType] = useState(ALL_QUEUE_TYPES); + const [excludeAssignedRequisitions, setExcludeAssignedRequisitions] = useState(true); const [isRefreshing, setIsRefreshing] = useState(false); const [isPullRefreshing, setIsPullRefreshing] = useState(false); const [hasLoaded, setHasLoaded] = useState(false); const fetchOrders = useCallback( - (fromPull = false) => { + (excludeAssignedRequisitionsParam: boolean, fromPull = false) => { setIsRefreshing(true); if (fromPull) { setIsPullRefreshing(true); } dispatch( - getOpenPickTasksAction(({ response, errorMessage }) => { + getOpenPickTasksAction(excludeAssignedRequisitionsParam, ({ response, errorMessage }) => { if (!errorMessage && response?.data) { setTasks(response.data); } @@ -59,8 +61,8 @@ export default function DiscretePickingListScreen() { useFocusEffect( useCallback(() => { - fetchOrders(); - }, [fetchOrders]) + fetchOrders(excludeAssignedRequisitions); + }, [fetchOrders, excludeAssignedRequisitions]) ); const sortedOrders = useMemo(() => sortOrders(groupTasksIntoOrders(tasks)), [tasks]); @@ -129,6 +131,15 @@ export default function DiscretePickingListScreen() { })} )} + {!isLoadingList && ( + + setExcludeAssignedRequisitions(!value)} + /> + + )} {isLoadingList ? ( @@ -137,7 +148,9 @@ export default function DiscretePickingListScreen() { order.requisitionId} - renderItem={({ item }) => } + renderItem={({ item }) => ( + + )} keyboardShouldPersistTaps="handled" keyboardDismissMode="on-drag" contentContainerStyle={styles.listContent} @@ -150,7 +163,7 @@ export default function DiscretePickingListScreen() { description={emptyStateMessage('orders', searchTerm, 'No open orders ready for picking')} /> } - onRefresh={() => fetchOrders(true)} + onRefresh={() => fetchOrders(excludeAssignedRequisitions, true)} /> )} diff --git a/src/screens/Picking/DiscretePickingOrderCard.tsx b/src/screens/Picking/DiscretePickingOrderCard.tsx index 993d0186..3eb2c4e2 100644 --- a/src/screens/Picking/DiscretePickingOrderCard.tsx +++ b/src/screens/Picking/DiscretePickingOrderCard.tsx @@ -24,6 +24,7 @@ export default function DiscretePickingOrderCard({ order, onPress }: Props) { ? DELIVERY_TYPE_LABELS[order.deliveryTypeCode] ?? order.deliveryTypeCode : null; const lineCountLabel = order.taskCount === 1 ? 'Line' : 'Lines'; + const assigneeName = order.assignee ? `${order.assignee.firstName} ${order.assignee.lastName}`.trim() : null; return ( onPress(order)}> @@ -75,6 +76,13 @@ export default function DiscretePickingOrderCard({ order, onPress }: Props) { {lineCountLabel}: {order.taskCount} + {assigneeName ? ( + + + Assigned to: {assigneeName} + + + ) : null} diff --git a/src/screens/Picking/discretePickingLib.ts b/src/screens/Picking/discretePickingLib.ts index 2383e7fb..70816d6c 100644 --- a/src/screens/Picking/discretePickingLib.ts +++ b/src/screens/Picking/discretePickingLib.ts @@ -39,6 +39,7 @@ export function groupTasksIntoOrders(tasks: PickTask[]): DiscretePickingOrder[] destination: task.destination, destinationLocationType: task.destinationLocationType, deliveryTypeCode: task.deliveryTypeCode, + assignee: task.assignee, priority: task.priority, taskCount: 0, inProgress: false, diff --git a/src/screens/Picking/discretePickingStyles.ts b/src/screens/Picking/discretePickingStyles.ts index 1f765672..1f6c0ea7 100644 --- a/src/screens/Picking/discretePickingStyles.ts +++ b/src/screens/Picking/discretePickingStyles.ts @@ -45,6 +45,9 @@ export default StyleSheet.create({ flexDirection: 'row', overflow: 'hidden' }, + showAssignedToggle: { + paddingHorizontal: Theme.spacing.medium + }, filterChipSkeleton: { height: 32, borderRadius: 12, diff --git a/src/types/picking.ts b/src/types/picking.ts index c7b7fda2..c1117ea2 100644 --- a/src/types/picking.ts +++ b/src/types/picking.ts @@ -83,6 +83,7 @@ export type DiscretePickingOrder = { destination?: string; destinationLocationType?: string; deliveryTypeCode?: DeliveryTypeCode; + assignee?: Person | null; /** requisition.priority (lower = higher priority) */ priority?: number; /** number of open pick tasks (line items) in this order */