added print, download as pdf. no puppeteer, we'll see
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
# 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:
|
||||
|
||||
1. **Current Reading is a separate full-width block** (`.reading-display`) sitting
|
||||
*above* the card row, not part of it.
|
||||
2. **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**.
|
||||
3. **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](frontend/src/components/Main.jsx#L604-L605) 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):
|
||||
|
||||
```jsx
|
||||
<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](frontend/src/components/concepts/ScalesAppCyberpunk.css#L94)):
|
||||
|
||||
```css
|
||||
.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:
|
||||
```css
|
||||
@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 explicit `background: var(--surface)` and
|
||||
`color: var(--text)`. They currently inherit UA defaults and survive cockpit
|
||||
only by accident of `color-scheme: dark`.
|
||||
- `.extra-fields` — add `@media (max-width: 768px) { grid-template-columns: 1fr }`;
|
||||
it is a hard `1fr 1fr` at every width today.
|
||||
- `.vehicle-form-actions` — add `justify-content: flex-end` to match the
|
||||
`.manual-actions` precedent (Main.css:539+).
|
||||
|
||||
## Critical files
|
||||
|
||||
- [frontend/src/components/Main.jsx](frontend/src/components/Main.jsx) — lines
|
||||
581-741 replaced; `firstWeighing` memo (290-309) deleted
|
||||
- [frontend/src/components/Main.css](frontend/src/components/Main.css) —
|
||||
`.reading-display` block removed, `.weighing-section` → grid, `max-width` cap
|
||||
lifted, cockpit `:nth-child` → modifier classes, form rules
|
||||
- [frontend/src/components/concepts/ScalesAppCyberpunk.css](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](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
|
||||
|
||||
1. `cd frontend && npx vitest run` — 201 tests still pass
|
||||
2. 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
|
||||
3. Confirm the merged card still shows: `Disconnected` when the bridge is down,
|
||||
`Waiting...` when connected with no reading, and the balanced/unbalanced
|
||||
colour on a live value
|
||||
4. Widths 1400 / 1100 / 600px — grid collapses 4 → 2 → 1 with no overflow
|
||||
5. Cockpit chrome (clipped corner, lit top edge, Net glow) lands on the right
|
||||
cards after the `:nth-child` → modifier rewrite
|
||||
6. Create form: 2-col above 768px, 1-col below; Cancel/Create right-aligned;
|
||||
inputs readable in cockpit
|
||||
Reference in New Issue
Block a user