diff --git a/web/src/padelnomics/templates/emails/business_plan.html b/web/src/padelnomics/templates/emails/business_plan.html new file mode 100644 index 0000000..1443d87 --- /dev/null +++ b/web/src/padelnomics/templates/emails/business_plan.html @@ -0,0 +1,11 @@ +{% extends "emails/_base.html" %} +{% from "emails/_macros.html" import email_button %} + +{% block body %} +
{{ t.email_business_plan_body }}
+{{ t.email_business_plan_includes }}
+{{ email_button(download_url, t.email_business_plan_btn) }} +{{ t.email_business_plan_quote_cta | tformat(quote_url=quote_url) }}
+{% endblock %} diff --git a/web/src/padelnomics/templates/emails/lead_forward.html b/web/src/padelnomics/templates/emails/lead_forward.html new file mode 100644 index 0000000..fdac780 --- /dev/null +++ b/web/src/padelnomics/templates/emails/lead_forward.html @@ -0,0 +1,53 @@ +{% extends "emails/_base.html" %} +{% from "emails/_macros.html" import email_button, heat_badge, section_heading %} + +{% block body %} +{# Yellow urgency banner #} +{{ t.email_lead_forward_urgency }}
+ +| {{ label }} | +{{ value }} | +
| {{ t.email_lead_forward_lbl_name }} | +{{ contact_name }} | +
| {{ t.email_lead_forward_lbl_email }} | +{{ contact_email }} | +
| {{ t.email_lead_forward_lbl_phone }} | +{{ contact_phone }} | +
| {{ t.email_lead_forward_lbl_company }} | +{{ contact_company }} | +
| {{ t.email_lead_forward_lbl_role }} | +{{ stakeholder_type }} | +
{{ t.email_lead_forward_reply_direct | tformat(contact_email=contact_email) }}
+ +{%- if cta_url %} + +{%- endif %} +{% endblock %} diff --git a/web/src/padelnomics/templates/emails/lead_match_notify.html b/web/src/padelnomics/templates/emails/lead_match_notify.html new file mode 100644 index 0000000..918625d --- /dev/null +++ b/web/src/padelnomics/templates/emails/lead_match_notify.html @@ -0,0 +1,30 @@ +{% extends "emails/_base.html" %} +{% from "emails/_macros.html" import email_button, heat_badge %} + +{% block body %} +A new project brief has been submitted that matches your service area.
+ +| Facility | +{{ facility_type }} | +
| Courts | +{{ courts }} | +
| Country | +{{ country }} | +
| Timeline | +{{ timeline or "-" }} | +
Contact details are available after unlocking. Credits required: {{ credit_cost }}.
+{{ email_button(base_url ~ "/suppliers/leads", "View lead feed") }} +{% endblock %} diff --git a/web/src/padelnomics/templates/emails/weekly_digest.html b/web/src/padelnomics/templates/emails/weekly_digest.html new file mode 100644 index 0000000..3f74930 --- /dev/null +++ b/web/src/padelnomics/templates/emails/weekly_digest.html @@ -0,0 +1,33 @@ +{% extends "emails/_base.html" %} +{% from "emails/_macros.html" import email_button, heat_badge_sm %} + +{% block body %} +New matching leads in your service area this week:
+ +| Project | +Country | +Timeline | +
|---|---|---|
| + {{ heat_badge_sm(lead.heat | upper) }} {{ lead.facility_type or "Padel" }}, {{ lead.court_count or "?" }} courts + | +{{ lead.country or "-" }} | +{{ lead.timeline or "-" }} | +
' - f'{_t("email_lead_forward_urgency", lang)}
' - f'' - f'{_t("email_lead_forward_reply_direct", lang, contact_email=contact_email)}
' - ) - # Send to supplier contact email or general contact to_email = supplier.get("contact_email") or supplier.get("contact") or "" if not to_email: @@ -458,16 +410,25 @@ async def handle_send_lead_forward_email(payload: dict) -> None: # Generate one-click "I've contacted this lead" CTA token cta_token = secrets.token_urlsafe(24) cta_url = f"{config.BASE_URL}/suppliers/leads/cta/{cta_token}" - body += ( - f'' - f'' - f'✓ Mark as contacted
' + + html = render_email_template( + "emails/lead_forward.html", + lang=lang, + heat=heat, + brief_rows=brief_rows, + contact_name=lead["contact_name"] or "-", + contact_email=contact_email, + contact_phone=lead["contact_phone"] or "-", + contact_company=lead["contact_company"] or "-", + stakeholder_type=lead["stakeholder_type"] or "-", + cta_url=cta_url, + preheader=", ".join(preheader_parts), ) await send_email( to=to_email, subject=subject, - html=_email_wrap(body, lang, preheader=", ".join(preheader_parts)), + html=html, from_addr=EMAIL_ADDRESSES["leads"], email_type="lead_forward", ) @@ -549,30 +510,22 @@ async def handle_notify_matching_suppliers(payload: dict) -> None: if not to_email: continue - body = ( - f'A new project brief has been submitted that matches your service area.
' - f'| Facility | ' - f'{facility_type} |
| Courts | ' - f'{courts} |
| Country | ' - f'{country} |
| Timeline | ' - f'{timeline or "-"} |
' - f'Contact details are available after unlocking. Credits required: {lead.get("credit_cost", "?")}.
' - f'{_email_button(f"{config.BASE_URL}/suppliers/leads", "View lead feed")}' + notify_html = render_email_template( + "emails/lead_match_notify.html", + lang=lang, + heat=heat, + country=country, + facility_type=facility_type, + courts=courts, + timeline=timeline, + credit_cost=lead.get("credit_cost", "?"), + preheader=f"New matching lead in {country}", ) await send_email( to=to_email, subject=f"[{heat}] New {facility_type} project in {country} — {courts} courts", - html=_email_wrap(body, lang, preheader=f"New matching lead in {country}"), + html=notify_html, from_addr=EMAIL_ADDRESSES["leads"], email_type="lead_match_notify", ) @@ -617,48 +570,27 @@ async def handle_send_weekly_lead_digest(payload: dict) -> None: if not new_leads: continue - lead_rows_html = "" - for ld in new_leads: - heat = (ld["heat_score"] or "cool").upper() - heat_colors = {"HOT": "#DC2626", "WARM": "#EA580C", "COOL": "#2563EB"} - hc = heat_colors.get(heat, "#2563EB") - badge = ( - f'{heat}' - ) - lead_rows_html += ( - f'New matching leads in your service area this week:
' - f'| Project | ' - f'Country | ' - f'Timeline | ' - f'
|---|
{_t("email_business_plan_body", language)}
' - f'{_t("email_business_plan_includes", language)}
' - f'{_email_button(f"{config.BASE_URL}/planner/export/{export_token}", _t("email_business_plan_btn", language))}' - f'' - f'{_t("email_business_plan_quote_cta", language, quote_url=f"{config.BASE_URL}/{language}/leads/quote")}
' + bp_html = render_email_template( + "emails/business_plan.html", + lang=language, + download_url=f"{config.BASE_URL}/planner/export/{export_token}", + quote_url=f"{config.BASE_URL}/{language}/leads/quote", + preheader=_t("email_business_plan_preheader", language), ) await send_email( to=user["email"], subject=_t("email_business_plan_subject", language), - html=_email_wrap(body, language, preheader=_t("email_business_plan_preheader", language)), + html=bp_html, from_addr=EMAIL_ADDRESSES["transactional"], email_type="business_plan", )