Phase 7: Replace render_template() with s-expression rendering in all POST/PUT/DELETE routes

Eliminates all render_template() calls from POST/PUT/DELETE handlers across
all 7 services. Moves sexp_components.py into sexp/ packages per service.

- Blog: like toggle, snippets, cache clear, features/sumup/entry panels,
  create/delete market, WYSIWYG editor panel (render_editor_panel)
- Federation: like/unlike/boost/unboost, follow/unfollow, actor card,
  interaction buttons
- Events: ticket widget, checkin, confirm/decline/provisional, tickets
  config, posts CRUD, description edit/save, calendar/slot/ticket_type
  CRUD, payments, buy tickets, day main panel, entry page
- Market: like toggle, cart add response
- Account: newsletter toggle
- Cart: checkout error pages (3 handlers)
- Orders: checkout error page (1 handler)

Remaining render_template() calls are exclusively in GET handlers and
internal services (email templates, fragment endpoints).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 01:15:29 +00:00
parent e65232761b
commit 838ec982eb
64 changed files with 2920 additions and 545 deletions

View File

@@ -1,7 +1,7 @@
from __future__ import annotations
import path_setup # noqa: F401 # adds shared/ to sys.path
import sexp_components # noqa: F401 # ensure Hypercorn --reload watches this file
import sexp.sexp_components as sexp_components # noqa: F401 # ensure Hypercorn --reload watches this file
from pathlib import Path
from quart import g, abort, request

View File

@@ -66,7 +66,7 @@ def register() -> Blueprint:
entries, has_more, pending_tickets, page_info = await _load_entries(page)
from shared.sexp.page import get_template_context
from sexp_components import render_all_events_page, render_all_events_oob
from sexp.sexp_components import render_all_events_page, render_all_events_oob
ctx = await get_template_context()
if is_htmx_request():
@@ -83,7 +83,7 @@ def register() -> Blueprint:
entries, has_more, pending_tickets, page_info = await _load_entries(page)
from sexp_components import render_all_events_cards
from sexp.sexp_components import render_all_events_cards
html = await render_all_events_cards(entries, has_more, pending_tickets, page_info, page, view)
return await make_response(html, 200)
@@ -124,12 +124,8 @@ def register() -> Blueprint:
if ident["session_id"] is not None:
frag_params["session_id"] = ident["session_id"]
widget_html = await render_template(
"_types/page_summary/_ticket_widget.html",
entry=entry,
qty=qty,
ticket_url="/all-tickets/adjust",
)
from sexp.sexp_components import render_ticket_widget
widget_html = render_ticket_widget(entry, qty, "/all-tickets/adjust")
mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False)
return await make_response(widget_html + mini_html, 200)

View File

@@ -20,7 +20,7 @@ def register():
from shared.browser.app.utils.htmx import is_htmx_request
from shared.sexp.page import get_template_context
from sexp_components import render_calendar_admin_page, render_calendar_admin_oob
from sexp.sexp_components import render_calendar_admin_page, render_calendar_admin_oob
tctx = await get_template_context()
if not is_htmx_request():
@@ -34,12 +34,8 @@ def register():
@bp.get("/description/")
@require_admin
async def calendar_description_edit(calendar_slug: str, **kwargs):
# g.post and g.calendar should already be set by the parent calendar bp
html = await render_template(
"_types/calendar/admin/_description_edit.html",
post=g.post_data['post'],
calendar=g.calendar,
)
from sexp.sexp_components import render_calendar_description_edit
html = render_calendar_description_edit(g.calendar)
return await make_response(html)
@@ -54,24 +50,16 @@ def register():
g.calendar.description = description
await g.s.flush()
html = await render_template(
"_types/calendar/admin/_description.html",
post=g.post_data['post'],
calendar=g.calendar,
oob=True
)
from sexp.sexp_components import render_calendar_description
html = render_calendar_description(g.calendar, oob=True)
return await make_response(html)
@bp.get("/description/view/")
@require_admin
async def calendar_description_view(calendar_slug: str, **kwargs):
# just render the display version without touching the DB (used by Cancel)
html = await render_template(
"_types/calendar/admin/_description.html",
post=g.post_data['post'],
calendar=g.calendar,
)
from sexp.sexp_components import render_calendar_description
html = render_calendar_description(g.calendar)
return await make_response(html)
return bp

View File

