3 Commits (main)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
57c6912987 |
Say that a click landed, and make moving one actually move it
tests / pest (push) Failing after 7m52s
Details
tests / assets (push) Successful in 20s
Details
tests / release (push) Has been skipped
Details
"Man klickt und sieht nicht was passiert." Every action in this console is a round trip, and a round trip with no sign of itself reads as a click that missed — so the answer is in three places, from the general to the specific. A thin bar at the top of the window for any Livewire request, in app.js. Delayed by 140 ms, because a request that answers faster than that is perceived as immediate and a bar flashing on every keystroke of a .live field is worse than none. It creeps to 70 % and only completes on the answer: a bar that reaches the end while the answer is still on its way is a lie about the thing it exists to report. Released on failure as well — the request somebody must not be left waiting on is precisely the one that went wrong — and on wire:navigate, which is not a request hook at all and would otherwise leave the bar behind on a page that is gone. Per button: a pressed state on the way down, disabled while its own request is out, scoped with wire:target to that button's own call so a row does not grey itself out because a neighbour is moving. The edit button carries its own spinner, because opening the modal is a request made by the MODAL component — wire:loading on this page never sees it. It clears when the package announces the modal is up, and on a six second timer as well, so a request that never answers cannot leave a row spinning for ever. And the reordering was not only slow to look at, it was wrong. It added or subtracted a fixed amount: with the seeded values ten apart that usually landed right, and sometimes landed on a value another template already had — or on the floor along with three others. Equal sort values fall back to the name, so a click could reorder something else, or nothing, which is indistinguishable from a click that never registered. It swaps with the neighbour now: exactly one place, or nothing at the ends, both of which are what an operator expects to see. Where two shared a value the swap leaves them distinct, or the next click would do nothing again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
|
|
|
173f05c1bd |
Fix a cancel button that did nothing, and fit the answers on one screen
tests / pest (push) Failing after 10m22s
Details
tests / assets (push) Successful in 20s
Details
tests / release (push) Has been skipped
Details
The cancel button on the template modal was written with Alpine's
$dispatch, which fires a browser DOM event — and wire-elements/modal
listens for a LIVEWIRE event of that name. So it did nothing at all, while
saving worked, which is the combination that makes somebody click twice and
then close the tab. Every other modal in the repo already used
Livewire.dispatch; this one was the odd one out, and nothing would have
caught it, so there is now a scan that fails on the Alpine form. Narrowed
to Alpine handlers deliberately: wire:click="$dispatch('closeModal')" IS
Livewire's own dispatcher and works.
The list was one column of thirteen entries, each carrying a name, a
subject, two clamped lines of body and two full-width buttons — four
screens to find the one you want, with the body preview taking most of the
height while being the least useful part of it. The whole text is one click
away in the modal.
Now: two columns of one-line entries — name and subject, which is what
tells two similar answers apart — with the actions as icons that do not
compete with the name. The create form is folded away behind the button
that creates one, because a form that is always open is a screen of form
between the operator and the thing they came for. And the placeholder list
runs as a grid across the page instead of a tall sidebar that squeezed the
entries into half the window.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
|
|
33566cd404 |
Show the customer, and write the answers once
tests / pest (push) Failing after 9m49s
Details
tests / assets (push) Successful in 21s
Details
tests / release (push) Has been skipped
Details
Two complaints, one cause: the customer page was a compose box with three
lists under it. It showed nothing ABOUT the customer, and every answer was
typed from scratch.
The page is five tabs now. Stammdaten — contact, phone, since when,
language, and the tax standing: consumer or business, with "nobody asked"
saying so rather than passing for business, because that answer decides
whether a withdrawal right exists at all. Paket — the contract's own
FROZEN figures, the modules at the price they were booked at, and the
machine: address, state, host, datacenter. Zahlungen — invoices with net,
gross and their PDF, and the orders beside them, because an order is a
purchase and an invoice is a document about one. Nachrichten — the portal
requests in the customer's own words, the mail they sent, the mail we
sent. Schreiben — last, because it is what you do after reading.
The tab is in the query string, like Settings and Integrations: a reload,
a bookmark and the back button all land where the operator was, and a link
can point at the tab that matters.
And templates, under Betrieb → E-Mail-Vorlagen. Most customer questions
are the same five questions, and typing the answer again every time is how
two customers get told two different things about one subject. A template
is INSERTED into the compose field with the customer's own details filled
in — never sent as it stands, because the last two sentences always belong
to the person asking. What goes out is what the operator saw and edited.
Three decisions worth naming. {{contact}} takes the contact person where
one is on record and the company name otherwise, because "Guten Tag
Beispiel GmbH" is the line that gives away a mail written by a database.
{{amount}} is the gross figure — what the price sheet quoted them and what
their bank statement says. And a typo comes out as {{kunde}}, standing
there in the field where the operator sees it, rather than as an empty
string that produces "Guten Tag ,". A placeholder with no value for this
customer stays empty; nothing is invented.
Placeholders are named in English because they are identifiers, not prose:
a template has to survive somebody switching the console's language. The
list the page documents is the renderer's own, so a token added in one
place appears in the other without being written down twice.
Blade's echo tag ends at the first }} it finds, which turned a literal
placeholder in the documentation into compiled nonsense. Assembled in PHP
now, and caught by the test that renders the page rather than by somebody
opening it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|