Files
vermietungs-tool/app/templates/base.html
T
BlackMarkandClaude Opus 5.5 45424e6fd6 Vermietungs-Tool
A local web app for a small room-rental business in Austria: guest register,
room ledger, occupancy plan, invoices, the monthly tourist-tax report and the
quarterly VAT list. Application code only; it ships no data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 16:52:27 +01:00

63 lines
3.6 KiB
HTML

<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ t('app_title') }}</title>
{# a house emoji as favicon: kills the browser's /favicon.ico 404 on every page load #}
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🏠</text></svg>">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script data-fp="{{ db_fp }}">
// Re-apply the grid layouts measured on an earlier visit BEFORE the tables parse, so the browser
// never has to lay out thousands of rows at once (grids.js stores them, keyed by a db fingerprint —
// any data change re-measures). See freezeLayout() in grids.js.
(function () {
try {
var fp = document.currentScript.dataset.fp;
window.__gridfp = fp;
window.__pregrids = {};
for (var i = localStorage.length - 1; i >= 0; i--) {
var k = localStorage.key(i);
if (k.indexOf("grid:") !== 0) continue;
var v = JSON.parse(localStorage.getItem(k));
if (v.v !== 5) { localStorage.removeItem(k); continue; } // older stored format: re-measure
if (v.fp === fp && v.vw === window.innerWidth) {
var s = document.createElement("style");
s.textContent = v.css;
document.head.appendChild(s);
window.__pregrids[k.slice(5)] = { rowH: v.rowH || 1, widths: v.widths || null };
} else if (v.fp !== fp) {
localStorage.removeItem(k);
}
}
} catch (e) { /* no stored layout -> the table measures itself after load */ }
})();
</script>
<script>window.GRID_TEXT = {{ {'search': t('print_search'), 'rows': t('print_rows'), 'rows_one': t('print_rows_one'),
'date': t('print_date'), 'pin': t('pin_tip'), 'unpin': t('unpin_tip')}|tojson }};</script>
<script src="{{ url_for('static', filename='grids.js') }}" defer></script>
</head>
<body>
<header class="topbar">
<div class="brand">{{ t('app_title') }}</div>
<nav>
<a href="{{ url_for('home') }}" class="{{ 'active' if request.endpoint == 'home' }}">{{ t('nav_home') }}</a>
<a href="{{ url_for('register') }}" class="{{ 'active' if request.endpoint in ('register','stay_form') }}">{{ t('nav_register') }}</a>
<a href="{{ url_for('ledger') }}" class="{{ 'active' if request.endpoint == 'ledger' }}">{{ t('nav_ledger') }}</a>
<a href="{{ url_for('plan_page') }}" class="{{ 'active' if request.endpoint == 'plan_page' }}">{{ t('nav_plan') }}</a>
<a href="{{ url_for('invoices') }}" class="{{ 'active' if request.endpoint and request.endpoint.startswith('invoice') }}">{{ t('nav_invoices') }}</a>
<a href="{{ url_for('clients') }}" class="{{ 'active' if request.endpoint and request.endpoint.startswith('client') }}">{{ t('nav_clients') }}</a>
<a href="{{ url_for('tvb_page') }}" class="{{ 'active' if request.endpoint == 'tvb_page' }}">{{ t('nav_tvb') }}</a>
<a href="{{ url_for('vat_page') }}" class="{{ 'active' if request.endpoint == 'vat_page' }}">{{ t('nav_vat') }}</a>
<a href="{{ url_for('quality_page') }}" class="{{ 'active' if request.endpoint and request.endpoint.startswith('quality') }}">{{ t('nav_quality') }}</a>
</nav>
</header>
<main class="{% block main_class %}{% endblock %}">
{% with msgs = get_flashed_messages() %}
{% if msgs %}<div class="flash">{% for m in msgs %}<div>{{ m }}</div>{% endfor %}</div>{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
</body>
</html>