feat(email-templates): tests, docs, and fix quote_verification sample data (subtask 8)

- Add 50 tests in test_email_templates.py:
  - TestRenderEmailTemplate: all 11 registry templates render in EN + DE
    without error; checks DOCTYPE, wordmark, font, CTA color, template-
    specific content (heat badges, brief rows, weekly digest loop, etc.)
    and registry structure
  - TestEmailGalleryRoutes: access control, gallery list (all labels
    present, preview links), preview pages (EN/DE/nonexistent/invalid-lang),
    compose preview endpoint (plain + wrapped + empty body)
- Fix _quote_verification_sample: add missing recap_parts key — StrictUndefined
  raised on the {% if recap_parts %} check when the variable was absent
- Update CHANGELOG.md: document email template system (renderer, base,
  macros, 11 templates, registry, gallery, compose preview, removed helpers)
- Update PROJECT.md: add email template system + gallery to Done section

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-25 12:24:52 +01:00
parent fb83f432db
commit 578a409893
4 changed files with 264 additions and 0 deletions

View File

@@ -7,6 +7,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
### Added
- **Email template system** — all 11 transactional emails migrated from inline f-string HTML in `worker.py` to Jinja2 templates:
- **Standalone renderer** (`email_templates.py`) — `render_email_template()` uses a module-level `jinja2.Environment` with `autoescape=True`, works outside Quart request context (worker process); `tformat` filter mirrors the one in `app.py`
- **`_base.html`** — branded shell (dark header, 3px blue accent, white card body, footer with tagline + copyright); replaces the old `_email_wrap()` helper
- **`_macros.html`** — reusable Jinja2 macros: `email_button`, `heat_badge`, `heat_badge_sm`, `section_heading`, `info_box`
- **11 email templates**: `magic_link`, `quote_verification`, `welcome`, `waitlist_supplier`, `waitlist_general`, `lead_matched`, `lead_forward`, `lead_match_notify`, `weekly_digest`, `business_plan`, `admin_compose`
- **`EMAIL_TEMPLATE_REGISTRY`** — dict mapping slug → `{template, label, description, email_type, sample_data}` with realistic sample data callables for each template
- **Admin email gallery** (`/admin/emails/gallery`) — card grid of all email types; preview page with EN/DE language toggle renders each template in a sandboxed iframe (`srcdoc`); "View in sent log →" cross-link; gallery link added to admin sidebar
- **Compose live preview** — two-column compose layout: form on the left, HTMX-powered preview iframe on the right; `hx-trigger="input delay:500ms"` on the textarea; `POST /admin/emails/compose/preview` endpoint supports plain body or branded wrapper via `wrap` checkbox
- 50 new tests covering all template renders (EN + DE), registry structure, gallery routes (access control, list, preview, lang fallback), and compose preview endpoint
### Removed
- `_email_wrap()` and `_email_button()` helper functions removed from `worker.py` — replaced by templates
- **Marketplace admin dashboard** (`/admin/marketplace`) — single-screen health view for the two-sided market:
- **Lead funnel** — total / verified-new (ready to unlock) / unlocked / won / conversion rate
- **Credit economy** — total credits issued, consumed (lead unlocks), outstanding balance across all paid suppliers, 30-day burn rate