From 96207d00961b202a112fe1878faffef2fed11976 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Wed, 9 Sep 2026 11:12:24 +0200 Subject: [PATCH] feat: mirror the new backend numeric bounds as HTML min/max on inputs The previous two commits added @Min(0)/@Max(100) validation and a sign-inversion guard on the backend, but the number inputs themselves had no min/max attributes - a user could still type a negative weight, quantity, or an out-of-range percentage and only find out via a generic "failed" toast after submitting, with no indication of why. Added min={0} (and max={100} on water-content percentages) to every input for a field the backend now bounds: harvest weights/super count, honey-batch amount/water content, honey measurements, feeding amount, extraction amount/water content, stock item quantity/min threshold, and varroa mite count/duration/calculated value - across both the create and edit form for each. The stock-movement quantity input is the one exception requiring care: min is only applied when type !== "ADJUSTMENT", matching the backend guard, since a correction movement must still be allowed to go negative. Added a short explanatory line under that field too. Co-Authored-By: Claude Sonnet 5 --- .../src/app/(app)/colonies/[id]/feeding-edit-dialog.tsx | 1 + .../src/app/(app)/colonies/[id]/varroa-edit-dialog.tsx | 3 +++ .../app/(app)/extractions/[id]/extraction-edit-dialog.tsx | 3 +++ ApiCore-Frontend/src/app/(app)/extractions/new/page.tsx | 3 +++ ApiCore-Frontend/src/app/(app)/feedings/new/page.tsx | 1 + .../src/app/(app)/harvests/[id]/harvest-edit-dialog.tsx | 3 +++ ApiCore-Frontend/src/app/(app)/harvests/new/page.tsx | 3 +++ .../app/(app)/honey-batches/[id]/add-measurement-dialog.tsx | 2 ++ .../app/(app)/honey-batches/[id]/extraction-edit-dialog.tsx | 3 +++ .../app/(app)/honey-batches/[id]/honey-batch-edit-dialog.tsx | 3 +++ .../src/app/(app)/storage/create-stock-item-dialog.tsx | 1 + .../src/app/(app)/storage/edit-stock-item-dialog.tsx | 1 + .../src/app/(app)/storage/record-movement-dialog.tsx | 5 +++++ ApiCore-Frontend/src/app/(app)/varroa/new/page.tsx | 2 ++ 14 files changed, 34 insertions(+) diff --git a/ApiCore-Frontend/src/app/(app)/colonies/[id]/feeding-edit-dialog.tsx b/ApiCore-Frontend/src/app/(app)/colonies/[id]/feeding-edit-dialog.tsx index 19821b6..5bd3301 100644 --- a/ApiCore-Frontend/src/app/(app)/colonies/[id]/feeding-edit-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/colonies/[id]/feeding-edit-dialog.tsx @@ -108,6 +108,7 @@ export function FeedingEditDialog({ feeding }: { feeding: Feeding }) { setAmount(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/colonies/[id]/varroa-edit-dialog.tsx b/ApiCore-Frontend/src/app/(app)/colonies/[id]/varroa-edit-dialog.tsx index d430fad..503a340 100644 --- a/ApiCore-Frontend/src/app/(app)/colonies/[id]/varroa-edit-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/colonies/[id]/varroa-edit-dialog.tsx @@ -111,6 +111,7 @@ export function VarroaEditDialog({ measurement }: { measurement: VarroaMeasureme setMiteCount(event.target.value)} /> @@ -120,6 +121,7 @@ export function VarroaEditDialog({ measurement }: { measurement: VarroaMeasureme setDurationMinutes(event.target.value)} /> @@ -130,6 +132,7 @@ export function VarroaEditDialog({ measurement }: { measurement: VarroaMeasureme id="varroa-edit-calculated" type="number" step="0.1" + min={0} value={calculatedValue} onChange={(event) => setCalculatedValue(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/extractions/[id]/extraction-edit-dialog.tsx b/ApiCore-Frontend/src/app/(app)/extractions/[id]/extraction-edit-dialog.tsx index b449004..0263e06 100644 --- a/ApiCore-Frontend/src/app/(app)/extractions/[id]/extraction-edit-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/extractions/[id]/extraction-edit-dialog.tsx @@ -78,6 +78,7 @@ export function ExtractionEditDialog({ extraction }: { extraction: Extraction }) setAmount(event.target.value)} /> @@ -97,6 +98,8 @@ export function ExtractionEditDialog({ extraction }: { extraction: Extraction }) setWaterContent(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/extractions/new/page.tsx b/ApiCore-Frontend/src/app/(app)/extractions/new/page.tsx index f0e7966..ef9f2b7 100644 --- a/ApiCore-Frontend/src/app/(app)/extractions/new/page.tsx +++ b/ApiCore-Frontend/src/app/(app)/extractions/new/page.tsx @@ -123,6 +123,7 @@ export default function NewExtractionPage() { id="extraction-amount" type="number" inputMode="decimal" + min={0} className="h-11" value={amount} onChange={(event) => setAmount(event.target.value)} @@ -143,6 +144,8 @@ export default function NewExtractionPage() { id="extraction-water" type="number" inputMode="decimal" + min={0} + max={100} className="h-11" value={waterContent} onChange={(event) => setWaterContent(event.target.value)} diff --git a/ApiCore-Frontend/src/app/(app)/feedings/new/page.tsx b/ApiCore-Frontend/src/app/(app)/feedings/new/page.tsx index db958bd..1a10c49 100644 --- a/ApiCore-Frontend/src/app/(app)/feedings/new/page.tsx +++ b/ApiCore-Frontend/src/app/(app)/feedings/new/page.tsx @@ -158,6 +158,7 @@ export default function NewFeedingPage() { id="feeding-amount" type="number" inputMode="decimal" + min={0} required className="h-11" value={amount} diff --git a/ApiCore-Frontend/src/app/(app)/harvests/[id]/harvest-edit-dialog.tsx b/ApiCore-Frontend/src/app/(app)/harvests/[id]/harvest-edit-dialog.tsx index 13b5e2f..15021d3 100644 --- a/ApiCore-Frontend/src/app/(app)/harvests/[id]/harvest-edit-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/harvests/[id]/harvest-edit-dialog.tsx @@ -88,6 +88,7 @@ export function HarvestEditDialog({ harvest }: { harvest: Harvest }) { setGrossWeight(event.target.value)} /> @@ -97,6 +98,7 @@ export function HarvestEditDialog({ harvest }: { harvest: Harvest }) { setNetWeight(event.target.value)} /> @@ -106,6 +108,7 @@ export function HarvestEditDialog({ harvest }: { harvest: Harvest }) { setHoneySuperCount(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/harvests/new/page.tsx b/ApiCore-Frontend/src/app/(app)/harvests/new/page.tsx index 2cc402d..76aa604 100644 --- a/ApiCore-Frontend/src/app/(app)/harvests/new/page.tsx +++ b/ApiCore-Frontend/src/app/(app)/harvests/new/page.tsx @@ -202,6 +202,7 @@ export default function NewHarvestPage() { id="harvest-super-count" type="number" inputMode="numeric" + min={0} className="h-11" value={honeySuperCount} onChange={(event) => setHoneySuperCount(event.target.value)} @@ -213,6 +214,7 @@ export default function NewHarvestPage() { id="harvest-gross-weight" type="number" inputMode="decimal" + min={0} className="h-11" value={grossWeight} onChange={(event) => setGrossWeight(event.target.value)} @@ -224,6 +226,7 @@ export default function NewHarvestPage() { id="harvest-net-weight" type="number" inputMode="decimal" + min={0} className="h-11" value={netWeight} onChange={(event) => setNetWeight(event.target.value)} diff --git a/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/add-measurement-dialog.tsx b/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/add-measurement-dialog.tsx index d8fd8cc..7c86ad6 100644 --- a/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/add-measurement-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/add-measurement-dialog.tsx @@ -70,6 +70,8 @@ export function AddMeasurementDialog({ honeyBatchId }: { honeyBatchId: string }) id="measurement-water" type="number" inputMode="decimal" + min={0} + max={100} required value={waterContent} onChange={(event) => setWaterContent(event.target.value)} diff --git a/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/extraction-edit-dialog.tsx b/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/extraction-edit-dialog.tsx index eb99369..a53d1de 100644 --- a/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/extraction-edit-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/extraction-edit-dialog.tsx @@ -77,6 +77,7 @@ function ExtractionEditForm({ setAmount(event.target.value)} /> @@ -96,6 +97,8 @@ function ExtractionEditForm({ id="extraction-edit-water" type="number" step="0.1" + min={0} + max={100} value={waterContent} onChange={(event) => setWaterContent(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/honey-batch-edit-dialog.tsx b/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/honey-batch-edit-dialog.tsx index 7a72095..a019839 100644 --- a/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/honey-batch-edit-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/honey-batches/[id]/honey-batch-edit-dialog.tsx @@ -72,6 +72,7 @@ export function HoneyBatchEditDialog({ honeyBatch }: { honeyBatch: HoneyBatch }) id="batch-edit-amount" type="number" inputMode="decimal" + min={0} value={amount} onChange={(event) => setAmount(event.target.value)} /> @@ -82,6 +83,8 @@ export function HoneyBatchEditDialog({ honeyBatch }: { honeyBatch: HoneyBatch }) id="batch-edit-water" type="number" step="0.1" + min={0} + max={100} value={waterContent} onChange={(event) => setWaterContent(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/storage/create-stock-item-dialog.tsx b/ApiCore-Frontend/src/app/(app)/storage/create-stock-item-dialog.tsx index b3aae4d..5d6e1c8 100644 --- a/ApiCore-Frontend/src/app/(app)/storage/create-stock-item-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/storage/create-stock-item-dialog.tsx @@ -109,6 +109,7 @@ export function CreateStockItemDialog() { id="item-quantity" type="number" inputMode="decimal" + min={0} value={quantity} onChange={(event) => setQuantity(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/storage/edit-stock-item-dialog.tsx b/ApiCore-Frontend/src/app/(app)/storage/edit-stock-item-dialog.tsx index b11a8cb..7515a87 100644 --- a/ApiCore-Frontend/src/app/(app)/storage/edit-stock-item-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/storage/edit-stock-item-dialog.tsx @@ -112,6 +112,7 @@ export function EditStockItemDialog({ item }: { item: StockItem }) { id="item-edit-min-threshold" type="number" inputMode="decimal" + min={0} value={minThreshold} onChange={(event) => setMinThreshold(event.target.value)} /> diff --git a/ApiCore-Frontend/src/app/(app)/storage/record-movement-dialog.tsx b/ApiCore-Frontend/src/app/(app)/storage/record-movement-dialog.tsx index 03f704d..9e4783d 100644 --- a/ApiCore-Frontend/src/app/(app)/storage/record-movement-dialog.tsx +++ b/ApiCore-Frontend/src/app/(app)/storage/record-movement-dialog.tsx @@ -87,10 +87,15 @@ export function RecordMovementDialog({ stockItemId }: { stockItemId: string }) { id="movement-quantity" type="number" inputMode="decimal" + min={type === "ADJUSTMENT" ? undefined : 0} required value={quantity} onChange={(event) => setQuantity(event.target.value)} /> +

+ Bei Eingang/Ausgang/Umlagerung immer positiv angeben - die Richtung ergibt sich aus + der Art. Nur bei Korrektur ist ein negativer Wert möglich. +

{error ? (

diff --git a/ApiCore-Frontend/src/app/(app)/varroa/new/page.tsx b/ApiCore-Frontend/src/app/(app)/varroa/new/page.tsx index 64f6f71..d124442 100644 --- a/ApiCore-Frontend/src/app/(app)/varroa/new/page.tsx +++ b/ApiCore-Frontend/src/app/(app)/varroa/new/page.tsx @@ -149,6 +149,7 @@ export default function NewVarroaMeasurementPage() { id="varroa-mite-count" type="number" inputMode="numeric" + min={0} className="h-11" value={miteCount} onChange={(event) => setMiteCount(event.target.value)} @@ -160,6 +161,7 @@ export default function NewVarroaMeasurementPage() { id="varroa-duration" type="number" inputMode="numeric" + min={0} className="h-11" value={durationMinutes} onChange={(event) => setDurationMinutes(event.target.value)}