Files
Paul Lützner fd3530b51c Make the public calendar pages look like the calendar they came from
A shared link opened a list of days and a booking page opened a wall of
times. Both were correct, both were themed against the `:root` fallback —
which is not a theme anybody picked, it is what a stylesheet resolves
against before a user is known — and neither was recognisable as
belonging to the application it came out of.

The shared page is now a month grid with the day list under it, and the
grid is literally the authenticated calendar's: calendar/_view_month.html.twig
was pulled apart into calendar/_month_shell.html.twig — the weekday strip,
six equal rows, hairline gutters, today/weekend/spill-in cells — which
both pages embed. The month view keeps its own chips, its "new event"
affordance and its "N more" link and renders exactly what it did.

The booking page is a week: seven columns of slot pills with prev/next,
opening on the first week that has anything in it, in a card that names
the appointment, its length and its zone.

Both pages wear the OWNER's appearance — theme, accent, radius, density —
via PublicAppearanceResolver, which hands the template three strings
rather than the User so it cannot print a name it does not have. Paper
for an account that never chose; a `system` theme resolves against the
reader's own machine. No user id is passed to the renderer, so a custom
uploaded background is dropped rather than 404ing with the owner's id in
the URL. Still no session and still no cookie, which the tests assert.

Redaction is unchanged and re-asserted over the new markup. Chips carry
no calendar colour, deliberately: ShareLinkReader's rule is that a shared
page says nothing about the owner's calendars, and colours would let a
busy/free link be grouped by which diary each block came from. Days the
window does not cover are dimmed, kept out of the list and named in a
legend, because a blank cell that read as a free one would have the page
claiming availability nobody published; paging is bounded to the months
the window touches for the same reason.

Also fixes a translation key that has been on screen since the feature
shipped: the window under the heading asked for `calendar.share.window`,
a node with two children, and printed the key itself.
2026-08-07 18:37:33 +02:00

41 lines
2.0 KiB
Twig

{#
sharing/booked.html.twig
─────────────────────────────────────────────────────────────────────────────
The page after a booking went through.
A page of its own rather than a banner on the form, and the reason is the
unique constraint: leaving a filled-in form on screen invites a second submit,
which the database would refuse correctly and inexplicably ("that time has just
been taken" — by yourself, a second ago). Replacing the form removes the
temptation entirely.
It deliberately does NOT repeat the time. The confirmation mail carries it, in
the booker's own zone and with an .ics attached, and a page saying "10:30" in
whichever clock the browser happened to be reading is one more chance for the
two to disagree. What this page promises is exactly what has happened: the
appointment is made and a message is on its way.
Variables:
page BookingPage what was booked, for the heading
appearance PublicAppearance the owner's theme, so this page and the form
that led to it are visibly the same place
#}
{% extends 'sharing/_layout.html.twig' %}
{% block title %}{{ 'calendar.booking.booked.title'|trans }}{% endblock %}
{% block body %}
<div class="rounded-pane border border-line bg-surface px-6 py-10 text-center">
<span class="mx-auto w-12 h-12 flex items-center justify-center rounded-full bg-accent/10 text-accent"
aria-hidden="true"><i class="fa-solid fa-check text-xl"></i></span>
<h1 class="mt-4 text-lg font-semibold text-ink">{{ 'calendar.booking.booked.title'|trans }}</h1>
<p class="mt-2 text-sm text-ink-muted">
{{ 'calendar.booking.booked.body'|trans({ '%name%': page.name }) }}
</p>
<p class="mt-4 text-xs text-ink-faint">{{ 'calendar.booking.booked.mail'|trans }}</p>
</div>
{% endblock %}