274 lines
12 KiB
HTML
Executable File
274 lines
12 KiB
HTML
Executable File
{% extends "admin/base.html" %}
|
|
{% block title %}Kunde: {{ customer.display_name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb mb-2">
|
|
<li class="breadcrumb-item"><a href="{{ url_for('admin.customers') }}" class="text-info">Kunden</a></li>
|
|
<li class="breadcrumb-item active">{{ customer.display_name }}</li>
|
|
</ol>
|
|
</nav>
|
|
<h1><i class="bi bi-person me-2"></i>{{ customer.display_name }}</h1>
|
|
</div>
|
|
<div>
|
|
<form method="POST" action="{{ url_for('admin.customer_sync', customer_id=customer.id) }}" class="d-inline">
|
|
<button type="submit" class="btn btn-outline-info" title="Von WordPress synchronisieren">
|
|
<i class="bi bi-arrow-repeat me-1"></i>Sync
|
|
</button>
|
|
</form>
|
|
<a href="{{ url_for('admin.customer_edit', customer_id=customer.id) }}" class="btn btn-warning ms-2">
|
|
<i class="bi bi-pencil me-1"></i>Bearbeiten
|
|
</a>
|
|
<a href="{{ url_for('admin.customers') }}" class="btn btn-outline-secondary ms-2">
|
|
<i class="bi bi-arrow-left me-1"></i>Zurueck
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Prepare custom_fields data early for ordering -->
|
|
{% set custom_fields = customer.get_custom_fields() %}
|
|
{% set wp_labels = {} %}
|
|
{% if wp_schema and wp_schema.custom_fields %}
|
|
{% for field in wp_schema.custom_fields %}
|
|
{% if field.name %}
|
|
{% set saved = field_config.wp_fields.get(field.name, {}) %}
|
|
{% set _ = wp_labels.update({field.name: saved.get('label', field.label)}) %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{# Sprint 13: Labels + Hidden aus customer_view_config #}
|
|
{% set view_labels = customer_view_config.field_labels if customer_view_config else {} %}
|
|
{% set hidden_fields = customer_view_config.hidden_fields if customer_view_config else [] %}
|
|
|
|
{# Skip fields already shown in Kontaktdaten section #}
|
|
{% set skip_fields = [
|
|
'mec_field_2', 'mec_field_3', 'mec_field_7', 'mec_field_8',
|
|
'name', 'vorname', 'nachname', 'first_name', 'last_name',
|
|
'email', 'e_mail', 'e-mail',
|
|
'telefon', 'phone', 'mobil', 'mobile', 'tel',
|
|
'adresse', 'strasse', 'straße', 'street', 'address_street',
|
|
'plz', 'postleitzahl', 'zip', 'address_zip',
|
|
'ort', 'stadt', 'city', 'address_city'
|
|
] %}
|
|
|
|
<div class="row g-4">
|
|
<!-- 1. Kontaktdaten -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<i class="bi bi-person-vcard me-2"></i>Kontaktdaten
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-dark table-borderless mb-0">
|
|
<tr>
|
|
<td class="text-muted" style="width: 140px;">E-Mail</td>
|
|
<td>
|
|
<a href="mailto:{{ customer.email }}" class="text-info">{{ customer.email }}</a>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text-muted">Telefon</td>
|
|
<td>
|
|
{% if customer.display_phone %}
|
|
<a href="tel:{{ customer.display_phone }}" class="text-info">{{ customer.display_phone }}</a>
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text-muted">Adresse</td>
|
|
<td>
|
|
{% set addr = customer.display_address %}
|
|
{% if addr.street %}
|
|
{{ addr.street }}<br>
|
|
{{ addr.zip }} {{ addr.city }}
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 2. Personendaten (wichtig - direkt nach Kontaktdaten) -->
|
|
{% if custom_fields %}
|
|
{% set has_data = namespace(value=false) %}
|
|
{% for key, value in custom_fields.items() %}
|
|
{% set saved_field = field_config.wp_fields.get(key, {}) %}
|
|
{# Sprint 13: Check both field_config.visible AND hidden_fields list #}
|
|
{% set is_hidden = key in hidden_fields %}
|
|
{% if key not in skip_fields and saved_field.get('visible', true) and not is_hidden %}
|
|
{% set has_data.value = true %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if has_data.value %}
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<i class="bi bi-person-lines-fill me-2"></i>Personendaten
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-dark table-borderless table-sm mb-0">
|
|
{% for key, value in custom_fields.items() %}
|
|
{% set saved_field = field_config.wp_fields.get(key, {}) %}
|
|
{% set is_visible = saved_field.get('visible', true) %}
|
|
{% set is_hidden = key in hidden_fields %}
|
|
{% if key not in skip_fields and is_visible and not is_hidden %}
|
|
<tr>
|
|
<td class="text-muted" style="width: 180px;">
|
|
{# Sprint 13: Priority: view_labels > saved_field.label > wp_labels > key #}
|
|
{{ view_labels.get(key) or saved_field.get('label') or wp_labels.get(key) or key }}
|
|
</td>
|
|
<td>{{ value }}</td>
|
|
</tr>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
<!-- 3. E-Mail-Einstellungen -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<i class="bi bi-envelope me-2"></i>E-Mail-Einstellungen
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center mb-2">
|
|
{% if customer.email_notifications %}
|
|
<i class="bi bi-check-circle text-success me-2"></i>
|
|
{% else %}
|
|
<i class="bi bi-x-circle text-danger me-2"></i>
|
|
{% endif %}
|
|
<span>Buchungsbestaetigungen</span>
|
|
</div>
|
|
<div class="d-flex align-items-center mb-2">
|
|
{% if customer.email_reminders %}
|
|
<i class="bi bi-check-circle text-success me-2"></i>
|
|
{% else %}
|
|
<i class="bi bi-x-circle text-danger me-2"></i>
|
|
{% endif %}
|
|
<span>Kurserinnerungen</span>
|
|
</div>
|
|
<div class="d-flex align-items-center mb-2">
|
|
{% if customer.email_invoices %}
|
|
<i class="bi bi-check-circle text-success me-2"></i>
|
|
{% else %}
|
|
<i class="bi bi-x-circle text-danger me-2"></i>
|
|
{% endif %}
|
|
<span>Rechnungen</span>
|
|
</div>
|
|
<div class="d-flex align-items-center">
|
|
{% if customer.email_marketing %}
|
|
<i class="bi bi-check-circle text-success me-2"></i>
|
|
{% else %}
|
|
<i class="bi bi-x-circle text-danger me-2"></i>
|
|
{% endif %}
|
|
<span>Newsletter & Marketing</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 4. Konto-Infos -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<i class="bi bi-info-circle me-2"></i>Konto-Informationen
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-dark table-borderless mb-0">
|
|
<tr>
|
|
<td class="text-muted" style="width: 140px;">Kunden-ID</td>
|
|
<td>#{{ customer.id }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text-muted">WP User-ID</td>
|
|
<td>{{ customer.wp_user_id or '-' }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text-muted">Registriert</td>
|
|
<td>{{ customer.created_at.strftime('%d.%m.%Y um %H:%M') if customer.created_at else '-' }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text-muted">Letzter Login</td>
|
|
<td>
|
|
{% if customer.last_login_at %}
|
|
{{ customer.last_login_at.strftime('%d.%m.%Y um %H:%M') }}
|
|
{% else %}
|
|
<span class="text-muted">Noch nie eingeloggt</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text-muted">Aktualisiert</td>
|
|
<td>{{ customer.updated_at.strftime('%d.%m.%Y um %H:%M') if customer.updated_at else '-' }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Gefahrenzone -->
|
|
<div class="card border-danger mt-4">
|
|
<div class="card-header bg-danger bg-opacity-25 text-danger">
|
|
<i class="bi bi-exclamation-triangle me-2"></i>Gefahrenzone
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<strong>Kunden loeschen</strong>
|
|
<p class="text-muted mb-0 small">
|
|
Loescht das Kundenkonto und alle zugehoerigen Daten unwiderruflich.
|
|
</p>
|
|
</div>
|
|
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">
|
|
<i class="bi bi-trash me-1"></i>Kunde loeschen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Delete Modal -->
|
|
<div class="modal fade" id="deleteModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content bg-dark">
|
|
<div class="modal-header border-secondary">
|
|
<h5 class="modal-title">Kunde loeschen</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Moechten Sie diesen Kunden wirklich loeschen?</p>
|
|
<p class="mb-0">
|
|
<strong>{{ customer.display_name }}</strong><br>
|
|
<span class="text-muted">{{ customer.email }}</span>
|
|
</p>
|
|
<div class="alert alert-danger mt-3 mb-0">
|
|
<i class="bi bi-exclamation-triangle me-2"></i>
|
|
Diese Aktion kann nicht rueckgaengig gemacht werden!
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer border-secondary">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
|
|
<form method="POST" action="{{ url_for('admin.customer_delete', customer_id=customer.id) }}" class="d-inline">
|
|
<button type="submit" class="btn btn-danger">
|
|
<i class="bi bi-trash me-1"></i>Endgueltig loeschen
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|