Add Jinja2 web UI with Bootstrap 5 dark theme

- app/templates/: base layout with sidebar nav + 6 pages
  (dashboard, printers, jobs, filaments, todos, pricing)
- app/routers/ui.py: HTML routes querying the DB live
- API routes moved to /api/* prefix
- requirements: jinja2, python-multipart

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Martin Hohenberg
2026-06-18 21:26:23 +02:00
parent f4e991e5dc
commit ee0b1b39e9
10 changed files with 473 additions and 9 deletions

View File

@@ -0,0 +1,52 @@
{% extends "base.html" %}
{% block title %}Filaments — POPS{% endblock %}
{% block content %}
<h5 class="text-white mb-4">Filament Inventory</h5>
<div class="card">
{% if filaments %}
<table class="table table-dark table-hover mb-0 align-middle">
<thead>
<tr class="text-secondary small">
<th class="fw-normal">Brand</th>
<th class="fw-normal">Material</th>
<th class="fw-normal">Color</th>
<th class="fw-normal">Remaining</th>
<th class="fw-normal text-end">Price / kg</th>
</tr>
</thead>
<tbody>
{% for f in filaments %}
{% set pct = (f.weight_remaining_g / f.weight_total_g * 100) | int if f.weight_total_g else 0 %}
<tr>
<td class="fw-medium text-white">{{ f.brand or '—' }}</td>
<td><span class="badge bg-secondary">{{ f.material.value }}</span></td>
<td>
<div class="d-flex align-items-center gap-2">
{% if f.color_hex %}
<span style="display:inline-block;width:12px;height:12px;border-radius:3px;background:{{ f.color_hex }};border:1px solid #444"></span>
{% endif %}
{{ f.color or '—' }}
</div>
</td>
<td style="min-width:160px">
<div class="d-flex align-items-center gap-2">
<div class="progress flex-grow-1" style="height:6px">
<div class="progress-bar {% if pct < 20 %}bg-danger{% elif pct < 50 %}bg-warning{% else %}bg-success{% endif %}"
style="width:{{ pct }}%"></div>
</div>
<span class="text-secondary small" style="min-width:70px">{{ f.weight_remaining_g | int }}g / {{ f.weight_total_g | int }}g</span>
</div>
</td>
<td class="text-secondary small text-end">
{% if f.price_per_kg_eur %}€ {{ "%.2f"|format(f.price_per_kg_eur) }}{% else %}—{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="card-body text-secondary">No filaments in inventory yet.</div>
{% endif %}
</div>
{% endblock %}