Archived
The ported markup was written a page at a time, so the same thing was said several ways. Counted before touching anything: nine variants of the page gutter, seven max-widths, six link styles, two definitions of an input, and one stray shadow. Now: `container` (which already centres and pads), `measure`/`measure-wide`, `link`/`link-plain`/ `link-on-dark`, one `field`, `photo`, `page-head`. Nothing in a template writes `bg-white rounded-… shadow-…` or `underline underline-offset-4` any more — 119 uses of `panel`, 82 of `label`, 52 of `panel-lift`, 17 of `link`. TWO REAL FIXES FELL OUT OF IT, not just tidying: - Every section said `container mx-auto px-4`: `mx-auto` twice, and a px-4 that beat the responsive padding inside `container`. The gutter was 16px at every width, including on a 27-inch screen. Removing the copy-paste restores sm:px-6 lg:px-8, which is most of why the pages now breathe. - The public form and the admin had grown two different inputs — cream vs white, ring-2 vs ring-1, py-2.5 vs py-2, and different text sizes. There is one `field` now, and the same focus ring as everything else. The admin uses the same names where they are the same thing (`link`, `field`, `h4`, `--radius-*`) and keeps its own denser buttons, because it is a tool and not a shop front. 53 tests green. Every class used across all nine pages resolves in the compiled stylesheet — that check is what makes a sweep this size safe to do with a script.
86 lines
4.0 KiB
HTML
86 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" xmlns:th="http://www.thymeleaf.org"
|
|
th:replace="~{admin/layout :: page('Goodie boxes & catering', ~{::content})}">
|
|
<body>
|
|
<div th:fragment="content">
|
|
|
|
<section>
|
|
<h2 class="card-heading">The price tables</h2>
|
|
<p class="mt-1 text-sm text-bakery-600">
|
|
In the order they appear on the page. Open one to change its columns, its prices or what's in it.
|
|
A table with no columns or no lines stays off the public page until it has both.
|
|
</p>
|
|
|
|
<ul class="mt-3 space-y-3">
|
|
<li th:each="table, t : ${menu.packages}" class="card flex flex-wrap items-center gap-3">
|
|
<div class="flex gap-1">
|
|
<form method="post" th:action="@{/admin/catering/tables/{id}/move(id=${table.id})}">
|
|
<input type="hidden" name="by" value="-1">
|
|
<button type="submit" class="btn-icon" th:disabled="${t.first}"
|
|
th:aria-label="|Move the ${table.name} table up|">↑</button>
|
|
</form>
|
|
<form method="post" th:action="@{/admin/catering/tables/{id}/move(id=${table.id})}">
|
|
<input type="hidden" name="by" value="1">
|
|
<button type="submit" class="btn-icon" th:disabled="${t.last}"
|
|
th:aria-label="|Move the ${table.name} table down|">↓</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="flex-1 min-w-60">
|
|
<a th:href="@{/admin/catering/tables/{id}(id=${table.id})}"
|
|
class="link h4 text-bakery-900"
|
|
th:text="${table.name}">Office</a>
|
|
<p class="text-sm text-bakery-600">
|
|
<span th:text="|${#lists.size(table.tiers)} column${#lists.size(table.tiers) == 1 ? '' : 's'}|">3 columns</span>,
|
|
<span th:text="|${#lists.size(table.rows)} line${#lists.size(table.rows) == 1 ? '' : 's'}|">3 lines</span>
|
|
<span th:if="${#lists.isEmpty(table.tiers) or #lists.isEmpty(table.rows)}"
|
|
class="text-bakery-700"> — not on the page yet</span>
|
|
</p>
|
|
</div>
|
|
|
|
<a th:href="@{/admin/catering/tables/{id}(id=${table.id})}" class="btn-secondary">Edit</a>
|
|
|
|
<form method="post" th:action="@{/admin/catering/tables/{id}/delete(id=${table.id})}">
|
|
<button type="submit" class="btn-danger"
|
|
th:aria-label="|Delete the ${table.name} table|">Delete</button>
|
|
</form>
|
|
</li>
|
|
</ul>
|
|
|
|
<p th:if="${#lists.isEmpty(menu.packages)}" class="mt-3 text-bakery-600">
|
|
No tables yet. The catering page will tell people to call instead until there is one.
|
|
</p>
|
|
|
|
<form method="post" action="/admin/catering/tables" class="mt-4 flex gap-2">
|
|
<label class="flex-1">
|
|
<span class="sr-only">New table</span>
|
|
<input class="field" name="name" placeholder="New table, e.g. Graduation parties" required>
|
|
</label>
|
|
<button type="submit" class="btn-primary">Add</button>
|
|
</form>
|
|
</section>
|
|
|
|
<!--/* The page's own terms, as opposed to the small print under one table. Replaced as a whole list:
|
|
deleting one is an omission, which is the same rule the tables follow. */-->
|
|
<section class="card">
|
|
<h2 class="card-heading">Under the whole page</h2>
|
|
<p class="mt-1 text-sm text-bakery-600">Terms that apply whichever table someone is reading.</p>
|
|
|
|
<form method="post" action="/admin/catering/notes" class="mt-3 space-y-2">
|
|
<label th:each="note : ${menu.notes}" class="block">
|
|
<span class="sr-only">Note</span>
|
|
<textarea class="field min-h-[3.25rem]" rows="2" name="notes" th:text="${note}"></textarea>
|
|
</label>
|
|
<!--/* An empty box is how you delete one: blank notes are dropped on save. */-->
|
|
<label class="block">
|
|
<span class="sr-only">Another note</span>
|
|
<textarea class="field min-h-[3.25rem]" rows="2" name="notes" placeholder="Add another note"></textarea>
|
|
</label>
|
|
<button type="submit" class="btn-primary">Save these notes</button>
|
|
<p class="text-sm text-bakery-600">Clearing a box and saving removes that note.</p>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
</body>
|
|
</html>
|