"""Badge helpers, OOB helpers, formatting utilities, list containers.""" from __future__ import annotations from shared.sx.helpers import sx_call # --------------------------------------------------------------------------- # OOB header helper — delegates to shared # --------------------------------------------------------------------------- # --------------------------------------------------------------------------- # Post header helpers — thin wrapper over shared post_header_sx # --------------------------------------------------------------------------- def _clear_oob(*ids: str) -> str: """Generate OOB swaps to remove orphaned header rows/children.""" from shared.sx.helpers import sx_call return "".join(sx_call("clear-oob-div", id=i) for i in ids) # All possible header row/child IDs at each depth (deepest first) _EVENTS_DEEP_IDS = [ "entry-admin-row", "entry-admin-header-child", "entry-row", "entry-header-child", "day-admin-row", "day-admin-header-child", "day-row", "day-header-child", "calendar-admin-row", "calendar-admin-header-child", "calendar-row", "calendar-header-child", "calendars-row", "calendars-header-child", "post-admin-row", "post-admin-header-child", ] def _clear_deeper_oob(*keep_ids: str) -> str: """Clear all events header rows/children NOT in keep_ids.""" to_clear = [i for i in _EVENTS_DEEP_IDS if i not in keep_ids] return _clear_oob(*to_clear) async def _ensure_container_nav(ctx: dict) -> dict: """Fetch container_nav if not already present (for post header row).""" if ctx.get("container_nav"): return ctx post = ctx.get("post") or {} post_id = post.get("id") slug = post.get("slug", "") if not post_id: return ctx from quart import g from shared.infrastructure.fragments import fetch_fragments current_cal = getattr(g, "calendar_slug", "") or "" nav_params = { "container_type": "page", "container_id": str(post_id), "post_slug": slug, "current_calendar": current_cal, } events_nav, market_nav = await fetch_fragments([ ("events", "container-nav", nav_params), ("market", "container-nav", nav_params), ], required=False) return {**ctx, "container_nav": events_nav + market_nav} # --------------------------------------------------------------------------- # Utility # --------------------------------------------------------------------------- def _list_container(ctx: dict) -> str: styles = ctx.get("styles") or {} return getattr(styles, "list_container", "") if hasattr(styles, "list_container") else styles.get("list_container", "") def _entry_state_badge_html(state: str) -> str: """Render an entry state badge.""" state_classes = { "confirmed": "bg-emerald-100 text-emerald-800", "provisional": "bg-amber-100 text-amber-800", "ordered": "bg-sky-100 text-sky-800", "pending": "bg-stone-100 text-stone-700", "declined": "bg-red-100 text-red-800", } cls = state_classes.get(state, "bg-stone-100 text-stone-700") label = state.replace("_", " ").capitalize() return sx_call("badge", cls=cls, label=label) def _ticket_state_badge_html(state: str) -> str: """Render a ticket state badge.""" cls_map = { "confirmed": "bg-emerald-100 text-emerald-800", "checked_in": "bg-blue-100 text-blue-800", "reserved": "bg-amber-100 text-amber-800", "cancelled": "bg-red-100 text-red-800", } cls = cls_map.get(state, "bg-stone-100 text-stone-700") label = (state or "").replace("_", " ").capitalize() return sx_call("badge", cls=cls, label=label) # --------------------------------------------------------------------------- # View toggle + SVG caching # --------------------------------------------------------------------------- _LIST_SVG = None _TILE_SVG = None def _get_list_svg(): global _LIST_SVG if _LIST_SVG is None: _LIST_SVG = sx_call("list-svg") return _LIST_SVG def _get_tile_svg(): global _TILE_SVG if _TILE_SVG is None: _TILE_SVG = sx_call("tile-svg") return _TILE_SVG def _view_toggle_html(ctx: dict, view: str) -> str: """Render the list/tile view toggle bar.""" from shared.utils import route_prefix prefix = route_prefix() clh = ctx.get("current_local_href", "/") hx_select = ctx.get("hx_select_search", "#main-panel") list_href = prefix + str(clh) tile_href = prefix + str(clh) if "?" in list_href: list_href = list_href.split("?")[0] if "?" in tile_href: tile_href = tile_href.split("?")[0] + "?view=tile" else: tile_href = tile_href + "?view=tile" list_active = 'bg-stone-200 text-stone-800' if view != 'tile' else 'text-stone-400 hover:text-stone-600' tile_active = 'bg-stone-200 text-stone-800' if view == 'tile' else 'text-stone-400 hover:text-stone-600' return sx_call("view-toggle", list_href=list_href, tile_href=tile_href, hx_select=hx_select, list_cls=list_active, tile_cls=tile_active, storage_key="events_view", list_svg=_get_list_svg(), tile_svg=_get_tile_svg()) def _cart_icon_oob(count: int) -> str: """Render the OOB cart icon/badge swap.""" from quart import g blog_url_fn = getattr(g, "blog_url", None) cart_url_fn = getattr(g, "cart_url", None) site_fn = getattr(g, "site", None) logo = "" if site_fn: site_obj = site_fn() if callable(site_fn) else site_fn logo = getattr(site_obj, "logo", "") if site_obj else "" if count == 0: blog_href = blog_url_fn("/") if blog_url_fn else "/" return sx_call("events-cart-icon-logo", blog_href=blog_href, logo=logo) cart_href = cart_url_fn("/") if cart_url_fn else "/" return sx_call("events-cart-icon-badge", cart_href=cart_href, count=str(count))