diff --git a/components/AreaGroup.tsx b/components/AreaGroup.tsx index f0495e4..f469aa5 100644 --- a/components/AreaGroup.tsx +++ b/components/AreaGroup.tsx @@ -1,7 +1,7 @@ 'use client'; import { useState } from 'react'; -import { OrderItem } from '@/lib/types'; +import { OrderItem, isOutOfStock, problemBadgeLabel } from '@/lib/types'; import { cn } from '@/lib/utils'; import CollectionItemCard from '@/components/CollectionItemCard'; import { @@ -175,7 +175,14 @@ export default function AreaGroup({ return (
  • {getItemIcon(item)} @@ -190,8 +197,15 @@ export default function AreaGroup({ )}
    {item.problem_flag && ( - - Problem + + {problemBadgeLabel(item)} )} diff --git a/components/SupplierGroup.tsx b/components/SupplierGroup.tsx index 1e6c424..e067ebc 100644 --- a/components/SupplierGroup.tsx +++ b/components/SupplierGroup.tsx @@ -1,7 +1,7 @@ 'use client'; import { useState, useRef, useEffect, useCallback } from 'react'; -import { OrderItem, Supplier } from '@/lib/types'; +import { OrderItem, Supplier, isOutOfStock, problemBadgeLabel } from '@/lib/types'; import { cn, parseCoordinates } from '@/lib/utils'; import CollectionItemCard from '@/components/CollectionItemCard'; import { @@ -108,6 +108,10 @@ function CompactItemRow({
  • {item.problem_flag && ( - - Problem + + {problemBadgeLabel(item)} )} diff --git a/lib/types.ts b/lib/types.ts index 19cc0f3..50f066a 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -279,3 +279,50 @@ export const PROBLEM_TYPES = [ { value: 'wrong_item', label: 'Wrong Item' }, { value: 'other', label: 'Other' }, ] as const; + +/** + * Stored `problem_type` -> the word we show the driver. + * + * The union is wider than PROBLEM_TYPES on purpose. `problem_type` is a + * PB **select** on `order_items` whose allowed values are + * stock | supplier | driver | delivery | pricing | other + * plus the four PROBLEM_TYPES entries we added on 2026-10-14. On + * `stock_purchase_items` the same field is a plain **text** field, so + * anything can turn up there too. `collectionStatus`/`updateStockCollectionStatus` + * write `stock` on their own. A generic "Problem" pill told the driver + * nothing about which of these they were looking at — an out-of-stock + * item and a quality complaint need different follow-ups. + */ +export const PROBLEM_TYPE_LABELS: Record = { + out_of_stock: 'Out of stock', + partial_stock: 'Partial stock', + quality_issue: 'Quality issue', + wrong_item: 'Wrong item', + stock: 'Short / partial', + supplier: 'Supplier issue', + driver: 'Driver issue', + delivery: 'Delivery issue', + pricing: 'Pricing issue', + other: 'Other', +}; + +/** Badge text for a flagged item; falls back to the old generic label. */ +export const problemBadgeLabel = (item: { + problem_flag?: boolean | null; + problem_type?: string | null; +}): string => { + if (!item.problem_flag) return ''; + return PROBLEM_TYPE_LABELS[item.problem_type ?? ''] ?? 'Problem'; +}; + +/** + * True only for a flagged row the driver reported as out of stock. + * + * Deliberately narrow: `stock` (partial collection) and the other + * operator-side types do NOT qualify, because the driver can't clear + * those and they don't block a re-collection the same way. + */ +export const isOutOfStock = (item: { + problem_flag?: boolean | null; + problem_type?: string | null; +}): boolean => Boolean(item.problem_flag) && item.problem_type === 'out_of_stock';