From e900772faab61957e8bde474c7df7cb69eb52283 Mon Sep 17 00:00:00 2001 From: Mika Date: Wed, 26 Aug 2026 01:08:52 +0200 Subject: [PATCH] fix(delivery-notes): move 'Add item' to per-card button after each row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step A — move the 'Add item' button from the top of the items section to the bottom of the items list. Step B — match the quote-form.tsx pattern: every item card is followed by its own ghost + dashed-border 'Add another item' button, so the operator never has to scroll back to the top to add the next line. The dashed-border styling keeps it from being mistaken for a submit/finish affordance. The data-testid="dn-adhoc-add-item" selector is preserved on the per-card buttons so any future test selectors continue to work. Fixes PINW-18 --- .../delivery-notes/create-adhoc-dialog.tsx | 391 +++++++++--------- 1 file changed, 196 insertions(+), 195 deletions(-) diff --git a/src/components/delivery-notes/create-adhoc-dialog.tsx b/src/components/delivery-notes/create-adhoc-dialog.tsx index 4e78325..e2d1b37 100644 --- a/src/components/delivery-notes/create-adhoc-dialog.tsx +++ b/src/components/delivery-notes/create-adhoc-dialog.tsx @@ -1,9 +1,9 @@ "use client"; -import { useEffect, useState } from "react"; +import { Fragment, useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; -import { Box, Loader2, Package, Trash2 } from "lucide-react"; +import { Loader2, Package, Plus, Trash2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -365,216 +365,217 @@ export function CreateAdHocDeliveryNoteDialog({ open, onOpenChange }: Props) { selling. The description + quantity are always editable so the operator can override. */}
-
- - -
+
{items.map((it, idx) => ( -
-
-
- Item #{idx + 1} - {it.stock_item_id && ( - +
+
+
+ Item #{idx + 1} + {it.stock_item_id && ( + + + From stock + + )} + {it.priced_from_catalogue && ( + + Priced from catalogue + + )} +
+ {items.length > 1 && ( + )}
- {items.length > 1 && ( - - )} -
- {/* "Pick from stock" combobox. When the operator - picks an item, the row auto-fills. Leaving - this empty just means the operator types - freehand. */} -
- - void pickStockItem(idx, id)} - placeholder={ - loadingLookups - ? "Loading stock…" - : "Type a SKU or item name…" - } - disabled={loadingLookups || submitting} - /> -
- -
-
- - - updateItem(idx, { description: e.target.value }) - } - placeholder="e.g. 10x M8 bolts" - disabled={submitting} - /> -
+ {/* "Pick from stock" combobox. When the operator + picks an item, the row auto-fills. Leaving + this empty just means the operator types + freehand. */}
- - updateItem(idx, { quantity: e.target.value }) - } - type="number" - min="1" - step="1" - disabled={submitting} - /> -
-
- - updateItem(idx, { supplier: id })} + void pickStockItem(idx, id)} + placeholder={ + loadingLookups + ? "Loading stock…" + : "Type a SKU or item name…" + } disabled={loadingLookups || submitting} />
-
- - - updateItem(idx, { sku: e.target.value }) - } - placeholder="optional" - disabled={submitting} - /> -
-
- - - updateItem(idx, { cost_price: e.target.value }) - } - type="number" - step="0.01" - min="0" - placeholder="optional" - disabled={submitting} - /> -
-
- - - updateItem(idx, { selling_price: e.target.value }) - } - type="number" - step="0.01" - min="0" - placeholder="optional" - disabled={submitting} - /> -
-
- - - updateItem(idx, { notes: e.target.value }) - } - placeholder="optional" - disabled={submitting} - /> + +
+
+ + + updateItem(idx, { description: e.target.value }) + } + placeholder="e.g. 10x M8 bolts" + disabled={submitting} + /> +
+
+ + + updateItem(idx, { quantity: e.target.value }) + } + type="number" + min="1" + step="1" + disabled={submitting} + /> +
+
+ + updateItem(idx, { supplier: id })} + suppliers={suppliers} + placeholder="Pick supplier…" + disabled={loadingLookups || submitting} + /> +
+
+ + + updateItem(idx, { sku: e.target.value }) + } + placeholder="optional" + disabled={submitting} + /> +
+
+ + + updateItem(idx, { cost_price: e.target.value }) + } + type="number" + step="0.01" + min="0" + placeholder="optional" + disabled={submitting} + /> +
+
+ + + updateItem(idx, { selling_price: e.target.value }) + } + type="number" + step="0.01" + min="0" + placeholder="optional" + disabled={submitting} + /> +
+
+ + + updateItem(idx, { notes: e.target.value }) + } + placeholder="optional" + disabled={submitting} + /> +
-
+ + ))}