feat(meals): suggest complementary sides
CI / backend (pytest + alembic) (push) Has been cancelled
CI / frontend (build) (push) Has been cancelled

This commit is contained in:
2026-06-29 14:59:30 -07:00
parent 18d7300b57
commit 7f5757094e
12 changed files with 294 additions and 9 deletions
@@ -36,6 +36,26 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
def _suggested_sides_html(components: dict | None) -> str:
sides = (components or {}).get("suggested_sides")
if not isinstance(sides, dict):
return ""
items = sides.get("items")
if isinstance(items, list) and items:
text = "Pair with " + " + ".join(str(item) for item in items[:2])
else:
pair = [sides.get("vegetable"), sides.get("carb")]
pair = [str(part) for part in pair if part]
if not pair:
return ""
text = "Add " + " + ".join(pair)
return (
"<p style='font-size:13px;background:#ecfdf5;color:#065f46;"
"padding:8px;border-radius:6px;margin:8px 0'>"
f"{html.escape(text)}</p>"
)
def step_scrape(run: "WeeklyRun", db: "Session") -> None:
if run.scraped_at is not None:
logger.info("step_scrape: already done for %s, skipping", run.week_start_date)
@@ -273,6 +293,7 @@ def step_email(run: "WeeklyRun", db: "Session") -> None:
f"<p style='font-size:13px;color:#888'>Est. ~${est_cost_per_serving:.2f}/serving</p>"
if est_cost_total > 0 else ""
)
sides_block = _suggested_sides_html(item.components)
item_html_parts.append(
f'<div style="border:1px solid #e5e7eb;border-radius:8px;padding:16px;margin-bottom:12px">'
@@ -280,6 +301,7 @@ def step_email(run: "WeeklyRun", db: "Session") -> None:
f'<h3 style="margin:8px 0 4px">{recipe_name}</h3>'
f'{ing_block}'
f'{instructions_block}'
f'{sides_block}'
f'{cost_block}'
f'<div style="margin-top:8px;display:flex;flex-wrap:wrap;gap:6px">'
f'<a href="{vote_url}&amp;scope=approve" style="display:inline-block;padding:8px 14px;'