Files
Pivot/templates/base.html
2026-10-14 13:34:37 +02:00

148 lines
6.9 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}PIVOT{% endblock %} – {{ school_name_short|upper or 'PIVOT' }}</title>
<link rel="icon" type="image/png" href="{{ url_for('static', filename='pivot_mark.png') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='global.css') }}">
{% block head %}{% endblock %}
<style>.header-school { display: inline-block; max-width: 200px; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }</style>
{% block extra_css %}{% endblock %}
</head>
<body class="{% block body_class %}{% endblock %}">
{# ---------- Laadscherm (gedeeld) ---------- #}
<div id="loader-overlay" aria-live="polite">
<div class="spinner"></div>
<div class="loader-text" id="loader-text">{% block loader_text %}Verwerken...{% endblock %}</div>
{% block loader_sub %}{% endblock %}
</div>
{# ---------- Header ---------- #}
{% block header %}
<header class="app-header {% block header_class %}{% endblock %}">
<div class="header-left">
<a href="{{ url_for('main.dashboard') }}" class="brand" title="Naar het dashboard">
<span class="brand-mark"><img src="{{ url_for('static', filename='pivot_mark.png') }}" alt=""></span>
<span class="brand-name">PIVOT</span>
</a>
{% block header_nav %}
<a href="{{ url_for('main.dashboard') }}" class="home-btn">🏠 Home</a>
{% endblock %}
</div>
<h1 class="page-title">{% block page_title %}{% endblock %}</h1>
<div class="header-right">
{% if school %}
{% if is_superbeheerder %}
<a href="{{ url_for('scholen.overzicht') }}" class="header-user header-school" style="color:inherit;text-decoration:none" title="{{ school.naam }} – andere school kiezen">🏫 {{ school.naam }} ⇄</a>
{% elif andere_scholen %}
<select class="header-user header-school" title="Andere school kiezen" aria-label="School kiezen"
style="width:auto;color:inherit;background:transparent;border:0;cursor:pointer"
onchange="if (this.value) location.href = this.value">
<option value="" selected>🏫 {{ school.naam }} ⇄</option>
{% for s in andere_scholen %}
<option value="{{ url_for('scholen.wissel', code=s.code) }}" style="color:#1e293b">{{ s.naam }}</option>
{% endfor %}
</select>
{% else %}
<span class="header-user header-school" title="{{ school.naam }}">🏫 {{ school.naam }}</span>
{% endif %}
{% endif %}
{% if session.get('user') %}
<span class="header-user">👤 {{ session.get('user') }}</span>
{% endif %}
<form action="{{ url_for('auth.logout') }}" method="get">
<button type="submit" class="logout-btn">Uitloggen</button>
</form>
</div>
</header>
{% endblock %}
<main class="app-main {% block main_class %}{% endblock %}">
{# ---------- Flash-berichten (gedeeld) ---------- #}
{% block flashes %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="flash-container">
{% for category, message in messages %}
<div class="flash-message {{ category if category else 'info' }}" role="alert">
<span>{{ message }}</span>
<button type="button" class="flash-close" aria-label="Sluiten" onclick="this.parentElement.remove()">&times;</button>
</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endblock %}
{% block content %}{% endblock %}
</main>
{% block modals %}{% endblock %}
{% block footer %}
<footer class="app-footer">
{% if school %}{{ school.naam }} – {% endif %}PIVOT – Versie {{ version }}
</footer>
{% endblock %}
<script>
/* Gedeelde helpers – beschikbaar op elke pagina */
/* Aantal rijen per pagina in tabellen: 10 / 25 / 50 / 100 / alles (0). Standaard 25 (of de opgegeven standaard).
De keuze wordt per tabel onthouden in deze browser. */
const PER_PAGINA_KEUZES = [10, 25, 50, 100, 0];
function perPagina(sleutel, standaard = 25) {
try {
const v = localStorage.getItem('pivot.perpagina.' + sleutel);
if (v !== null && PER_PAGINA_KEUZES.includes(+v)) return +v;
} catch (e) { /* geen opslag beschikbaar */ }
return standaard;
}
function perPaginaKiezer(container, sleutel, opWijzig, standaard = 25) {
if (!container) return;
const huidig = perPagina(sleutel, standaard);
container.innerHTML = '<label class="per-pagina">Toon <select aria-label="Aantal per pagina">'
+ PER_PAGINA_KEUZES.map(n => `<option value="${n}" ${n === huidig ? 'selected' : ''}>${n || 'alles'}</option>`).join('')
+ '</select> per pagina</label>';
container.querySelector('select').addEventListener('change', e => {
const n = +e.target.value;
try { localStorage.setItem('pivot.perpagina.' + sleutel, n); } catch (err) { /* negeren */ }
opWijzig(n);
});
}
function showLoader(text) {
if (text) document.getElementById('loader-text').innerText = text;
document.getElementById('loader-overlay').style.display = 'flex';
}
function hideLoader() {
document.getElementById('loader-overlay').style.display = 'none';
}
// Loader verbergen wanneer de pagina via 'terug' uit de cache komt
window.addEventListener('pageshow', function (e) { if (e.persisted) hideLoader(); });
// Succes- en infoberichten verdwijnen na 6 seconden; foutmeldingen blijven staan
setTimeout(function () {
document.querySelectorAll('.flash-message:not(.error):not(.danger)').forEach(function (f) {
f.style.transition = 'opacity .5s ease';
f.style.opacity = '0';
setTimeout(function () { f.remove(); }, 500);
});
}, 6000);
// Escape sluit open modals
document.addEventListener('keydown', function (e) {
if (e.key !== 'Escape') return;
document.querySelectorAll('.modal, .modal-overlay').forEach(function (m) {
if (m.style.display && m.style.display !== 'none') m.style.display = 'none';
});
});
</script>
{% block scripts %}{% endblock %}
</body>
</html>