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';