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

168 lines
9.0 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';
require_once __DIR__ . '/_ui.php';
$staff = require_admin_or_permission('manage_priorities');
$pdo = get_db();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$action = $_POST['action'] ?? '';
if ($action === 'create' || $action === 'update') {
$id = (int) ($_POST['id'] ?? 0);
$name = trim($_POST['name'] ?? '');
$color = trim($_POST['color'] ?? '#888888');
$response = (int) ($_POST['response_hours'] ?? 0);
$resolution = (int) ($_POST['resolution_hours'] ?? 0);
$sort = (int) ($_POST['sort_order'] ?? 0);
$notes = trim($_POST['notes'] ?? '');
if ($name === '') $errors[] = 'Bitte einen Namen angeben.';
if ($response <= 0 || $resolution <= 0) $errors[] = 'Bitte gültige SLA-Stunden angeben (größer als 0).';
if ($response > $resolution) $errors[] = 'Die Reaktionszeit darf nicht länger als die Lösungszeit sein.';
if (!preg_match('/^#[0-9a-fA-F]{6}$/', $color)) $errors[] = 'Bitte eine gültige Farbe im Format #RRGGBB angeben.';
$dup = $pdo->prepare('SELECT COUNT(*) FROM priorities WHERE LOWER(name) = LOWER(?) AND id <> ?');
$dup->execute([$name, $id]);
if ($dup->fetchColumn() > 0) $errors[] = 'Eine Priorität mit diesem Namen existiert bereits.';
if (!$errors) {
if ($action === 'create') {
$pdo->prepare('INSERT INTO priorities (name, color, response_hours, resolution_hours, sort_order, notes, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)')
->execute([$name, $color, $response, $resolution, $sort, $notes ?: null, db_now(), db_now()]);
audit_log($staff['id'], "Priorität erstellt: {$name}");
flash('success', 'Priorität erstellt.');
} else {
$pdo->prepare('UPDATE priorities SET name=?, color=?, response_hours=?, resolution_hours=?, sort_order=?, notes=?, updated_at=? WHERE id=?')
->execute([$name, $color, $response, $resolution, $sort, $notes ?: null, db_now(), $id]);
audit_log($staff['id'], "Priorität aktualisiert: {$name}");
flash('success', 'Änderungen gespeichert.');
}
redirect('/staff/priorities.php');
}
}
if ($action === 'delete') {
$id = (int) $_POST['id'];
$stmt = $pdo->prepare('SELECT COUNT(*) FROM tickets WHERE priority_id = ?');
$stmt->execute([$id]);
if ((int) $stmt->fetchColumn() > 0) {
flash('error', 'Diese Priorität wird noch von Tickets verwendet und kann nicht gelöscht werden.');
} else {
$pdo->prepare('DELETE FROM priorities WHERE id = ?')->execute([$id]);
audit_log($staff['id'], "Priorität gelöscht: #{$id}");
flash('success', 'Priorität gelöscht.');
}
redirect('/staff/priorities.php');
}
}
$isNew = isset($_GET['new']);
$editId = (int) ($_GET['edit'] ?? 0);
$showForm = $isNew || $editId || ($errors && in_array($_POST['action'] ?? '', ['create', 'update'], true));
$priorities = $pdo->query('SELECT p.*, (SELECT COUNT(*) FROM tickets t WHERE t.priority_id = p.id) AS ticket_count FROM priorities p ORDER BY p.sort_order')->fetchAll();
$editPrio = null;
if ($editId) {
$stmt = $pdo->prepare('SELECT * FROM priorities WHERE id = ?');
$stmt->execute([$editId]);
$editPrio = $stmt->fetch() ?: null;
}
$hours = fn(int $h) => $h >= 24 && $h % 24 === 0 ? ($h / 24) . ' Tag' . ($h / 24 === 1 ? '' : 'e') : $h . ' Std';
$pageTitle = 'Prioritäten / SLA';
$activePage = 'priorities';
require __DIR__ . '/_header.php';
?>
<?php foreach ($errors as $err): ?>
<div class="flash error"><?= e($err) ?></div>
<?php endforeach; ?>
<?php if ($showForm): ?>
<?php
$f = fn(string $k, $default = '') => $_POST[$k] ?? $default;
$v = fn(string $k, string $col, $default = '') => $f($k, $editPrio[$col] ?? $default);
?>
<h1>
<?= $editPrio ? 'Priorität / SLA aktualisieren' : 'Neue Priorität' ?>
<?php if ($editPrio): ?><span class="muted" style="font-size:1rem;font-weight:400">— <?= e($editPrio['name']) ?></span><?php endif; ?>
</h1>
<form method="post" class="card" style="padding:0">
<?= csrf_field() ?>
<input type="hidden" name="action" value="<?= $editPrio ? 'update' : 'create' ?>">
<?php if ($editPrio): ?><input type="hidden" name="id" value="<?= (int) $editPrio['id'] ?>"><?php endif; ?>
<?php ui_tab_bar(['prio' => 'Priorität', 'sla' => 'SLA-Zeiten']); ?>
<div class="tab-pane" data-pane="prio" style="padding:16px 20px">
<h3 style="margin-top:0">Prioritätsinformationen</h3>
<label for="name">Name *</label>
<input type="text" id="name" name="name" value="<?= e($v('name', 'name')) ?>" required>
<label for="color">Farbe *</label>
<div style="display:flex;align-items:center;gap:10px;max-width:260px">
<input type="color" id="color_picker" value="<?= e($v('color', 'color', '#2563eb')) ?>" style="width:46px;padding:2px" oninput="document.getElementById('color').value=this.value">
<input type="text" id="color" name="color" value="<?= e($v('color', 'color', '#2563eb')) ?>" placeholder="#2563eb" required oninput="if(/^#[0-9a-fA-F]{6}$/.test(this.value))document.getElementById('color_picker').value=this.value">
</div>
<label for="sort_order">Sortierung</label>
<input type="number" id="sort_order" name="sort_order" value="<?= e((string) $v('sort_order', 'sort_order', '0')) ?>" style="max-width:140px">
<h3>Administratornotizen <span class="muted" style="font-weight:400;font-size:.85rem">– Interne Notizen, sichtbar für alle Administratoren</span></h3>
<textarea name="notes" rows="5"><?= e($v('notes', 'notes')) ?></textarea>
</div>
<div class="tab-pane" data-pane="sla" style="padding:16px 20px;display:none">
<p class="muted" style="margin-top:0">Zeiten in Stunden ab Ticketerstellung bzw. Prioritätsänderung. Sie gelten kalendarisch (rund um die Uhr) – <strong>sobald unter <a href="/staff/business_hours.php">Geschäftszeiten</a> „Geschäftszeiten für SLA-Berechnung verwenden“ aktiv ist, zählen nur die dort eingetragenen Öffnungszeiten</strong>.</p>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;max-width:520px">
<div><label for="response_hours">Reaktionszeit (Std) *</label>
<input type="number" min="1" id="response_hours" name="response_hours" value="<?= e((string) $v('response_hours', 'response_hours', '24')) ?>" required></div>
<div><label for="resolution_hours">Lösungszeit (Std) *</label>
<input type="number" min="1" id="resolution_hours" name="resolution_hours" value="<?= e((string) $v('resolution_hours', 'resolution_hours', '72')) ?>" required></div>
</div>
</div>
<div class="btn-row" style="padding:0 20px 18px">
<button type="submit" class="btn"><?= $editPrio ? 'Änderungen speichern' : 'Erstellen' ?></button>
<a href="/staff/priorities.php" class="btn secondary">Abbrechen</a>
</div>
</form>
<?php ui_tab_assets('prio'); ?>
<?php else: ?>
<div style="display:flex;justify-content:space-between;align-items:center;gap:12px">
<h1 style="margin:0">Prioritäten &amp; SLA-Zeiten</h1>
<a href="/staff/priorities.php?new=1" class="btn">Neue Priorität hinzufügen</a>
</div>
<p class="muted">Reaktions- und Lösungszeit ab Ticketerstellung bzw. Prioritätsänderung. Mit aktivierten <a href="/staff/business_hours.php">Geschäftszeiten</a> zählen nur die dort eingetragenen Öffnungszeiten.</p>
<div class="card">
<table>
<thead><tr><th>Priorität</th><th>Reaktion</th><th>Lösung</th><th style="text-align:center">Tickets</th><th>Erstellt</th><th>Zuletzt aktualisiert</th><th></th></tr></thead>
<tbody>
<?php foreach ($priorities as $p): ?>
<tr>
<td><a href="/staff/priorities.php?edit=<?= (int) $p['id'] ?>"><span class="badge" style="background:<?= e($p['color']) ?>"><?= e($p['name']) ?></span></a></td>
<td><?= e($hours((int) $p['response_hours'])) ?></td>
<td><?= e($hours((int) $p['resolution_hours'])) ?></td>
<td style="text-align:center"><?= (int) $p['ticket_count'] ?></td>
<td class="muted" style="font-size:.82rem"><?= e(ui_date($p['created_at'] ?? null)) ?></td>
<td class="muted" style="font-size:.82rem"><?= e(ui_date($p['updated_at'] ?? null)) ?></td>
<td style="white-space:nowrap">
<a href="/staff/priorities.php?edit=<?= (int) $p['id'] ?>">Bearbeiten</a> ·
<form method="post" style="display:inline" onsubmit="return confirm('Priorität wirklich löschen?');">
<?= csrf_field() ?>
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= (int) $p['id'] ?>">
<button type="submit" style="background:none;border:none;color:#dc2626;cursor:pointer;padding:0;font-size:.9rem">Löschen</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php require __DIR__ . '/_footer.php'; ?>