mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-06 14:45:04 +00:00
feat(warehouses): backoffice UI for container stack positions
Surfaces the physical stack/slot model in the staff app. - ZoneLayoutModal: stacks drawn level by level with occupancy colours, configured-vs-built-vs-occupied counts, and stack create/delete plus block/reserve/free on empty levels - SlotPicker in the store and move modals, offering only the next fillable level of each stack so the form cannot suggest a position the API will refuse - move modal warns when a container is buried, lists the blockers, and disables the action instead of firing a 409 - fix: move() now asserts accessibility server-side, matching release — both are exits from a stack
This commit is contained in:
@@ -118,6 +118,7 @@ const blockNegative = (event: KeyboardEvent<HTMLInputElement>) => {
|
||||
|
||||
interface UnitErrors {
|
||||
containerNumber?: string;
|
||||
sealNumber?: string;
|
||||
vgmTons?: string;
|
||||
}
|
||||
|
||||
@@ -886,6 +887,9 @@ export default function GlCreateBookingForm() {
|
||||
} else if ((numberCounts.get(key) ?? 0) > 1) {
|
||||
errs.containerNumber = "Duplicate container number in this shipment.";
|
||||
}
|
||||
if (u.sealNumber.trim() === "") {
|
||||
errs.sealNumber = "Seal number is required.";
|
||||
}
|
||||
const vgm = Number(u.vgmTons);
|
||||
if (u.vgmTons.trim() === "" || Number.isNaN(vgm) || vgm <= 0) {
|
||||
errs.vgmTons = "Enter a valid VGM.";
|
||||
@@ -1185,7 +1189,7 @@ export default function GlCreateBookingForm() {
|
||||
: {}),
|
||||
units: l.units.map((u) => ({
|
||||
containerNumber: u.containerNumber.trim().toUpperCase(),
|
||||
...(u.sealNumber ? { sealNumber: u.sealNumber } : {}),
|
||||
sealNumber: u.sealNumber.trim(),
|
||||
vgmTons: Number(u.vgmTons) || 0,
|
||||
// Per-container handling — the server rolls these into the line
|
||||
// counts and bills each surcharge on the ticked containers only.
|
||||
@@ -1247,7 +1251,7 @@ export default function GlCreateBookingForm() {
|
||||
reeferQuantity: Number(l.reeferQuantity || 0) || undefined,
|
||||
units: l.units.map((u) => ({
|
||||
containerNumber: u.containerNumber.trim().toUpperCase(),
|
||||
...(u.sealNumber ? { sealNumber: u.sealNumber } : {}),
|
||||
sealNumber: u.sealNumber.trim(),
|
||||
vgmTons: Number(u.vgmTons) || 0,
|
||||
isHazardous: Boolean(u.isHazardous),
|
||||
isReefer: Boolean(u.isReefer),
|
||||
@@ -1857,7 +1861,7 @@ export default function GlCreateBookingForm() {
|
||||
Container number *
|
||||
</Text>
|
||||
<Text fz={12} fw={600} c="#10202F" style={{ flex: 1 }}>
|
||||
Seal number
|
||||
Seal number *
|
||||
</Text>
|
||||
<Text fz={12} fw={600} c="#10202F" style={{ flex: 1 }}>
|
||||
VGM (tons) *
|
||||
@@ -1901,8 +1905,13 @@ export default function GlCreateBookingForm() {
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Optional"
|
||||
placeholder="e.g. SL-0099231"
|
||||
value={unit.sealNumber}
|
||||
error={
|
||||
showErrors
|
||||
? unitErrors[lineIdx]?.[unitIdx]?.sealNumber
|
||||
: undefined
|
||||
}
|
||||
onChange={(e) =>
|
||||
patchUnit(lineIdx, unitIdx, {
|
||||
sealNumber: e.currentTarget.value,
|
||||
|
||||
Reference in New Issue
Block a user