Commit Graph
4 Commits
Author SHA1 Message Date
tajniak81andClaude Opus 5 cc1dafa9f7 Cars: drag the tabs into order, and a lock for every arrangement
Two things, both about layouts you arrange by dragging.

A car's tab bar now takes a drag: the tabs reorder as the pointer crosses
them and the arrangement saves on drop — or on dragend, since a tab
released in the gap beside the bar never produces a drop and would
otherwise revert on the next load. Same native drag events as the garage
and the Information rows, so also pointer-only, and it needs write access.

The order belongs to the car, like the choice of which tabs show at all,
so everyone it is shared with sees the same bar. It is stored as the full
list of keys, hidden tabs included, so a tab switched off and back on
returns to where it was rather than to the end; a key the stored
arrangement doesn't mention — a tab added in a later release — follows
the arranged ones. Information is arrangeable although it cannot be
switched off, which is why the validation needs arrangeableCarTabs rather
than reusing hideableCarTabs; it is derived from that set so the two
cannot drift as tabs are added. tabOrder rides on the existing PUT
/api/cars/{id}/view, so a tab drag never has to resend what is hidden.
Where the page opens is unchanged: Information, wherever it now sits.

And a padlock in the sidebar, above the theme toggle, holds every
arrangement in the app still at once — the garage, a car's tabs, its
Information rows, the provider's readings. It is a guard against nudging
a layout while reading it, not a permission: it is the user's own setting
and says nothing about what anybody may edit, so locking hides your own
drag handles rather than stopping a co-owner rearranging a shared car.
Stored as dragLocked on the profile, like the theme it sits above, so a
locked account is still locked on the next device — where a folded
provider card stays one browser's reading habit. Unlocked by default, so
nothing changes until it is clicked, and while locked the grab cursor and
the drag hints go with the drag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:43:54 +02:00
tajniak81andClaude Opus 5 6191160f14 Cars: log what charging costs, and drag the provider readings
Three things, all on a car's page.

A Charging cost tab, which is the Fuel cost tab written for an electric
car: charges in kWh, consumption in kWh/100km beside km per kWh, cost per
km and price per kWh, and the same summary panel over the whole history.
It keeps the reference-point method too, and has to — a session records
the energy that went in, not what was left in the battery, so a given
number of kWh only maps to a distance between two charges that ended at
the same state. A charge to the car's usual full point plays the part of
the full tank; partial charges still count towards the cost and roll into
the next full one; and a charge taken without logging it leaves its
window uncomputed rather than reporting an implausibly good figure.
Sessions live in their own collection, the figures are derived on read
like the fuel ones, and logging a charge advances the odometer exactly as
a refill does. The tab switches off from the gear like every other, so a
petrol car need never see it.

The headline readings on the connected-service tab now drag into any
order, saved on drop. Stored on the car as metricOrder, like the
Information rows, rather than per device the way the collapsed cards are:
an arrangement is something everyone the car is shared with should see,
where a folded card is one browser's reading habit. Only what the
provider reported can be arranged, so a reading that turns up later joins
the end rather than displacing the arrangement.

Fuel is now Fuel cost, tab and heading, which is what the tab has always
been about and what pairs it with Charging cost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:17:52 +02:00
tajniak81andClaude Opus 5 bc798dae49 Cars: drag the Information rows into the order you want
The rows on a car's Information tab now take a drag: they reorder as the
pointer crosses them and the arrangement saves on drop — or on dragend,
since a row released in the gap between rows never produces a drop and
would otherwise revert on the next load. Same native drag events as the
garage, so also pointer-only, and it needs write access.

The order belongs to the car, like the choice of which rows show at all,
so everyone it is shared with sees the same page. It is stored as the
full list of the 14 keys, hidden rows included: a row switched off and
back on returns to where it was rather than to the end. A key the stored
arrangement doesn't mention — a row added in a later release — follows
the arranged ones, the same rule the garage uses for a car added since
the last drag.

fieldOrder rides on the existing PUT /api/cars/{id}/view, which writes
only the lists it is given, so a drag never has to resend what is hidden.
A partial arrangement is accepted; an invented key is still a 400, which
is why normalizeHidden is now normalizeKeys — it validates an order as
well as a switched-off set.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 20:52:21 +02:00
tajniak81andClaude Opus 5 049da69c83 Cars: arrange the garage, and choose what a car's page shows
Three things you can now set up rather than live with.

The garage takes a drag: cards reorder as you drag across them and the
arrangement saves on drop — or on dragend, since a card released in the
gap between cards never produces a drop and would otherwise revert on
the next load. It is a per-user list of car ids on the profile, so it
covers cars shared with you and never reorders anybody else's garage;
the API returns /api/cars in that order, so a client only sends the new
one back. Pointer-only: touch browsers don't fire the native drag
events, and this is not worth a dependency.

A car's page is now configurable from the gear in its header: which tabs
it shows, and which of the 14 Information rows. Both belong to the car,
so everyone it is shared with sees the same page — Fuel off on an EV
stays off for all of them — and setting them needs write access. Stored
as the hidden sets, so anything added in a later release is on by
default. PUT /api/cars/{id}/view is its own endpoint precisely so an
ordinary save of the car form, which sends every other field, can never
reveal something that was deliberately switched off. Information itself
can't be hidden: a page with no tabs left would be a dead end.

The connected-service cards fold away, remembered per device, so a
provider that reports eight sections can be trimmed to the two worth
watching. A failed section keeps a short badge in its collapsed header
and puts the provider's own message — a few hundred characters of JSON,
which used to stretch the page sideways — inside the body with
everything else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 20:29:23 +02:00