183 lines
8.9 KiB
HTML
183 lines
8.9 KiB
HTML
|
|
{% extends "base.html" %}
|
|||
|
|
{% block title %}Dashboard — Admin{% endblock %}
|
|||
|
|
{% block content %}
|
|||
|
|
|
|||
|
|
<div class="section-header">
|
|||
|
|
<h1>Dashboard</h1>
|
|||
|
|
<div>
|
|||
|
|
<a href="{{ url_for('admin.profile_liste') }}" class="btn btn-secondary">Profile</a>
|
|||
|
|
<a href="{{ url_for('admin.admin_logout') }}" class="btn btn-secondary">Admin-Logout</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{# ====== Schnell-Zahlen ====== #}
|
|||
|
|
<div class="grid" style="grid-template-columns: repeat(3, 1fr); gap: 1rem;">
|
|||
|
|
<div class="stat-card">
|
|||
|
|
<div class="number">{{ zahlen.heute_n }}</div>
|
|||
|
|
<div class="label">heute eingecheckt</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="stat-card" style="{% if zahlen.review_n > 0 %}border: 2px solid var(--warning);{% endif %}">
|
|||
|
|
<div class="number" style="{% if zahlen.review_n > 0 %}color: var(--warning);{% endif %}">{{ zahlen.review_n }}</div>
|
|||
|
|
<div class="label">wartet auf Review</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="stat-card" style="{% if zahlen.drucker_problem_n > 0 %}border: 2px solid var(--danger);{% endif %}">
|
|||
|
|
<div class="number" style="{% if zahlen.drucker_problem_n > 0 %}color: var(--danger);{% endif %}">{{ zahlen.drucker_problem_n }}</div>
|
|||
|
|
<div class="label">Drucker-Problem</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{# ====== Sektion 1: Wer ist heute hier ====== #}
|
|||
|
|
<div class="card" style="margin-top: 1.5rem;">
|
|||
|
|
<h2>👋 Wer ist heute hier ({{ heute|length }})</h2>
|
|||
|
|
{% if heute %}
|
|||
|
|
<table>
|
|||
|
|
<thead>
|
|||
|
|
<tr><th></th><th>Vorname</th><th>Modus</th><th>Notiz</th><th>seit</th><th></th></tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for h in heute %}
|
|||
|
|
<tr>
|
|||
|
|
<td style="font-size: 1.6rem;">{{ tier_emoji(h.tier) }}</td>
|
|||
|
|
<td><strong>{{ h.vorname }}</strong></td>
|
|||
|
|
<td>
|
|||
|
|
{% if h.modus == 'weiter_wie_bisher' %}Arbeitet weiter
|
|||
|
|
{% elif h.modus == 'neues_projekt' %}🆕 Neues Projekt
|
|||
|
|
{% elif h.modus == 'onboarding' %}📚 Onboarding
|
|||
|
|
{% elif h.modus == 'drucken' %}🖨️ Drucken
|
|||
|
|
{% elif h.modus == 'helfen' %}🤝 Hilft anderen
|
|||
|
|
{% else %}{{ h.modus }}{% endif %}
|
|||
|
|
</td>
|
|||
|
|
<td style="font-style: italic; color: var(--text-light); font-size: 0.9rem;">{{ h.freitext or "" }}</td>
|
|||
|
|
<td style="font-size: 0.85rem; color: var(--text-light);">{{ h.erstellt_am[11:16] if h.erstellt_am else '' }}</td>
|
|||
|
|
<td>
|
|||
|
|
<details>
|
|||
|
|
<summary class="btn btn-secondary" style="padding: 0.2rem 0.5rem; font-size: 0.8rem; list-style: none;">Notiz schreiben</summary>
|
|||
|
|
<form method="post" action="{{ url_for('admin.profil_notiz', profil_id=h.profil_id) }}" style="margin-top: 0.4rem; display: flex; gap: 0.3rem;">
|
|||
|
|
<input type="text" name="text" placeholder="Kurze Nachricht …" required
|
|||
|
|
style="padding: 0.3rem; border: 1px solid var(--border); border-radius: 4px; width: 220px;">
|
|||
|
|
<button class="btn btn-primary" style="padding: 0.3rem 0.6rem; font-size: 0.85rem;">senden</button>
|
|||
|
|
</form>
|
|||
|
|
</details>
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
{% else %}
|
|||
|
|
<p style="color: var(--text-light);">Noch keiner heute eingecheckt.</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{# ====== Sektion 2: Wartet auf Review ====== #}
|
|||
|
|
<div class="card">
|
|||
|
|
<h2>⏳ Wartet auf Review ({{ review|length }})</h2>
|
|||
|
|
{% if review %}
|
|||
|
|
<table>
|
|||
|
|
<thead><tr><th></th><th>Projekt</th><th>SuS</th><th>Selbsteinschaetzung</th><th>abgeschlossen</th><th></th></tr></thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for r in review %}
|
|||
|
|
<tr>
|
|||
|
|
<td style="font-size: 1.4rem;">{{ tier_emoji(r.tier) }}</td>
|
|||
|
|
<td><strong>{{ r.titel }}</strong></td>
|
|||
|
|
<td>{{ r.vorname }}</td>
|
|||
|
|
<td>
|
|||
|
|
{% if r.selbsteinschaetzung == 'zufrieden' %}🟢 zufrieden
|
|||
|
|
{% elif r.selbsteinschaetzung == 'mittel' %}🟡 mittel
|
|||
|
|
{% elif r.selbsteinschaetzung == 'gelernt' %}🔴 gelernt
|
|||
|
|
{% endif %}
|
|||
|
|
</td>
|
|||
|
|
<td style="font-size: 0.85rem; color: var(--text-light);">{{ r.abgeschlossen_am[:10] if r.abgeschlossen_am else '' }}</td>
|
|||
|
|
<td>
|
|||
|
|
<a href="#" class="btn btn-primary" style="padding: 0.2rem 0.6rem; font-size: 0.85rem; opacity: 0.5;" title="Etappe 6">Reviewen</a>
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
{% else %}
|
|||
|
|
<p style="color: var(--text-light);">Keine offenen Reviews. <em>(Selbstlern-Loop kommt mit Etappe 6.)</em></p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{# ====== Sektion 3: Drucker-Status ====== #}
|
|||
|
|
<div class="card">
|
|||
|
|
<h2>🖨️ Drucker-Status</h2>
|
|||
|
|
<div class="grid" style="grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.8rem;">
|
|||
|
|
{% for d in drucker %}
|
|||
|
|
<div class="drucker-kachel drucker-{{ d.status or 'idle' }}">
|
|||
|
|
<h3 style="margin-bottom: 0.2rem;">{{ d.name }}</h3>
|
|||
|
|
<p style="font-size: 0.85rem; color: var(--text-light); margin: 0;">
|
|||
|
|
{{ d.modell }}{% if not d.geschlossenes_gehaeuse %} · <span style="color: var(--danger);">offen</span>{% endif %}
|
|||
|
|
</p>
|
|||
|
|
<p style="margin-top: 0.5rem; font-weight: 600;">
|
|||
|
|
{% if d.status == 'printing' %}🟢 drucken
|
|||
|
|
{% elif d.status == 'idle' %}⚪ idle
|
|||
|
|
{% elif d.status == 'paused' %}🟡 pausiert
|
|||
|
|
{% elif d.status == 'finished' %}✅ fertig
|
|||
|
|
{% elif d.status == 'failed' %}🔴 Fehler
|
|||
|
|
{% elif d.status == 'offline' %}⚫ offline
|
|||
|
|
{% else %}⚪ kein Status (API noch nicht in Etappe 5){% endif %}
|
|||
|
|
</p>
|
|||
|
|
{% if d.job_name %}<p style="font-size: 0.85rem;">{{ d.job_name }}</p>{% endif %}
|
|||
|
|
{% if d.progress_pct %}<p style="font-size: 0.85rem;">{{ d.progress_pct|round|int }} %{% if d.restzeit_min %} · noch {{ d.restzeit_min }} min{% endif %}</p>{% endif %}
|
|||
|
|
{% if d.fehlermeldung %}<p style="font-size: 0.85rem; color: var(--danger);">{{ d.fehlermeldung }}</p>{% endif %}
|
|||
|
|
{% if d.notiz %}<p style="font-size: 0.8rem; color: var(--text-light); margin-top: 0.5rem;">ℹ️ {{ d.notiz }}</p>{% endif %}
|
|||
|
|
</div>
|
|||
|
|
{% endfor %}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{# ====== Sektion 4: Wer haengt fest ====== #}
|
|||
|
|
<div class="card">
|
|||
|
|
<h2>💤 Wer hängt fest (>2 Wochen kein Check-In)</h2>
|
|||
|
|
{% if haengen_fest %}
|
|||
|
|
<table>
|
|||
|
|
<thead><tr><th></th><th>Vorname</th><th>letzter Check-In</th><th></th></tr></thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for h in haengen_fest %}
|
|||
|
|
<tr>
|
|||
|
|
<td style="font-size: 1.4rem;">{{ tier_emoji(h.tier) }}</td>
|
|||
|
|
<td><strong>{{ h.vorname }}</strong></td>
|
|||
|
|
<td style="font-size: 0.85rem; color: var(--text-light);">
|
|||
|
|
{% if h.letzter_check_in %}{{ h.letzter_check_in }}{% else %}<em>noch nie</em>{% endif %}
|
|||
|
|
</td>
|
|||
|
|
<td>
|
|||
|
|
<details>
|
|||
|
|
<summary class="btn btn-secondary" style="padding: 0.2rem 0.5rem; font-size: 0.8rem; list-style: none;">Erinnerung</summary>
|
|||
|
|
<form method="post" action="{{ url_for('admin.profil_notiz', profil_id=h.id) }}" style="margin-top: 0.4rem; display: flex; gap: 0.3rem;">
|
|||
|
|
<input type="hidden" name="typ" value="erinnerung">
|
|||
|
|
<input type="text" name="text" placeholder="Hey, lange nicht gesehen — alles okay?" required
|
|||
|
|
style="padding: 0.3rem; border: 1px solid var(--border); border-radius: 4px; width: 240px;">
|
|||
|
|
<button class="btn btn-primary" style="padding: 0.3rem 0.6rem; font-size: 0.85rem;">senden</button>
|
|||
|
|
</form>
|
|||
|
|
</details>
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
{% else %}
|
|||
|
|
<p style="color: var(--text-light);">Alle dabei. 👍</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{# ====== Sektion: Offene Rueckfragen ====== #}
|
|||
|
|
{% if rueckfragen %}
|
|||
|
|
<div class="card" style="border-left: 4px solid var(--warning);">
|
|||
|
|
<h2>❓ Offene Rückfragen ({{ rueckfragen|length }})</h2>
|
|||
|
|
<p style="font-size: 0.85rem; color: var(--text-light);">SuS hat noch nicht nachgebessert.</p>
|
|||
|
|
<ul style="margin-top: 0.5rem; padding-left: 1.2rem;">
|
|||
|
|
{% for r in rueckfragen %}
|
|||
|
|
<li style="margin: 0.3rem 0;">
|
|||
|
|
{{ tier_emoji(r.tier) }} <strong>{{ r.vorname }}</strong> ·
|
|||
|
|
„{{ r.projekt_titel }}" ·
|
|||
|
|
seit {{ r.erstellt_am[:10] }} ·
|
|||
|
|
<em>„{{ r.text[:80] }}{% if r.text|length > 80 %}…{% endif %}"</em>
|
|||
|
|
</li>
|
|||
|
|
{% endfor %}
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
|
|||
|
|
{% endblock %}
|