7.5 KiB
Main page: 5-group weighing row + form restyle
Context
The weighing detail panel doesn't match the layout the user wants (reference screenshot: a single row of five groups — CURRENT READING | TARE | GROSS | NET | actions). Three things differ today:
- Current Reading is a separate full-width block (
.reading-display) sitting above the card row, not part of it. - There is a redundant "Scale" card duplicating the same live weight, which exists only to host the Measure / Manual entry buttons. The user's call: these two are the same thing — merge into one card.
- Tare and Gross are all-or-nothing. Today a lone first reading renders as a single neutral "First weighing" card, and Tare/Gross only appear once both exist. The user wants the five groups always visible, with the first reading shown plainly in its slot.
Result: a stable five-column row that never changes its column count.
The one behaviour being deliberately traded away
Main.jsx:604-605 documents why the
merged card exists: the backend parks a lone reading in tare, but a lighter
second reading moves it to gross. So a single reading labelled "TARE" can
later jump to the GROSS box. The user chose "show it plainly" — accepting that
jump. firstWeighing (Main.jsx:290-309) becomes dead and is removed.
Approach
1. Merge Current Reading + Scale into one card
Delete the standalone .reading-display block (Main.jsx:581-600) and the Scale
card (647-677). One card takes their place as the row's first column, keeping the
richer of the two behaviours — the reading-display value logic, which the
Scale card lacked (disconnected state, readingError line):
<div className="weight-card weight-card--reading">
<div className="weight-card-header">Current Reading</div>
<div className={`weight-card-value weight-card-value--reading ${…same ternary as today's reading-value…}`}>
{currentWeight !== null && !isNaN(currentWeight)
? `${currentWeight} kg`
: (isConnected ? 'Waiting...' : 'Disconnected')}
</div>
{isConnected && readingError && latestReading && (
<div className="reading-error" title={latestReading.data}>{readingError}</div>
)}
{canMeasure && !isFinalized && (<>
<button className="weight-set-btn" onClick={handleMeasure}
disabled={currentWeight === null || isNaN(currentWeight) || !licenseAllowed}
title={licenseAllowed ? undefined : licenseDetail}>Measure</button>
{!licenseAllowed && <div className="weight-license-block">{licenseDetail}</div>}
{currentUser?.can_manually_measure && (
<button className="weight-manual-btn" onClick={…}>Manual entry</button>
)}
</>)}
</div>
Keep the .reading-value--balanced/--unbalanced class names on the value so the
existing colour rules (Main.css:547-553) and cockpit glow keep applying
unchanged. The --reading modifier carries the larger font that
.reading-value had.
2. Tare / Gross / Net always render
Replace the ternary at Main.jsx:606-644 with three unconditional cards. Each
shows — and no meta when its value is null:
- Tare —
selectedVehicle.tare,tare_date,tare_user_name,tare_manual - Gross — same shape with
gross_* - Net —
netWeight(null until both exist)
Add modifier classes weight-card--tare, --gross (Net already has --net).
This is a prerequisite, not polish: Main.css:576-578 states the cockpit rules
use :nth-child precisely because these cards have no distinguishing class, and
the column count is about to change. Those :nth-child selectors must be
rewritten to the modifiers in the same pass or cockpit chrome lands on the wrong
cards.
Net keeps Print Notice + the Design Notice split button inside it (unchanged
markup, including the dropdown menu and backdrop). Gate them on netWeight !== null so an empty Net card shows no dead buttons.
3. Row becomes a grid
.weighing-section moves from flex + flex-wrap to a 5-column grid, following
the ratio proven in the concept file
(ScalesAppCyberpunk.css:94):
.weighing-section {
display: grid;
grid-template-columns: 1.3fr 1fr 1fr 1fr;
gap: 16px;
margin-bottom: 24px;
align-items: stretch;
}
Four columns, because Print/Design stay inside Net rather than becoming a separate action column — the user kept them there. Reading gets the wider track.
Remove .reading-display's margin-bottom: 20px block along with the element.
Lift .vehicle-detail { max-width: 700px } (Main.css:115) — four readouts do not
fit in 700px. The cockpit override at 851-853 that already does this then becomes
redundant and should go.
Responsive, replacing the cockpit-only @media (max-width:1150px) rule:
@media (max-width: 1150px) { .weighing-section { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .weighing-section { grid-template-columns: 1fr; } }
These apply to both themes now, so drop the [data-theme="cockpit"] prefix
from the wrap rules at 858-872.
4. Form restyle (styling only, no new capability)
Confirmed scope: the create form only. There is no edit form and none is being added. In Main.css:
.extra-field input/select— set explicitbackground: var(--surface)andcolor: var(--text). They currently inherit UA defaults and survive cockpit only by accident ofcolor-scheme: dark..extra-fields— add@media (max-width: 768px) { grid-template-columns: 1fr }; it is a hard1fr 1frat every width today..vehicle-form-actions— addjustify-content: flex-endto match the.manual-actionsprecedent (Main.css:539+).
Critical files
- frontend/src/components/Main.jsx — lines
581-741 replaced;
firstWeighingmemo (290-309) deleted - frontend/src/components/Main.css —
.reading-displayblock removed,.weighing-section→ grid,max-widthcap lifted, cockpit:nth-child→ modifier classes, form rules - frontend/src/components/concepts/ScalesAppCyberpunk.css
— reference only, not modified. Its hardcoded hex and
var(--cyan)/var(--green)must not be copied; translate to the semantic tokens in frontend/src/styles/tokens.css (--accent,--success). tokens.css is semantic-by-rule (header comment, lines 5-9).
No backend, serializer or API change. No new dependency.
Verification
cd frontend && npx vitest run— 201 tests still pass- Browser check at http://localhost:5172, both themes via the header toggle,
walking the full weighing lifecycle on one vehicle:
- no vehicle selected → placeholder unchanged
- fresh vehicle, no readings → 4 cards, all
—, no dead buttons - after first Measure → value appears in TARE, Gross/Net still
— - after second Measure → Tare+Gross+Net populated, Measure button gone, Print/Design appear in Net
- Confirm the merged card still shows:
Disconnectedwhen the bridge is down,Waiting...when connected with no reading, and the balanced/unbalanced colour on a live value - Widths 1400 / 1100 / 600px — grid collapses 4 → 2 → 1 with no overflow
- Cockpit chrome (clipped corner, lit top edge, Net glow) lands on the right
cards after the
:nth-child→ modifier rewrite - Create form: 2-col above 768px, 1-col below; Cancel/Create right-aligned; inputs readable in cockpit