Files
deskhub/DeskHub-Webseite/staff/customer_profile.php
T
2026-10-16 19:12:21 +00:00

226 lines
10 KiB
PHP
Raw 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.
<?php
require_once __DIR__ . '/../includes/bootstrap.php';
$staff = require_staff_login();
$pdo = get_db();
$userId = (int) ($_GET['id'] ?? 0);
$guestEmail = trim($_GET['email'] ?? '');
$isGuest = false;
if ($userId > 0) {
$stmt = $pdo->prepare('SELECT u.*, o.name AS org_name FROM users u LEFT JOIN organizations o ON o.id = u.organization_id WHERE u.id = ?');
$stmt->execute([$userId]);
$customer = $stmt->fetch();
} elseif ($guestEmail !== '') {
// Gast-Anfrager (kein Konto, nur über Tickets bekannt) – keine Zeile in "users",
// daher hier aus den Ticket-Daten zusammengesetzt statt per user_id nachgeschlagen.
$stmt = $pdo->prepare(
"SELECT requester_email AS email, MAX(requester_name) AS name, MIN(created_at) AS created_at,
NULL AS phone, NULL AS org_name
FROM tickets WHERE requester_email = ? AND user_id IS NULL GROUP BY requester_email"
);
$stmt->execute([$guestEmail]);
$customer = $stmt->fetch();
$isGuest = (bool) $customer;
} else {
$customer = false;
}
if (!$customer) {
flash('error', 'Kunde nicht gefunden.');
redirect('/staff/customers.php');
}
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$action = $_POST['action'] ?? '';
// Notizen und Kontaktdaten hängen an einem echten Kundenkonto (users-Tabelle) –
// für Gast-Anfrager ohne Konto gibt es das nicht, siehe Hinweis oben in der Seite.
if ($isGuest && in_array($action, ['add_note', 'delete_note', 'save_customer'], true)) {
flash('error', 'Für Gast-Anfrager ohne Konto nicht verfügbar.');
redirect('/staff/customer_profile.php?email=' . urlencode($guestEmail));
}
if ($action === 'add_note') {
$note = trim($_POST['note'] ?? '');
if ($note !== '') {
$pdo->prepare('INSERT INTO customer_notes (user_id, staff_id, note, created_at) VALUES (?,?,?,?)')
->execute([$userId, $staff['id'], $note, db_now()]);
flash('success', 'Notiz gespeichert.');
}
redirect('/staff/customer_profile.php?id=' . $userId);
}
if ($action === 'delete_note') {
$noteId = (int) ($_POST['note_id'] ?? 0);
$pdo->prepare('DELETE FROM customer_notes WHERE id=? AND user_id=?')->execute([$noteId, $userId]);
redirect('/staff/customer_profile.php?id=' . $userId);
}
if ($action === 'save_customer') {
$name = trim($_POST['name'] ?? '');
$phone = trim($_POST['phone'] ?? '');
if ($name !== '') {
$pdo->prepare('UPDATE users SET name=?, phone=? WHERE id=?')->execute([$name, $phone ?: null, $userId]);
flash('success', 'Kundendaten gespeichert.');
}
redirect('/staff/customer_profile.php?id=' . $userId);
}
}
// Alle Tickets dieses Kunden (Mitarbeiter sehen nur Tickets ihrer Abteilungen)
[$deptSql, $deptParams] = dept_filter_sql(staff_department_ids($staff), 't.department_id');
$ticketStmt = $pdo->prepare(
"SELECT t.*, p.name AS priority_name, p.color AS priority_color, d.name AS department_name, s.name AS staff_name
FROM tickets t
JOIN priorities p ON p.id = t.priority_id
JOIN departments d ON d.id = t.department_id
LEFT JOIN staff s ON s.id = t.assigned_staff_id
WHERE (t.requester_email = ? OR t.user_id = ?) {$deptSql}
ORDER BY t.created_at DESC LIMIT 100"
);
$ticketStmt->execute([$customer['email'], $userId, ...$deptParams]);
$tickets = $ticketStmt->fetchAll();
// Notizen
$noteStmt = $pdo->prepare(
"SELECT cn.*, COALESCE(s.name, 'Gelöschter Mitarbeiter') AS staff_name
FROM customer_notes cn
LEFT JOIN staff s ON s.id = cn.staff_id
WHERE cn.user_id = ? ORDER BY cn.created_at DESC"
);
$noteStmt->execute([$userId]);
$notes = $noteStmt->fetchAll();
// Statistiken
$totalTickets = count($tickets);
$openTickets = count(array_filter($tickets, fn($t) => !in_array($t['status'], ['resolved','closed'])));
$closedTickets = count(array_filter($tickets, fn($t) => in_array($t['status'], ['resolved','closed'])));
$pageTitle = 'Kundenprofil: ' . $customer['name'];
$activePage = 'customers';
require __DIR__ . '/_header.php';
?>
<div class="topbar">
<div>
<h1><?= e($customer['name']) ?> <?php if ($isGuest): ?><span class="badge" style="background:#64748b; font-size:.7rem; vertical-align:middle">Gast</span><?php endif; ?></h1>
<span class="muted" style="font-size:.88rem"><?= e($customer['email']) ?></span>
</div>
<a href="/staff/customers.php" class="btn secondary">← Zurück</a>
</div>
<?php if ($isGuest): ?>
<div class="flash info" style="margin-bottom:20px">Gast-Anfrager ohne eigenes Kundenkonto – Notizen und Kontaktdaten-Bearbeitung sind daher nicht verfügbar.</div>
<?php endif; ?>
<div style="display:flex; gap:24px; align-items:flex-start; flex-wrap:wrap">
<!-- Linke Spalte -->
<div style="flex:2; min-width:0">
<!-- Tickets -->
<div class="card">
<h3>Tickets (<?= $totalTickets ?>)</h3>
<?php if (!$tickets): ?>
<div class="empty-state">Keine Tickets vorhanden.</div>
<?php else: ?>
<table>
<thead><tr><th>Ticket</th><th>Betreff</th><th>Status</th><th>Priorität</th><th>Mitarbeiter</th><th>Erstellt</th></tr></thead>
<tbody>
<?php foreach ($tickets as $t):
[$label, $color] = status_label($t['status']);
?>
<tr>
<td><a href="/staff/ticket_view.php?n=<?= urlencode($t['ticket_number']) ?>" class="ticket-no">#<?= e($t['ticket_number']) ?></a></td>
<td><a href="/staff/ticket_view.php?n=<?= urlencode($t['ticket_number']) ?>"><?= e($t['subject']) ?></a></td>
<td><span class="badge" style="background:<?= $color ?>"><?= e($label) ?></span></td>
<td><span class="badge" style="background:<?= e($t['priority_color']) ?>"><?= e($t['priority_name']) ?></span></td>
<td class="muted"><?= e($t['staff_name'] ?? '–') ?></td>
<td class="muted"><?= format_dt($t['created_at']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<!-- Notizen -->
<?php if (!$isGuest): ?>
<div class="card">
<h3>Interne Notizen</h3>
<form method="post" style="margin-bottom:16px">
<?= csrf_field() ?>
<input type="hidden" name="action" value="add_note">
<textarea name="note" placeholder="Notiz hinzufügen…" rows="3" required></textarea>
<div class="btn-row"><button type="submit" class="btn">Notiz speichern</button></div>
</form>
<?php if (!$notes): ?>
<p class="muted">Noch keine Notizen.</p>
<?php else: ?>
<?php foreach ($notes as $n): ?>
<div style="border-bottom:1px solid var(--border-soft); padding:10px 0; display:flex; justify-content:space-between; gap:12px">
<div>
<div style="font-size:.82rem; color:var(--muted); margin-bottom:4px"><?= e($n['staff_name']) ?> · <?= format_dt($n['created_at']) ?></div>
<div style="white-space:pre-wrap"><?= e($n['note']) ?></div>
</div>
<form method="post" onsubmit="return confirm('Notiz löschen?')">
<?= csrf_field() ?>
<input type="hidden" name="action" value="delete_note">
<input type="hidden" name="note_id" value="<?= $n['id'] ?>">
<button type="submit" style="background:none;border:none;color:var(--muted-lt);cursor:pointer;font-size:.9rem" title="Löschen">✕</button>
</form>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<!-- Rechte Spalte -->
<div style="flex:1; min-width:240px; max-width:280px">
<!-- Statistiken -->
<div class="stat-grid" style="grid-template-columns:1fr 1fr; margin-bottom:16px">
<div class="stat-card"><div class="num"><?= $totalTickets ?></div><div class="lbl">Gesamt</div></div>
<div class="stat-card"><div class="num"><?= $openTickets ?></div><div class="lbl">Offen</div></div>
<div class="stat-card"><div class="num"><?= $closedTickets ?></div><div class="lbl">Gelöst</div></div>
<div class="stat-card"><div class="num"><?= format_dt($customer['created_at'], 'd.m.Y') ?></div><div class="lbl">Seit</div></div>
</div>
<!-- Kundendaten bearbeiten -->
<div class="card" style="padding:16px 18px">
<div style="font-size:.78rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); margin-bottom:12px">Kontaktdaten</div>
<?php if ($isGuest): ?>
<label style="font-size:.78rem; color:var(--muted)">Name</label>
<div style="font-size:.84rem; padding:7px 0"><?= e($customer['name']) ?></div>
<label style="font-size:.78rem; margin-top:4px; color:var(--muted)">E-Mail</label>
<div style="font-size:.84rem; padding:7px 0; color:var(--muted)"><?= e($customer['email']) ?></div>
<p class="muted" style="font-size:.78rem; margin-top:8px">Ohne Konto nicht bearbeitbar.</p>
<?php else: ?>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_customer">
<label style="font-size:.78rem">Name</label>
<input type="text" name="name" value="<?= e($customer['name']) ?>" required>
<label style="font-size:.78rem; margin-top:8px">Telefon</label>
<input type="text" name="phone" value="<?= e($customer['phone'] ?? '') ?>" placeholder="Optional">
<label style="font-size:.78rem; margin-top:8px; color:var(--muted)">E-Mail</label>
<div style="font-size:.84rem; padding:7px 0; color:var(--muted)"><?= e($customer['email']) ?></div>
<?php if ($customer['org_name']): ?>
<label style="font-size:.78rem; margin-top:4px; color:var(--muted)">Organisation</label>
<div style="font-size:.84rem; padding:7px 0"><?= e($customer['org_name']) ?></div>
<?php endif; ?>
<button type="submit" class="btn" style="width:100%; margin-top:12px; justify-content:center">Speichern</button>
</form>
<?php endif; ?>
</div>
</div>
</div>
<?php require __DIR__ . '/_footer.php'; ?>