@@ -143,7 +143,7 @@ def register():
confirmed_entries = visible.confirmed_entries
from shared.sexp.page import get_template_context
from sexp_components import render_calendar_page, render_calendar_oob
from sexp.sexp_components import render_calendar_page, render_calendar_oob
tctx = await get_template_context()
tctx.update(dict(
@@ -183,7 +183,10 @@ def register():
description = (form.get("description") or "").strip()
await update_calendar_description(g.calendar, description)
html = await render_template("_types/calendar/admin/index.html")
from shared.sexp.page import get_template_context
from sexp.sexp_components import _calendar_admin_main_panel_html
ctx = await get_template_context()
html = _calendar_admin_main_panel_html(ctx)
return await make_response(html, 200)
@@ -199,10 +202,14 @@ def register():
# If we have post context (blog-embedded mode), update nav
post_data = getattr(g, "post_data", None)
html = await render_template("_types/calendars/index.html")
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_calendars_list_panel
ctx = await get_template_context()
html = render_calendars_list_panel(ctx)
if post_data:
from shared.services.entry_associations import get_associated_entries
from sexp.sexp_components import render_post_nav_entries_oob
post_id = (post_data.get("post") or {}).get("id")
cals = (
@@ -214,13 +221,7 @@ def register():
).scalars().all()
associated_entries = await get_associated_entries(g.s, post_id)
nav_oob = await render_template(
"_types/post/admin/_nav_entries_oob.html",
associated_entries=associated_entries,
calendars=cals,
post=post_data["post"],
)
nav_oob = render_post_nav_entries_oob(associated_entries, cals, post_data["post"])
html = html + nav_oob
return await make_response(html, 200)

View File

@@ -216,7 +216,49 @@ def register():
if ident["session_id"] is not None:
frag_params["session_id"] = ident["session_id"]
html = await render_template("_types/day/_main_panel.html")
# Re-query day entries for the sexp component
from datetime import date as date_cls, timedelta
from bp.calendar.services import get_visible_entries_for_period
from quart import session as qsession
period_start = datetime(year, month, day, tzinfo=timezone.utc)
period_end = period_start + timedelta(days=1)
user = getattr(g, "user", None)
session_id = qsession.get("calendar_sid")
visible = await get_visible_entries_for_period(
sess=g.s,
calendar_id=g.calendar.id,
period_start=period_start,
period_end=period_end,
user=user,
session_id=session_id,
)
# Query day slots for this weekday
day_date = date_cls(year, month, day)
weekday_attr = ["mon","tue","wed","thu","fri","sat","sun"][day_date.weekday()]
stmt = select(CalendarSlot).where(
CalendarSlot.calendar_id == g.calendar.id,
getattr(CalendarSlot, weekday_attr) == True,
CalendarSlot.deleted_at.is_(None),
).order_by(CalendarSlot.time_start.asc(), CalendarSlot.id.asc())
result = await g.s.execute(stmt)
day_slots = list(result.scalars())
styles = getattr(g, "styles", None) or {}
ctx = {
"calendar": g.calendar,
"day_entries": visible.merged_entries,
"day": day,
"month": month,
"year": year,
"hx_select_search": "#main-panel",
"styles": styles,
}
from sexp.sexp_components import render_day_main_panel
html = render_day_main_panel(ctx)
mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False)
return await make_response(html + mini_html, 200)

View File

@@ -109,15 +109,9 @@ def register():
session_id=session_id,
)
# Render OOB template
nav_oob = await render_template(
"_types/day/admin/_nav_entries_oob.html",
confirmed_entries=visible.confirmed_entries,
post=g.post_data["post"],
calendar=calendar,
day_date=day_date,
)
return nav_oob
# Render OOB nav
from sexp.sexp_components import render_day_entries_nav_oob
return render_day_entries_nav_oob(visible.confirmed_entries, calendar, day_date)
async def get_post_nav_oob(entry_id: int):
"""Helper to generate OOB update for post entries nav when entry state changes"""
@@ -152,13 +146,9 @@ def register():
)
).scalars().all()
# Render OOB template for this post's nav
nav_oob = await render_template(
"_types/post/admin/_nav_entries_oob.html",
associated_entries=associated_entries,
calendars=calendars,
post=post,
)
# Render OOB nav for this post
from sexp.sexp_components import render_post_nav_entries_oob
nav_oob = render_post_nav_entries_oob(associated_entries, calendars, post)
nav_oobs.append(nav_oob)
return "".join(nav_oobs)
@@ -250,19 +240,15 @@ def register():
@require_admin
async def get(entry_id: int, **rest):
from shared.browser.app.utils.htmx import is_htmx_request
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_entry_page, render_entry_oob
# Full template for both HTMX and normal requests
tctx = await get_template_context()
if not is_htmx_request():
# Normal browser request: full page with layout
html = await render_template(
"_types/entry/index.html",
)
html = await render_entry_page(tctx)
else:
html = await render_template(
"_types/entry/_oob_elements.html",
)
html = await render_entry_oob(tctx)
return await make_response(html, 200)
@bp.get("/edit/")
@@ -431,10 +417,11 @@ def register():
# Get nav OOB update
nav_oob = await get_day_nav_oob(year, month, day)
html = await render_template(
"_types/entry/index.html",
#entry=entry,
)
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_entry_page
tctx = await get_template_context()
html = await render_entry_page(tctx)
return await make_response(html + nav_oob, 200)
@@ -457,8 +444,10 @@ def register():
day_nav_oob = await get_day_nav_oob(year, month, day)
post_nav_oob = await get_post_nav_oob(entry_id)
# redirect back to calendar admin or order page as you prefer
html = await render_template("_types/entry/_optioned.html")
# Re-read entry to get updated state
await g.s.refresh(g.entry)
from sexp.sexp_components import render_entry_optioned
html = render_entry_optioned(g.entry, g.calendar, day, month, year)
return await make_response(html + day_nav_oob + post_nav_oob, 200)
@bp.post("/decline/")
@@ -480,8 +469,10 @@ def register():
day_nav_oob = await get_day_nav_oob(year, month, day)
post_nav_oob = await get_post_nav_oob(entry_id)
# redirect back to calendar admin or order page as you prefer
html = await render_template("_types/entry/_optioned.html")
# Re-read entry to get updated state
await g.s.refresh(g.entry)
from sexp.sexp_components import render_entry_optioned
html = render_entry_optioned(g.entry, g.calendar, day, month, year)
return await make_response(html + day_nav_oob + post_nav_oob, 200)
@bp.post("/provisional/")
@@ -503,8 +494,10 @@ def register():
day_nav_oob = await get_day_nav_oob(year, month, day)
post_nav_oob = await get_post_nav_oob(entry_id)
# redirect back to calendar admin or order page as you prefer
html = await render_template("_types/entry/_optioned.html")
# Re-read entry to get updated state
await g.s.refresh(g.entry)
from sexp.sexp_components import render_entry_optioned
html = render_entry_optioned(g.entry, g.calendar, day, month, year)
return await make_response(html + day_nav_oob + post_nav_oob, 200)
@bp.post("/tickets/")
@@ -546,7 +539,9 @@ def register():
await g.s.flush()
# Return just the tickets fragment (targeted by hx-target="#entry-tickets-...")
html = await render_template("_types/entry/_tickets.html")
await g.s.refresh(g.entry)
from sexp.sexp_components import render_entry_tickets_config
html = render_entry_tickets_config(g.entry, g.calendar, request.view_args.get("day"), request.view_args.get("month"), request.view_args.get("year"))
return await make_response(html, 200)
@bp.get("/posts/search/")
@@ -596,11 +591,10 @@ def register():
entry_posts = await get_entry_posts(g.s, entry_id)
# Return updated posts list + OOB nav update
html = await render_template("_types/entry/_posts.html")
nav_oob = await render_template(
"_types/entry/admin/_nav_posts_oob.html",
entry_posts=entry_posts,
)
from sexp.sexp_components import render_entry_posts_panel, render_entry_posts_nav_oob
va = request.view_args or {}
html = render_entry_posts_panel(entry_posts, g.entry, g.calendar, va.get("day"), va.get("month"), va.get("year"))
nav_oob = render_entry_posts_nav_oob(entry_posts)
return await make_response(html + nav_oob, 200)
@bp.delete("/posts/<int:post_id>/")
@@ -619,11 +613,10 @@ def register():
entry_posts = await get_entry_posts(g.s, entry_id)
# Return updated posts list + OOB nav update
html = await render_template("_types/entry/_posts.html")
nav_oob = await render_template(
"_types/entry/admin/_nav_posts_oob.html",
entry_posts=entry_posts,
)
from sexp.sexp_components import render_entry_posts_panel, render_entry_posts_nav_oob
va = request.view_args or {}
html = render_entry_posts_panel(entry_posts, g.entry, g.calendar, va.get("day"), va.get("month"), va.get("year"))
nav_oob = render_entry_posts_nav_oob(entry_posts)
return await make_response(html + nav_oob, 200)
return bp

