""" Account service s-expression page components. Renders login, device auth, and check-email pages. Dashboard and newsletters are now fully handled by .sx defcomps called from defpage expressions. """ from __future__ import annotations import os from typing import Any from shared.sx.jinja_bridge import load_service_components from shared.sx.helpers import ( render_to_sx, root_header_sx, full_page_sx, ) # Load account-specific .sx components + handlers at import time load_service_components(os.path.dirname(os.path.dirname(__file__)), service_name="account") # --------------------------------------------------------------------------- # Public API: Auth pages (login, device, check_email) # --------------------------------------------------------------------------- async def render_login_page(ctx: dict) -> str: """Full page: login form.""" error = ctx.get("error", "") email = ctx.get("email", "") hdr = await root_header_sx(ctx) content = await render_to_sx("account-login-content", error=error or None, email=email) return await full_page_sx(ctx, header_rows=hdr, content=content, meta_html='Login \u2014 Rose Ash') async def render_device_page(ctx: dict) -> str: """Full page: device authorization form.""" error = ctx.get("error", "") code = ctx.get("code", "") hdr = await root_header_sx(ctx) content = await render_to_sx("account-device-content", error=error or None, code=code) return await full_page_sx(ctx, header_rows=hdr, content=content, meta_html='Authorize Device \u2014 Rose Ash') async def render_device_approved_page(ctx: dict) -> str: """Full page: device approved.""" hdr = await root_header_sx(ctx) content = await render_to_sx("account-device-approved") return await full_page_sx(ctx, header_rows=hdr, content=content, meta_html='Device Authorized \u2014 Rose Ash') async def render_check_email_page(ctx: dict) -> str: """Full page: check email after magic link sent.""" email = ctx.get("email", "") email_error = ctx.get("email_error") hdr = await root_header_sx(ctx) content = await render_to_sx("account-check-email-content", email=email, email_error=email_error) return await full_page_sx(ctx, header_rows=hdr, content=content, meta_html='Check your email \u2014 Rose Ash') # --------------------------------------------------------------------------- # Public API: Fragment renderers for POST handlers # --------------------------------------------------------------------------- async def render_newsletter_toggle(un) -> str: """Render a newsletter toggle switch for POST response.""" from shared.browser.app.csrf import generate_csrf_token nid = un.newsletter_id from quart import g account_url_fn = getattr(g, "_account_url", None) if account_url_fn is None: from shared.infrastructure.urls import account_url account_url_fn = account_url toggle_url = account_url_fn(f"/newsletter/{nid}/toggle/") csrf = generate_csrf_token() if un.subscribed: bg = "bg-emerald-500" translate = "translate-x-6" checked = "true" else: bg = "bg-stone-300" translate = "translate-x-1" checked = "false" return await render_to_sx( "account-newsletter-toggle", id=f"nl-{nid}", url=toggle_url, hdrs=f'{{"X-CSRFToken": "{csrf}"}}', target=f"#nl-{nid}", cls=f"relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2 {bg}", checked=checked, knob_cls=f"inline-block h-4 w-4 rounded-full bg-white shadow transform transition-transform {translate}", )