Files
agentbox-test/templates/public.html
T
agentbox ae95841b5b
CI / test-and-package (push) Successful in 40s
feat: public sharing links for households
Add hard-to-guess public URLs (/public/<token>) that show a read-only
meal status dashboard for each household. Only people with the link can
see the data — no login required.

- models.py: public_token + public_enabled columns on households,
  get_household_by_public_token(), generate_public_token(),
  set_public_enabled()
- meals.py: /public/<token> route, /admin/public-link for
  generate/disable/enable/regenerate
- templates/public.html: clean read-only public dashboard
- templates/public-not-found.html: 404 for invalid/disabled links
- templates/dashboard.html: admin UI with copy/regenerate/disable
- static/style.css: public page and URL box styles
- i18n.py: 18 new translation keys (en/fr/de)
2026-08-01 10:12:21 +00:00

78 lines
3.2 KiB
HTML

<!doctype html>
<html lang="{{ lang }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>{{ household.name }} — {{ t('Meal Tracker') }}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body class="public-page">
<nav class="navbar">
<span class="brand">🍽 {{ household.name }}</span>
<span class="nav-household">{{ viewing_date.isoformat() }}</span>
</nav>
<main class="container">
<h2 class="public-heading">{{ t("Today's Meals") }}</h2>
<div class="date-nav">
<a class="btn btn-sm" href="?date={{ prev_date.isoformat() }}">{{ t('◀ Prev') }}</a>
<span class="date-display">{{ viewing_date.isoformat() }}</span>
<a class="btn btn-sm" href="?date={{ next_date.isoformat() }}">{{ t('Next ▶') }}</a>
{% if viewing_date != today %}
<a class="btn btn-sm" href="?">Today</a>
{% endif %}
</div>
{% if not dashboard.users %}
<p class="empty-state">{{ t('No users yet.') }}</p>
{% else %}
<div class="table-wrapper">
<table class="meal-table">
<thead>
<tr>
<th>{{ t('User') }}</th>
{% for period in dashboard.periods %}
<th class="meal-col">{{ t(period.meal_type|capitalize) }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for user in dashboard.users %}
<tr>
<td class="user-cell">
{{ user.username }}
{% if user.is_admin %}<span class="admin-tag">{{ t('admin') }}</span>{% endif %}
</td>
{% for period in dashboard.periods %}
{% set resp = user.responses[period.meal_type] %}
<td class="response-cell status-{{ resp.status }}{% if resp.changed_at %} changed-mind{% endif %}">
<span class="badge badge-{{ resp.status }}">{{ t('Home') if resp.status == 'yes' else (t('Out') if resp.status == 'no' else t('—')) }}</span>
{% if resp.changed_at %}
<div class="changed-badge" title="{{ t('Changed mind at {time}', time=resp.changed_at) }}">↻ {{ resp.changed_at[11:16] }}</div>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<p class="public-footer">
{{ t('Meal Tracker') }}
</p>
</main>
<footer class="lang-footer">
{% for code, name in {'en': 'English', 'fr': 'Français', 'de': 'Deutsch'}.items() %}
<a href="?lang={{ code }}"
class="lang-link{% if lang == code %} lang-active{% endif %}"
aria-label="{{ name }}">{{ code.upper() }}</a>
{% endfor %}
</footer>
</body>
</html>