DB: - migration 006 — cauldron_households (mirrors Mealie household), members - migration 007 — cauldron_meal_plans (per household per week, lock state) - new helpers: upsert_household, add_household_member, get_user_household_id, list_household_member_subs, get_or_create_plan, lock_plan, auto_lock_past_unlocked_plans, household_scoreboard, household_streak, list_household_pick_slugs, list_household_picks_with_pickers Backend: - sync_user_household() — pulls Mealie's /api/users/self, upserts the household row, ensures membership. Fires on /connect-mealie POST and lazy on every /me / /picks / /plan / /recipes load. - current_household_id() helper used by all user-facing routes - /recipes + /api/recipes.json now mark items.picked=True if ANYONE in the household has pinned (shared pool, not per-user) - /picks now renders household-pooled view with attribution (who pinned what) - /plan replaces stub: shows current week's lock state + lock button + scoreboard + streak. POST /api/plan/lock locks this week's plan with reason='user'. Past unlocked weeks auto-lock on read with reason='auto'. - /list still stub (v0.3 territory) UI: - picks.html: each pick shows '🍄 pinned by <name(s)>' attribution row, unpin button only on your own picks, household_size in lede - plan.html: NEW. Lock state pill, lock button (open weeks only), scoreboard table with rank/wins/last_win, streak ribbon ('🔥 abby on a 3-week run') if streak >= 2 - me.html: shows household name + member count Locking semantics match Cobb's pick: - (c) both — user-lock = scoreboard win, auto-lock past calendar = no win. Auto-lock fires lazily on /plan view (no cron needed for v0.2). - Picks pool = (a) shared across household. - Game shape = medium (locked-by + tally + streak counter, room for richer badges/notifs in v0.4).
57 lines
2.2 KiB
HTML
57 lines
2.2 KiB
HTML
{% extends "_base.html" %}
|
|
{% block title %}{{ user.name or user.email }} · Cauldron{% endblock %}
|
|
{% block content %}
|
|
|
|
<div class="page-head">
|
|
<div class="crumb">// account</div>
|
|
<h1><span class="accent">{{ user.name or user.email.split('@')[0] }}</span></h1>
|
|
<div class="lede">welcome back to the coven.</div>
|
|
</div>
|
|
|
|
<section class="panel">
|
|
<div class="panel-head">
|
|
<h2>identity</h2>
|
|
<span class="ctx">authentik</span>
|
|
</div>
|
|
<dl class="kv">
|
|
<dt>email</dt><dd>{{ user.email }}</dd>
|
|
<dt>subject</dt><dd>{{ user.sub }}</dd>
|
|
</dl>
|
|
</section>
|
|
|
|
<section class="panel green">
|
|
<div class="panel-head">
|
|
<h2>mealie</h2>
|
|
{% if connected %}<span class="pill pill-ok">connected</span>{% else %}<span class="pill pill-warn">not connected</span>{% endif %}
|
|
</div>
|
|
|
|
{% if connected and mealie_user %}
|
|
<dl class="kv">
|
|
<dt>logged in as</dt><dd>{{ mealie_user.username or mealie_user.email }}</dd>
|
|
<dt>full name</dt><dd>{{ mealie_user.fullName or '—' }}</dd>
|
|
<dt>role</dt><dd>{{ 'admin' if mealie_user.admin else 'member' }}</dd>
|
|
{% if mealie_user.household %}
|
|
<dt>household</dt><dd>{{ mealie_user.household.name or mealie_user.household.slug }} · {{ household_size }} {% if household_size == 1 %}member{% else %}members{% endif %}</dd>
|
|
{% endif %}
|
|
</dl>
|
|
<form method="post" action="/disconnect-mealie" class="btn-row">
|
|
<button class="btn btn-purple" type="submit">Disconnect</button>
|
|
<span class="muted">revoking on mealie's side also works.</span>
|
|
</form>
|
|
{% elif connected %}
|
|
<p class="muted">token stored, but mealie didn't return profile data. probably revoked or rotated.</p>
|
|
<form method="post" action="/disconnect-mealie" class="btn-row">
|
|
<button class="btn btn-purple" type="submit">Reset</button>
|
|
</form>
|
|
{% else %}
|
|
<p>connect mealie so cauldron can act on your behalf — your recipes, your meal plan, your shopping list. one-time, ~30 seconds.</p>
|
|
<p><a class="btn btn-primary" href="/connect-mealie">Connect mealie →</a></p>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<hr>
|
|
<form method="post" action="/logout">
|
|
<button class="btn" type="submit">Sign out</button>
|
|
</form>
|
|
|
|
{% endblock %}
|