From 5a145487eff666bdeba64462bb451d9bfeec3f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C3=ABl=20Notermans?= Date: Thu, 28 May 2026 13:04:19 +0200 Subject: [PATCH 1/6] feat(emails+rsvp): redesigned card-based templates with header badge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restyle the calendar invitation/update/cancel/reply emails AND the /rsvp confirm + response pages into a consistent card layout (blue header strip, uppercase badge, body section, footer). Email templates share a new emails/_invitation_layout.html base via {% extends %}, preserving all existing context vars (content.badge/body, summary, start_date/time_str, labels.*, actions.*, rsvp_*_url, instructions, footer). RSVP pages get a matching card with header colored per action. Translation additions (en/fr/nl): email.invitation.badge (was missing) and email.reply.badge (was missing) — required by the new header layout. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../templates/emails/_invitation_layout.html | 65 +++++ .../templates/emails/calendar_invitation.html | 225 ++++++----------- .../emails/calendar_invitation_cancel.html | 171 +++---------- .../emails/calendar_invitation_reply.html | 153 +++--------- .../emails/calendar_invitation_update.html | 226 ++++++------------ src/backend/core/templates/rsvp/confirm.html | 96 +++----- src/backend/core/templates/rsvp/response.html | 112 ++++----- .../src/features/i18n/translations.json | 6 + 8 files changed, 365 insertions(+), 689 deletions(-) create mode 100644 src/backend/core/templates/emails/_invitation_layout.html diff --git a/src/backend/core/templates/emails/_invitation_layout.html b/src/backend/core/templates/emails/_invitation_layout.html new file mode 100644 index 0000000..d2d2b63 --- /dev/null +++ b/src/backend/core/templates/emails/_invitation_layout.html @@ -0,0 +1,65 @@ +{# Shared layout for calendar invitation / update / cancel / reply emails. + Email-client-safe: table-based, inline styles, no external CSS. + Blocks: + header_color — background color of the header strip (default blue). + badge_color — text color of the uppercase header badge (default light blue tint). + body — the per-template body content (after the header, before the footer). +#} + + + + + + {{ content.title }} + + + + +
+ + + {# ── header ── #} + + + {# ── body (per-template) ── #} + + + {# ── divider ── #} + + + {# ── footer ── #} + + +
+ {% if content.badge %} +

+ {{ content.badge }} +

+ {% endif %} +

+ {{ summary }} +

+
+ {% block body %}{% endblock %} +
+ {% if instructions %} +

+ {{ instructions }} +

+ {% endif %} +

+ {{ footer }} +

+
+
+ + diff --git a/src/backend/core/templates/emails/calendar_invitation.html b/src/backend/core/templates/emails/calendar_invitation.html index d684b9d..6203982 100644 --- a/src/backend/core/templates/emails/calendar_invitation.html +++ b/src/backend/core/templates/emails/calendar_invitation.html @@ -1,158 +1,79 @@ - - - - - - {{ content.title }} - - - -
-
-

{{ content.heading }}

-
+{% extends "emails/_invitation_layout.html" %} -

{{ content.body }}

+{# Header defaults (blue) inherited from the base layout. #} -
{{ summary }}
+{% block body %} + {# date/time #} +

+ {{ start_date }} +

+

+ {{ time_str }}{% if start_date != end_date %} · {{ labels.until }} {{ end_date }}{% endif %} +

-
- - - - - - {% if event.location %} - - - - - {% endif %} - {% if event.url %} - - - - - {% endif %} - - - - -
{{ labels.when }} - {{ start_date }}
- {{ time_str }} - {% if start_date != end_date %}
{{ labels.until }} {{ end_date }}{% endif %} -
{{ labels.location }}{{ event.location }}
{{ labels.videoConference }}{{ event.url }}
{{ labels.organizer }}{{ organizer_display }}
-
+ {% if event.location %} +

+ {{ labels.location }}: {{ event.location }} +

+ {% endif %} - {% if event.description %} -
-

{{ labels.description }}

-

{{ event.description|linebreaks }}

-
- {% endif %} + {% if event.url %} +

+ {{ labels.videoConference }}: + {{ event.url }} +

+ {% endif %} - {% if rsvp_accepted_url %} -
- {{ actions.accept }} - {{ actions.maybe }} - {{ actions.decline }} -
- {% endif %} -
-

{{ instructions }}

-
+ {# organizer / body sentence (content.body is i18n-rendered with {{organizer}}) #} +

+ {{ content.body }} +

- -
- - + {% if event.description %} +

+ {{ event.description|linebreaksbr }} +

+ {% endif %} + + {# RSVP buttons — only present for REQUEST-method emails #} + {% if rsvp_accepted_url %} + + + + + + +
+ + {{ actions.accept }} + + + + {{ actions.maybe }} + + + + {{ actions.decline }} + +
+ {% endif %} +{% endblock %} diff --git a/src/backend/core/templates/emails/calendar_invitation_cancel.html b/src/backend/core/templates/emails/calendar_invitation_cancel.html index b1aaacd..94908a6 100644 --- a/src/backend/core/templates/emails/calendar_invitation_cancel.html +++ b/src/backend/core/templates/emails/calendar_invitation_cancel.html @@ -1,139 +1,42 @@ - - - - - - {{ content.title }} - - - -
-
-

{{ content.heading }}

-
+{% extends "emails/_invitation_layout.html" %} - {{ content.badge }} +{% block header_color %}#d2212f{% endblock %} +{% block badge_color %}#f5c2c6{% endblock %} -

{{ content.body }}

+{% block body %} + {# small label above the strikethrough date (cancelled event was scheduled for…) #} +

+ {{ labels.wasScheduledFor }} +

+

+ {{ start_date }} +

+

+ {{ time_str }}{% if start_date != end_date %} · {{ labels.until }} {{ end_date }}{% endif %} +

-
{{ summary }}
+ {% if event.location %} +

+ {{ labels.location }}: {{ event.location }} +

+ {% endif %} -
- - - - - - {% if event.location %} - - - - - {% endif %} - {% if event.url %} - - - - - {% endif %} - - - - -
{{ labels.wasScheduledFor }} - {{ start_date }}
- {{ time_str }} - {% if start_date != end_date %}
{{ labels.until }} {{ end_date }}{% endif %} -
{{ labels.location }}{{ event.location }}
{{ labels.videoConference }}{{ event.url }}
{{ labels.organizer }}{{ organizer_display }}
-
+ {% if event.url %} +

+ {{ labels.videoConference }}: {{ event.url }} +

+ {% endif %} -
-

{{ instructions }}

-
- - -
- - +

+ {{ content.body }} +

+{% endblock %} diff --git a/src/backend/core/templates/emails/calendar_invitation_reply.html b/src/backend/core/templates/emails/calendar_invitation_reply.html index d6858a3..c3c8229 100644 --- a/src/backend/core/templates/emails/calendar_invitation_reply.html +++ b/src/backend/core/templates/emails/calendar_invitation_reply.html @@ -1,126 +1,37 @@ - - - - - - {{ content.title }} - - - -
-
-

{{ content.heading }}

-
+{% extends "emails/_invitation_layout.html" %} -

{{ content.body }}

+{% block header_color %}#16a34a{% endblock %} +{% block badge_color %}#bbe5c5{% endblock %} -
{{ summary }}
+{% block body %} + {# date/time #} +

+ {{ start_date }} +

+

+ {{ time_str }}{% if start_date != end_date %} · {{ labels.until }} {{ end_date }}{% endif %} +

-
- - - - - - {% if event.location %} - - - - - {% endif %} - {% if event.url %} - - - - - {% endif %} - - - - -
{{ labels.when }} - {{ start_date }}
- {{ time_str }} - {% if start_date != end_date %}
{{ labels.until }} {{ end_date }}{% endif %} -
{{ labels.location }}{{ event.location }}
{{ labels.videoConference }}{{ event.url }}
{{ labels.attendee }}{{ attendee_display }}
-
+ {% if event.location %} +

+ {{ labels.location }}: {{ event.location }} +

+ {% endif %} -
-

{{ instructions }}

-
+ {% if event.url %} +

+ {{ labels.videoConference }}: + {{ event.url }} +

+ {% endif %} - -
- - + {# attendee response sentence (content.body interpolates {{attendee}}) #} +

+ {{ content.body }} +

+{% endblock %} diff --git a/src/backend/core/templates/emails/calendar_invitation_update.html b/src/backend/core/templates/emails/calendar_invitation_update.html index dec29d9..5a87e8f 100644 --- a/src/backend/core/templates/emails/calendar_invitation_update.html +++ b/src/backend/core/templates/emails/calendar_invitation_update.html @@ -1,163 +1,77 @@ - - - - - - {{ content.title }} - - - -
-
-

{{ content.heading }}

-
+{% extends "emails/_invitation_layout.html" %} - {{ content.badge }} +{# Header defaults (blue) inherited; content.badge resolves to "UPDATED" via i18n. #} -

{{ content.body }}

+{% block body %} + {# date/time #} +

+ {{ start_date }} +

+

+ {{ time_str }}{% if start_date != end_date %} · {{ labels.until }} {{ end_date }}{% endif %} +

-
{{ summary }}
+ {% if event.location %} +

+ {{ labels.location }}: {{ event.location }} +

+ {% endif %} -
- - - - - - {% if event.location %} - - - - - {% endif %} - {% if event.url %} - - - - - {% endif %} - - - - -
{{ labels.when }} - {{ start_date }}
- {{ time_str }} - {% if start_date != end_date %}
{{ labels.until }} {{ end_date }}{% endif %} -
{{ labels.location }}{{ event.location }}
{{ labels.videoConference }}{{ event.url }}
{{ labels.organizer }}{{ organizer_display }}
-
+ {% if event.url %} +

+ {{ labels.videoConference }}: + {{ event.url }} +

+ {% endif %} - {% if event.description %} -
-

{{ labels.description }}

-

{{ event.description|linebreaks }}

-
- {% endif %} +

+ {{ content.body }} +

- {% if rsvp_accepted_url %} -
- {{ actions.accept }} - {{ actions.maybe }} - {{ actions.decline }} -
- {% endif %} -
-

{{ instructions }}

-
+ {% if event.description %} +

+ {{ event.description|linebreaksbr }} +

+ {% endif %} - -
- - + {% if rsvp_accepted_url %} + + + + + + +
+ + {{ actions.accept }} + + + + {{ actions.maybe }} + + + + {{ actions.decline }} + +
+ {% endif %} +{% endblock %} diff --git a/src/backend/core/templates/rsvp/confirm.html b/src/backend/core/templates/rsvp/confirm.html index b5b00cd..3b323c0 100644 --- a/src/backend/core/templates/rsvp/confirm.html +++ b/src/backend/core/templates/rsvp/confirm.html @@ -1,70 +1,46 @@ - - + + - - - {{ page_title }} - + + + {{ page_title }} + -
+
+
+
{{ status_icon|safe }}

{{ heading }}

+
+
- - -

...

+ + +

+
- +
+ diff --git a/src/backend/core/templates/rsvp/response.html b/src/backend/core/templates/rsvp/response.html index 4affa87..d6837a4 100644 --- a/src/backend/core/templates/rsvp/response.html +++ b/src/backend/core/templates/rsvp/response.html @@ -1,76 +1,56 @@ - - + + - - - {{ page_title }} - + + + {{ page_title }} + -
- {% if error %} +
+
+ {% if error %} +
-

{{ error_title }}

+

{{ error_title }}

+
+

{{ error }}

- {% else %} +
+ {% else %} +
{{ status_icon|safe }}

{{ heading }}

- {% if event_summary %} -
{{ event_summary }}
- {% endif %} - {% if event_date %} -
{{ event_date }}
- {% endif %} -

{{ message }}

- {% endif %} +
+
+ {% if event_summary %}
{{ event_summary }}
{% endif %} + {% if event_date %}
{{ event_date }}
{% endif %} + {% if message %}

{{ message }}

{% endif %} +
+ {% endif %}
+
diff --git a/src/frontend/apps/calendars/src/features/i18n/translations.json b/src/frontend/apps/calendars/src/features/i18n/translations.json index bdd783b..a7215f8 100644 --- a/src/frontend/apps/calendars/src/features/i18n/translations.json +++ b/src/frontend/apps/calendars/src/features/i18n/translations.json @@ -416,6 +416,7 @@ "invitation": { "title": "Event invitation", "heading": "Event invitation", + "badge": "Event invitation", "body": "{{organizer}} invites you to an event" }, "update": { @@ -433,6 +434,7 @@ "reply": { "title": "Event reply", "heading": "Reply received", + "badge": "Response", "body": "{{attendee}} has replied to your event" }, "labels": { @@ -1336,6 +1338,7 @@ "invitation": { "title": "Invitation à un événement", "heading": "Invitation à un événement", + "badge": "Invitation à un événement", "body": "{{organizer}} vous invite à un événement" }, "update": { @@ -1353,6 +1356,7 @@ "reply": { "title": "Réponse à l'événement", "heading": "Réponse reçue", + "badge": "Réponse", "body": "{{attendee}} a répondu à votre événement" }, "labels": { @@ -1998,6 +2002,7 @@ "invitation": { "title": "Uitnodiging voor evenement", "heading": "Uitnodiging voor evenement", + "badge": "Uitnodiging voor evenement", "body": "{{organizer}} nodigt u uit voor een evenement" }, "update": { @@ -2015,6 +2020,7 @@ "reply": { "title": "Antwoord op evenement", "heading": "Antwoord ontvangen", + "badge": "Antwoord", "body": "{{attendee}} heeft gereageerd op uw evenement" }, "labels": { From ad48d1d276c95f53a7cd333b53cea3dcb8586623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C3=ABl=20Notermans?= Date: Thu, 28 May 2026 20:09:06 +0200 Subject: [PATCH 2/6] feat(rsvp): apply the email card layout to /rsvp pages Reuse the invitation email's blue card design for the /rsvp confirm and response pages, with meeting details filled in: - confirm.html and response.html: blue card with header (badge + title), body, divider, and footer ("via {{ app_name }}"). - response.html: title = event_summary; badge = action label (uppercased); body shows status icon, optional event_date, and the confirmation message. Error path uses a red header. - viewsets_rsvp.py: pass app_name (settings.APP_NAME) to the three render contexts (GET confirm, POST response, _render_error). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/core/api/viewsets_rsvp.py | 3 + src/backend/core/templates/rsvp/confirm.html | 46 +++++++------ src/backend/core/templates/rsvp/response.html | 64 +++++++++++-------- 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/backend/core/api/viewsets_rsvp.py b/src/backend/core/api/viewsets_rsvp.py index 3708db4..4064741 100644 --- a/src/backend/core/api/viewsets_rsvp.py +++ b/src/backend/core/api/viewsets_rsvp.py @@ -57,6 +57,7 @@ def _render_error(request, message, lang="en"): "error_title": t("rsvp.error.invalidLink", lang), "header_color": "#dc2626", "lang": lang, + "app_name": getattr(settings, "APP_NAME", "Calendars"), }, status=400, ) @@ -159,6 +160,7 @@ def get(self, request): "status_icon": PARTSTAT_ICONS[action], "header_color": PARTSTAT_COLORS[action], "submit_label": label, + "app_name": getattr(settings, "APP_NAME", "Calendars"), }, ) @@ -199,6 +201,7 @@ def post(self, request): "header_color": PARTSTAT_COLORS[action], "event_summary": summary, "lang": lang, + "app_name": getattr(settings, "APP_NAME", "Calendars"), }, ) diff --git a/src/backend/core/templates/rsvp/confirm.html b/src/backend/core/templates/rsvp/confirm.html index 3b323c0..c22c44e 100644 --- a/src/backend/core/templates/rsvp/confirm.html +++ b/src/backend/core/templates/rsvp/confirm.html @@ -5,30 +5,36 @@ {{ page_title }}
-
{{ status_icon|safe }}
-

{{ heading }}

+

{{ heading }}

+

{{ submit_label }} {{ status_icon|safe }}

@@ -39,6 +45,10 @@

{{ heading }}

+
+
diff --git a/src/backend/core/templates/rsvp/response.html b/src/backend/core/templates/rsvp/response.html index d6837a4..6f70a67 100644 --- a/src/backend/core/templates/rsvp/response.html +++ b/src/backend/core/templates/rsvp/response.html @@ -5,27 +5,30 @@ {{ page_title }} @@ -33,23 +36,28 @@
{% if error %}
-
-

{{ error_title }}

+

{{ error_title }}

+

{{ error_title }}

-

{{ error }}

+
+

{{ error }}

{% else %}
-
{{ status_icon|safe }}
-

{{ heading }}

+

{{ heading }}

+

{{ event_summary }}

- {% if event_summary %}
{{ event_summary }}
{% endif %} + {% if status_icon %}
{{ status_icon|safe }}
{% endif %} {% if event_date %}
{{ event_date }}
{% endif %} - {% if message %}

{{ message }}

{% endif %} + {% if message %}

{{ message }}

{% endif %}
{% endif %} +
+
From d2a9b855605aa442f9ea573e31cc2da36c47ccfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C3=ABl=20Notermans?= Date: Thu, 28 May 2026 22:21:36 +0200 Subject: [PATCH 3/6] fix(emails+rsvp): drop status_icon from /rsvp + multi-line layout doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove the partstat icon from /rsvp confirm + response pages — the uppercase badge ("ACCEPTED"/"DECLINED"/"TENTATIVE") already conveys the action, the icon was redundant. - Use {% comment %}…{% endcomment %} for the multi-line header doc in emails/_invitation_layout.html. Django {# … #} comments are single- line only, so the doc lines below the first were leaking into the rendered email body. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../core/templates/emails/_invitation_layout.html | 15 ++++++++------- src/backend/core/templates/rsvp/confirm.html | 2 +- src/backend/core/templates/rsvp/response.html | 2 -- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/backend/core/templates/emails/_invitation_layout.html b/src/backend/core/templates/emails/_invitation_layout.html index d2d2b63..d25fdf4 100644 --- a/src/backend/core/templates/emails/_invitation_layout.html +++ b/src/backend/core/templates/emails/_invitation_layout.html @@ -1,10 +1,11 @@ -{# Shared layout for calendar invitation / update / cancel / reply emails. - Email-client-safe: table-based, inline styles, no external CSS. - Blocks: - header_color — background color of the header strip (default blue). - badge_color — text color of the uppercase header badge (default light blue tint). - body — the per-template body content (after the header, before the footer). -#} +{% comment %} +Shared layout for calendar invitation / update / cancel / reply emails. +Email-client-safe: table-based, inline styles, no external CSS. +Blocks: + header_color — background color of the header strip (default blue). + badge_color — text color of the uppercase header badge (default light blue tint). + body — the per-template body content (after the header, before the footer). +{% endcomment %} diff --git a/src/backend/core/templates/rsvp/confirm.html b/src/backend/core/templates/rsvp/confirm.html index c22c44e..82ecc21 100644 --- a/src/backend/core/templates/rsvp/confirm.html +++ b/src/backend/core/templates/rsvp/confirm.html @@ -34,7 +34,7 @@

{{ heading }}

-

{{ submit_label }} {{ status_icon|safe }}

+

{{ submit_label }}

diff --git a/src/backend/core/templates/rsvp/response.html b/src/backend/core/templates/rsvp/response.html index 6f70a67..42d8951 100644 --- a/src/backend/core/templates/rsvp/response.html +++ b/src/backend/core/templates/rsvp/response.html @@ -40,7 +40,6 @@

{{ error_title }}

-

{{ error }}

{% else %} @@ -49,7 +48,6 @@

{{ event_summary }}

- {% if status_icon %}
{{ status_icon|safe }}
{% endif %} {% if event_date %}
{{ event_date }}
{% endif %} {% if message %}

{{ message }}

{% endif %}
From a724c6f1c8e49e203ee59a6819bf22817852f03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C3=ABl=20Notermans?= Date: Thu, 28 May 2026 22:37:51 +0200 Subject: [PATCH 4/6] refactor(emails+rsvp): hardcode 'Calendars' footer, link cancel URL, DRY rsvp CSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - viewsets_rsvp.py: drop the app_name kwarg from all three render contexts (error / GET confirm / POST response) — the footer string is hardcoded "Calendars" in the rsvp templates instead, since these pages are only ever served by the calendars app. - calendar_invitation_cancel.html: render event.url as a clickable instead of plain text, matching the invitation/update templates. - rsvp/_common_styles.html (new): shared CSS for the rsvp pages — base .wrap/.card/.header/.badge/.title/.body/.divider/.footer plus a .err variant for header/badge. confirm.html and response.html now {% include %} it and keep only page-specific rules (.submit-btn on confirm, .event-date on response). Dropped the unused .ok class from response.html's success branch (default is blue). --- src/backend/core/api/viewsets_rsvp.py | 7 ++-- .../emails/calendar_invitation_cancel.html | 4 ++- .../core/templates/rsvp/_common_styles.html | 23 ++++++++++++ src/backend/core/templates/rsvp/confirm.html | 23 +++--------- src/backend/core/templates/rsvp/response.html | 35 +++++-------------- 5 files changed, 40 insertions(+), 52 deletions(-) create mode 100644 src/backend/core/templates/rsvp/_common_styles.html diff --git a/src/backend/core/api/viewsets_rsvp.py b/src/backend/core/api/viewsets_rsvp.py index 4064741..fd861e6 100644 --- a/src/backend/core/api/viewsets_rsvp.py +++ b/src/backend/core/api/viewsets_rsvp.py @@ -57,7 +57,6 @@ def _render_error(request, message, lang="en"): "error_title": t("rsvp.error.invalidLink", lang), "header_color": "#dc2626", "lang": lang, - "app_name": getattr(settings, "APP_NAME", "Calendars"), }, status=400, ) @@ -160,8 +159,7 @@ def get(self, request): "status_icon": PARTSTAT_ICONS[action], "header_color": PARTSTAT_COLORS[action], "submit_label": label, - "app_name": getattr(settings, "APP_NAME", "Calendars"), - }, + }, ) def post(self, request): @@ -201,8 +199,7 @@ def post(self, request): "header_color": PARTSTAT_COLORS[action], "event_summary": summary, "lang": lang, - "app_name": getattr(settings, "APP_NAME", "Calendars"), - }, + }, ) diff --git a/src/backend/core/templates/emails/calendar_invitation_cancel.html b/src/backend/core/templates/emails/calendar_invitation_cancel.html index 94908a6..20d3d4d 100644 --- a/src/backend/core/templates/emails/calendar_invitation_cancel.html +++ b/src/backend/core/templates/emails/calendar_invitation_cancel.html @@ -31,7 +31,9 @@ {% if event.url %}

- {{ labels.videoConference }}: {{ event.url }} + {{ labels.videoConference }}: + {{ event.url }}

{% endif %} diff --git a/src/backend/core/templates/rsvp/_common_styles.html b/src/backend/core/templates/rsvp/_common_styles.html new file mode 100644 index 0000000..2c664f1 --- /dev/null +++ b/src/backend/core/templates/rsvp/_common_styles.html @@ -0,0 +1,23 @@ +{# Shared CSS for rsvp/confirm.html and rsvp/response.html. Page-specific + styles (e.g. .submit-btn, .event-date) live in each template. #} + diff --git a/src/backend/core/templates/rsvp/confirm.html b/src/backend/core/templates/rsvp/confirm.html index 82ecc21..8a3652c 100644 --- a/src/backend/core/templates/rsvp/confirm.html +++ b/src/backend/core/templates/rsvp/confirm.html @@ -4,29 +4,14 @@ {{ page_title }} + {% include "rsvp/_common_styles.html" %} @@ -47,7 +32,7 @@
diff --git a/src/backend/core/templates/rsvp/response.html b/src/backend/core/templates/rsvp/response.html index 42d8951..b0af50b 100644 --- a/src/backend/core/templates/rsvp/response.html +++ b/src/backend/core/templates/rsvp/response.html @@ -4,31 +4,12 @@ {{ page_title }} + {% include "rsvp/_common_styles.html" %} @@ -43,8 +24,8 @@

{{ error }}

{% else %} -
-

{{ heading }}

+
+

{{ heading }}

{{ event_summary }}

@@ -54,7 +35,7 @@ {% endif %}
From 3bc5430b6a517a186dfaec599fe586c972f12665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C3=ABl=20Notermans?= Date: Thu, 28 May 2026 22:40:51 +0200 Subject: [PATCH 5/6] style(rsvp): dedent stray },} in viewsets_rsvp render contexts Lint-only: ruff format flagged the closing braces in the GET-confirm and POST-response render contexts that ended up over-indented after the earlier app_name kwarg removal. --- src/backend/core/api/viewsets_rsvp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/core/api/viewsets_rsvp.py b/src/backend/core/api/viewsets_rsvp.py index fd861e6..3708db4 100644 --- a/src/backend/core/api/viewsets_rsvp.py +++ b/src/backend/core/api/viewsets_rsvp.py @@ -159,7 +159,7 @@ def get(self, request): "status_icon": PARTSTAT_ICONS[action], "header_color": PARTSTAT_COLORS[action], "submit_label": label, - }, + }, ) def post(self, request): @@ -199,7 +199,7 @@ def post(self, request): "header_color": PARTSTAT_COLORS[action], "event_summary": summary, "lang": lang, - }, + }, ) From 0930e13bace3d47375e7fdaefb4d495276bc4c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ri=C3=ABl=20Notermans?= Date: Fri, 29 May 2026 15:57:55 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=90=9B=20(rsvp)=20fix=20leaking=20tem?= =?UTF-8?q?plate=20comment=20+=20sync=20test=20button=20colors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shared CSS partial used a multi-line {# #} comment, which Django does not support (no newlines allowed between the delimiters), so the comment text was rendered into the page. Switch to {% comment %}. The email RSVP restyle changed the button colors, but the end-to-end tests still selected buttons by the old palette. Update the accept, tentative, and decline colors to match the new design. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../core/templates/rsvp/_common_styles.html | 6 ++++-- src/backend/core/tests/test_rsvp.py | 16 ++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/backend/core/templates/rsvp/_common_styles.html b/src/backend/core/templates/rsvp/_common_styles.html index 2c664f1..c1a1aa6 100644 --- a/src/backend/core/templates/rsvp/_common_styles.html +++ b/src/backend/core/templates/rsvp/_common_styles.html @@ -1,5 +1,7 @@ -{# Shared CSS for rsvp/confirm.html and rsvp/response.html. Page-specific - styles (e.g. .submit-btn, .event-date) live in each template. #} +{% comment %} + Shared CSS for rsvp/confirm.html and rsvp/response.html. Page-specific + styles (e.g. .submit-btn, .event-date) live in each template. +{% endcomment %}