View File

@@ -36,7 +36,7 @@ def register():
@cache_page(tag="calendars")
async def home(**kwargs):
from shared.sexp.page import get_template_context
from sexp_components import render_calendars_page, render_calendars_oob
from sexp.sexp_components import render_calendars_page, render_calendars_oob
ctx = await get_template_context()
if not is_htmx_request():
@@ -68,13 +68,15 @@ def register():
except Exception as e:
return await make_response(f'<div class="text-red-600 text-sm">{e}</div>', 422)
html = await render_template(
"_types/calendars/index.html",
)
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_calendars_list_panel
ctx = await get_template_context()
html = render_calendars_list_panel(ctx)
# Blog-embedded mode: also update post nav
if post_data:
from shared.services.entry_associations import get_associated_entries
from sexp.sexp_components import render_post_nav_entries_oob
cals = (
await g.s.execute(
@@ -85,14 +87,7 @@ def register():
).scalars().all()
associated_entries = await get_associated_entries(g.s, post_id)
nav_oob = await render_template(
"_types/post/admin/_nav_entries_oob.html",
associated_entries=associated_entries,
calendars=cals,
post=post_data["post"],
)
nav_oob = render_post_nav_entries_oob(associated_entries, cals, post_data["post"])
html = html + nav_oob
return await make_response(html)

View File

@@ -18,7 +18,7 @@ def register():
from shared.browser.app.utils.htmx import is_htmx_request
from shared.sexp.page import get_template_context
from sexp_components import render_day_admin_page, render_day_admin_oob
from sexp.sexp_components import render_day_admin_page, render_day_admin_oob
tctx = await get_template_context()
if not is_htmx_request():

View File

@@ -121,7 +121,7 @@ def register():
- pending only for current user/session
"""
from shared.sexp.page import get_template_context
from sexp_components import render_day_page, render_day_oob
from sexp.sexp_components import render_day_page, render_day_oob
tctx = await get_template_context()
if not is_htmx_request():

View File

@@ -24,7 +24,7 @@ def register():
@bp.get("/")
async def home(**kwargs):
from shared.sexp.page import get_template_context
from sexp_components import render_markets_page, render_markets_oob
from sexp.sexp_components import render_markets_page, render_markets_oob
ctx = await get_template_context()
if not is_htmx_request():
@@ -52,7 +52,10 @@ def register():
except Exception as e:
return await make_response(f'<div class="text-red-600 text-sm">{e}</div>', 422)
html = await render_template("_types/markets/index.html")
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_markets_list_panel
ctx = await get_template_context()
html = render_markets_list_panel(ctx)
return await make_response(html)
@bp.delete("/<market_slug>/")
@@ -63,7 +66,10 @@ def register():
if not deleted:
return await make_response("Market not found", 404)
html = await render_template("_types/markets/index.html")
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_markets_list_panel
ctx = await get_template_context()
html = render_markets_list_panel(ctx)
return await make_response(html)
return bp

View File

@@ -46,7 +46,7 @@ def register() -> Blueprint:
entries, has_more, pending_tickets = await _load_entries(post["id"], page)
from shared.sexp.page import get_template_context
from sexp_components import render_page_summary_page, render_page_summary_oob
from sexp.sexp_components import render_page_summary_page, render_page_summary_oob
ctx = await get_template_context()
if is_htmx_request():
@@ -64,7 +64,7 @@ def register() -> Blueprint:
entries, has_more, pending_tickets = await _load_entries(post["id"], page)
from sexp_components import render_page_summary_cards
from sexp.sexp_components import render_page_summary_cards
html = await render_page_summary_cards(entries, has_more, pending_tickets, {}, page, view, post)
return await make_response(html, 200)
@@ -105,12 +105,8 @@ def register() -> Blueprint:
if ident["session_id"] is not None:
frag_params["session_id"] = ident["session_id"]
widget_html = await render_template(
"_types/page_summary/_ticket_widget.html",
entry=entry,
qty=qty,
ticket_url=f"/{g.post_slug}/tickets/adjust",
)
from sexp.sexp_components import render_ticket_widget
widget_html = render_ticket_widget(entry, qty, f"/{g.post_slug}/tickets/adjust")
mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False)
return await make_response(widget_html + mini_html, 200)

View File

@@ -45,7 +45,7 @@ def register():
pay_ctx = await _load_payment_ctx()
from shared.sexp.page import get_template_context
from sexp_components import render_payments_page, render_payments_oob
from sexp.sexp_components import render_payments_page, render_payments_oob
ctx = await get_template_context()
ctx.update(pay_ctx)
@@ -80,8 +80,11 @@ def register():
await call_action("blog", "update-page-config", payload=payload)
ctx = await _load_payment_ctx()
html = await render_template("_types/payments/_main_panel.html", **ctx)
from shared.sexp.page import get_template_context
from sexp.sexp_components import render_payments_panel
ctx = await get_template_context()
ctx.update(await _load_payment_ctx())
html = render_payments_panel(ctx)
return await make_response(html)
return bp

View File

@@ -74,12 +74,8 @@ def register():
slot = await svc_get_slot(g.s, slot_id)
if not slot:
return await make_response("Not found", 404)
html = await render_template(
"_types/slot/_main_panel.html",
slot=slot,
#post=g.post_data['post'],
#calendar=g.calendar,
)
from sexp.sexp_components import render_slot_main_panel
html = render_slot_main_panel(slot, g.calendar)
return await make_response(html)
@bp.delete("/")
@@ -88,7 +84,8 @@ def register():
async def slot_delete(slot_id: int, **kwargs):
await svc_delete_slot(g.s, slot_id)
slots = await svc_list_slots(g.s, g.calendar.id)
html = await render_template("_types/slots/_man_panel.html", calendar=g.calendar, slots=slots)
from sexp.sexp_components import render_slots_table
html = render_slots_table(slots, g.calendar)
return await make_response(html)
@bp.put("/")
@@ -170,11 +167,8 @@ def register():
}
), 422
html = await render_template(
"_types/slot/_main_panel.html",
slot=slot,
oob=True,
)
from sexp.sexp_components import render_slot_main_panel
html = render_slot_main_panel(slot, g.calendar, oob=True)
return await make_response(html)

View File

@@ -128,7 +128,9 @@ def register():
}), 422
# Success → re-render the slots table
html = await render_template("_types/slots/_main_panel.html")
slots = await svc_list_slots(g.s, g.calendar.id)
from sexp.sexp_components import render_slots_table
html = render_slots_table(slots, g.calendar)
return await make_response(html)

View File

@@ -71,7 +71,7 @@ def register() -> Blueprint:
}
from shared.sexp.page import get_template_context
from sexp_components import render_ticket_admin_page, render_ticket_admin_oob
from sexp.sexp_components import render_ticket_admin_page, render_ticket_admin_oob
ctx = await get_template_context()
if not is_htmx_request():
@@ -100,11 +100,8 @@ def register() -> Blueprint:
tickets = await get_tickets_for_entry(g.s, entry_id)
html = await render_template(
"_types/ticket_admin/_entry_tickets.html",
entry=entry,
tickets=tickets,
)
from sexp.sexp_components import render_entry_tickets_admin
html = render_entry_tickets_admin(entry, tickets)
return await make_response(html, 200)
@bp.get("/lookup/")
@@ -119,19 +116,12 @@ def register() -> Blueprint:
)
ticket = await get_ticket_by_code(g.s, code)
from sexp.sexp_components import render_lookup_result
if not ticket:
html = await render_template(
"_types/ticket_admin/_lookup_result.html",
ticket=None,
error="Ticket not found",
)
html = render_lookup_result(None, "Ticket not found")
return await make_response(html, 200)
html = await render_template(
"_types/ticket_admin/_lookup_result.html",
ticket=ticket,
error=None,
)
html = render_lookup_result(ticket, None)
return await make_response(html, 200)
@bp.post("/<code>/checkin/")
@@ -141,22 +131,13 @@ def register() -> Blueprint:
"""Check in a ticket by its code."""
success, error = await checkin_ticket(g.s, code)
from sexp.sexp_components import render_checkin_result
if not success:
html = await render_template(
"_types/ticket_admin/_checkin_result.html",
success=False,
error=error,
ticket=None,
)
html = render_checkin_result(False, error, None)
return await make_response(html, 200)
ticket = await get_ticket_by_code(g.s, code)
html = await render_template(
"_types/ticket_admin/_checkin_result.html",
success=True,
error=None,
ticket=ticket,
)
html = render_checkin_result(True, None, ticket)
return await make_response(html, 200)
return bp

View File

@@ -66,9 +66,11 @@ def register():
if not ticket_type:
return await make_response("Not found", 404)
html = await render_template(
"_types/ticket_type/_main_panel.html",
ticket_type=ticket_type,
from sexp.sexp_components import render_ticket_type_main_panel
va = request.view_args or {}
html = render_ticket_type_main_panel(
ticket_type, g.entry, g.calendar,
va.get("day"), va.get("month"), va.get("year"),
)
return await make_response(html)
@@ -132,9 +134,11 @@ def register():
return await make_response("Not found", 404)
# Return updated view with OOB flag
html = await render_template(
"_types/ticket_type/_main_panel.html",
ticket_type=ticket_type,
from sexp.sexp_components import render_ticket_type_main_panel
va = request.view_args or {}
html = render_ticket_type_main_panel(
ticket_type, g.entry, g.calendar,
va.get("day"), va.get("month"), va.get("year"),
oob=True,
)
return await make_response(html)
@@ -150,9 +154,11 @@ def register():
# Re-render the ticket types list
ticket_types = await svc_list_ticket_types(g.s, g.entry.id)
html = await render_template(
"_types/ticket_types/_main_panel.html",
ticket_types=ticket_types
from sexp.sexp_components import render_ticket_types_table
va = request.view_args or {}
html = render_ticket_types_table(
ticket_types, g.entry, g.calendar,
va.get("day"), va.get("month"), va.get("year"),
)
return await make_response(html)

View File

@@ -108,7 +108,13 @@ def register():
)
# Success → re-render the ticket types table
html = await render_template("_types/ticket_types/_main_panel.html")
ticket_types = await svc_list_ticket_types(g.s, g.entry.id)
from sexp.sexp_components import render_ticket_types_table
va = request.view_args or {}
html = render_ticket_types_table(
ticket_types, g.entry, g.calendar,
va.get("day"), va.get("month"), va.get("year"),
)
return await make_response(html)
@bp.get("/add")

View File

@@ -51,7 +51,7 @@ def register() -> Blueprint:
)
from shared.sexp.page import get_template_context
from sexp_components import render_tickets_page, render_tickets_oob
from sexp.sexp_components import render_tickets_page, render_tickets_oob
ctx = await get_template_context()
if not is_htmx_request():
@@ -82,7 +82,7 @@ def register() -> Blueprint:
return await make_response("Ticket not found", 404)
from shared.sexp.page import get_template_context
from sexp_components import render_ticket_detail_page, render_ticket_detail_oob
from sexp.sexp_components import render_ticket_detail_page, render_ticket_detail_oob
ctx = await get_template_context()
if not is_htmx_request():
@@ -169,13 +169,20 @@ def register() -> Blueprint:
remaining = await get_available_ticket_count(g.s, entry_id)
all_tickets = await get_tickets_for_entry(g.s, entry_id)
html = await render_template(
"_types/tickets/_buy_result.html",
entry=entry,
created_tickets=created,
remaining=remaining,
all_tickets=all_tickets,
)
# Compute cart count for OOB mini-cart update
from shared.infrastructure.data_client import fetch_data
from shared.contracts.dtos import CartSummaryDTO, dto_from_dict
summary_params = {}
if ident["user_id"] is not None:
summary_params["user_id"] = ident["user_id"]
if ident["session_id"] is not None:
summary_params["session_id"] = ident["session_id"]
raw_summary = await fetch_data("cart", "cart-summary", params=summary_params, required=False)
summary = dto_from_dict(CartSummaryDTO, raw_summary) if raw_summary else CartSummaryDTO()
cart_count = summary.count + summary.calendar_count + summary.ticket_count
from sexp.sexp_components import render_buy_result
html = render_buy_result(entry, created, remaining, cart_count)
return await make_response(html, 200)
@bp.post("/adjust/")
@@ -298,14 +305,10 @@ def register() -> Blueprint:
summary = dto_from_dict(CartSummaryDTO, raw_summary) if raw_summary else CartSummaryDTO()
cart_count = summary.count + summary.calendar_count + summary.ticket_count
html = await render_template(
"_types/tickets/_adjust_response.html",
entry=entry,
ticket_remaining=ticket_remaining,
ticket_sold_count=ticket_sold_count,
user_ticket_count=user_ticket_count,
user_ticket_counts_by_type=user_ticket_counts_by_type,
cart_count=cart_count,
from sexp.sexp_components import render_adjust_response
html = render_adjust_response(
entry, ticket_remaining, ticket_sold_count,
user_ticket_count, user_ticket_counts_by_type, cart_count,
)
return await make_response(html, 200)

0
events/sexp/__init__.py Normal file
View File

File diff suppressed because it is too large Load Diff