Christian Mueller 0d080ff885 refactor: AIDA -> modulare Zeiterfassung
- Alle AIDA-Referenzen durch generische Begriffe ersetzt
  (aida -> attendance im Code, "Zeiterfassung" im UI)
- DB-Spalten: last_aida_status -> last_attendance_status
- Settings: aida_csv_path -> attendance_csv_path
- REST API fuer Zeiterfassung auf Port 8081:
  POST /api/attendance/{personal_nr} mit {"status": "anwesend"}
  GET  /api/attendance - alle Status abfragen
- Automatische DB-Migration fuer bestehende Installationen
- CSV bleibt als Option, API als Echtzeit-Alternative

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 10:28:45 +02:00

109 lines
5.2 KiB
HTML

{% extends "base.html" %}
{% block title %}Benutzer - Busylight{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="mb-0">Benutzer</h4>
<form method="post" action="/api/users/sync">
<button type="submit" class="btn btn-primary">
<i class="bi bi-cloud-download"></i> Aus Azure synchronisieren
</button>
</form>
</div>
{% if request.query_params.get('synced') %}
<div class="alert alert-success alert-dismissible fade show">
<i class="bi bi-check-circle"></i> {{ request.query_params.get('synced') }} neue Benutzer synchronisiert.
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endif %}
{% if request.query_params.get('error') == 'not_authenticated' %}
<div class="alert alert-danger alert-dismissible fade show">
<i class="bi bi-x-circle"></i> Azure nicht verbunden. Bitte zuerst authentifizieren.
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endif %}
<div class="card">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th>Status</th>
<th>Name</th>
<th>E-Mail</th>
<th>Personal-Nr</th>
<th>Durchwahl</th>
<th>Zuordnung</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr class="{% if not user.active %}table-light text-muted{% endif %}">
<td>
{% if user.active %}
<span class="badge bg-success">Aktiv</span>
{% else %}
<span class="badge bg-secondary">Inaktiv</span>
{% endif %}
</td>
<td>{{ user.display_name }}</td>
<td><small>{{ user.email or '-' }}</small></td>
<td>
<form method="post" action="/api/users/{{ user.azure_id }}/update" class="d-flex gap-1">
<input type="text" name="personal_nr" value="{{ user.personal_nr or '' }}"
class="form-control form-control-sm" style="width: 120px;"
placeholder="~~00000~~">
<input type="hidden" name="active" value="{{ '1' if user.active else '0' }}">
<input type="hidden" name="phone_extension" value="{{ user.phone_extension or '' }}">
<button type="submit" class="btn btn-sm btn-outline-secondary">
<i class="bi bi-check"></i>
</button>
</form>
</td>
<td>
<form method="post" action="/api/users/{{ user.azure_id }}/update" class="d-flex gap-1">
<input type="text" name="phone_extension" value="{{ user.phone_extension or '' }}"
class="form-control form-control-sm" style="width: 80px;"
placeholder="z.B. 123">
<input type="hidden" name="personal_nr" value="{{ user.personal_nr or '' }}">
<input type="hidden" name="active" value="{{ '1' if user.active else '0' }}">
<button type="submit" class="btn btn-sm btn-outline-secondary">
<i class="bi bi-check"></i>
</button>
</form>
</td>
<td>
{% if user.assignment_id %}
<span class="badge bg-info"><i class="bi bi-link-45deg"></i> Zugeordnet</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<form method="post" action="/api/users/{{ user.azure_id }}/toggle" class="d-inline">
<button type="submit" class="btn btn-sm {% if user.active %}btn-outline-warning{% else %}btn-outline-success{% endif %}">
{% if user.active %}
<i class="bi bi-pause-circle"></i>
{% else %}
<i class="bi bi-play-circle"></i>
{% endif %}
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="mt-3 text-muted">
<small>{{ users|length }} Benutzer insgesamt</small>
</div>
{% endblock %}