- CSS variables for dark theme: surface, text, borders, accents - Dark mode overrides for all hardcoded colors (buttons, tags, flashes, inputs, table headers, code blocks) - Toggle button (☀️/🌙) in navbar, saved to localStorage - Inline script applies saved theme before page render (no flash) - Applied to both base.html and public.html - System color-scheme meta tag for native browser chrome
105 lines
4.3 KiB
HTML
105 lines
4.3 KiB
HTML
<!doctype html>
|
|
<html lang="{{ lang }}" data-theme="light">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="robots" content="noindex, nofollow">
|
|
<meta name="color-scheme" content="light dark">
|
|
<title>{{ household.name }} — {{ t('Meal Tracker') }}</title>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
|
<script>
|
|
(function() {
|
|
var t = localStorage.getItem('mealtracker-theme');
|
|
if (t === 'dark') document.documentElement.setAttribute('data-theme', 'dark');
|
|
})();
|
|
</script>
|
|
</head>
|
|
<body class="public-page">
|
|
<nav class="navbar">
|
|
<span class="brand">🍽 {{ household.name }}</span>
|
|
<div class="nav-right">
|
|
<button class="theme-toggle" id="theme-toggle" title="Toggle dark mode" aria-label="Toggle dark mode">☀️</button>
|
|
<span class="nav-household">{{ viewing_date.isoformat() }}</span>
|
|
</div>
|
|
</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>
|
|
|
|
<script>
|
|
(function() {
|
|
var btn = document.getElementById('theme-toggle');
|
|
var html = document.documentElement;
|
|
function setIcon() {
|
|
btn.textContent = html.getAttribute('data-theme') === 'dark' ? '🌙' : '☀️';
|
|
}
|
|
setIcon();
|
|
btn.addEventListener('click', function() {
|
|
var next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
html.setAttribute('data-theme', next);
|
|
localStorage.setItem('mealtracker-theme', next);
|
|
setIcon();
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|