195 lines
11 KiB
PHP
195 lines
11 KiB
PHP
<?php
|
||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||
$admin = require_admin_or_permission('manage_custom_fields');
|
||
$pdo = get_db();
|
||
|
||
$errors = [];
|
||
$fieldTypes = [
|
||
'text' => 'Einzeiliger Text',
|
||
'textarea' => 'Mehrzeiliger Text',
|
||
'select' => 'Dropdown-Auswahl',
|
||
'radio' => 'Radio-Auswahl (Punkte)',
|
||
'checkbox' => 'Checkbox (Ja/Nein)',
|
||
'number' => 'Zahl',
|
||
'date' => 'Datum',
|
||
];
|
||
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
verify_csrf();
|
||
$action = $_POST['action'] ?? '';
|
||
|
||
if ($action === 'create' || $action === 'update') {
|
||
$label = trim($_POST['label'] ?? '');
|
||
$type = array_key_exists($_POST['field_type'] ?? '', $fieldTypes) ? $_POST['field_type'] : 'text';
|
||
$optionsRaw = trim($_POST['options'] ?? '');
|
||
$helpTopicId = ($_POST['help_topic_id'] ?? '') !== '' ? (int) $_POST['help_topic_id'] : null;
|
||
$isRequired = !empty($_POST['is_required']) ? 1 : 0;
|
||
$isActive = !empty($_POST['is_active']) ? 1 : 0;
|
||
$sort = (int) ($_POST['sort_order'] ?? 0);
|
||
$radioInline = !empty($_POST['radio_inline']) ? 1 : 0;
|
||
$helpText = form_help_compose((string) ($_POST['help_text'] ?? ''), (string) ($_POST['link_url'] ?? ''), (string) ($_POST['link_word'] ?? ''), $label);
|
||
|
||
if ($label === '') $errors[] = 'Bitte eine Bezeichnung angeben.';
|
||
if (in_array($type, ['select', 'radio'], true) && $optionsRaw === '') $errors[] = 'Bitte mindestens eine Option angeben (eine pro Zeile).';
|
||
|
||
if (!$errors) {
|
||
if ($action === 'create') {
|
||
$pdo->prepare('INSERT INTO custom_fields (label, field_type, options, help_topic_id, is_required, is_active, sort_order, radio_inline, help_text, created_at) VALUES (?,?,?,?,?,?,?,?,?,?)')
|
||
->execute([$label, $type, $optionsRaw ?: null, $helpTopicId, $isRequired, $isActive, $sort, $radioInline, $helpText ?: null, db_now()]);
|
||
audit_log($admin['id'], "Ticket-Feld erstellt: {$label}");
|
||
flash('success', 'Feld erstellt.');
|
||
} else {
|
||
$id = (int) $_POST['id'];
|
||
$pdo->prepare('UPDATE custom_fields SET label=?, field_type=?, options=?, help_topic_id=?, is_required=?, is_active=?, sort_order=?, radio_inline=?, help_text=? WHERE id=?')
|
||
->execute([$label, $type, $optionsRaw ?: null, $helpTopicId, $isRequired, $isActive, $sort, $radioInline, $helpText ?: null, $id]);
|
||
audit_log($admin['id'], "Ticket-Feld aktualisiert: {$label}");
|
||
flash('success', 'Feld aktualisiert.');
|
||
}
|
||
redirect('/staff/custom_fields.php');
|
||
}
|
||
}
|
||
|
||
if ($action === 'delete') {
|
||
$id = (int) $_POST['id'];
|
||
$labelStmt = $pdo->prepare('SELECT label FROM custom_fields WHERE id = ?');
|
||
$labelStmt->execute([$id]);
|
||
$delLabel = $labelStmt->fetchColumn();
|
||
$pdo->prepare('DELETE FROM custom_fields WHERE id = ?')->execute([$id]);
|
||
audit_log($admin['id'], "Ticket-Feld gelöscht: {$delLabel}");
|
||
flash('success', 'Feld gelöscht (bereits erfasste Werte bleiben in bestehenden Tickets sichtbar).');
|
||
redirect('/staff/custom_fields.php');
|
||
}
|
||
}
|
||
|
||
$fields = $pdo->query(
|
||
'SELECT cf.*, ht.name AS help_topic_name FROM custom_fields cf
|
||
LEFT JOIN help_topics ht ON ht.id = cf.help_topic_id
|
||
WHERE cf.department_id IS NULL ORDER BY cf.sort_order, cf.label'
|
||
)->fetchAll();
|
||
$helpTopics = $pdo->query('SELECT * FROM help_topics ORDER BY name')->fetchAll();
|
||
|
||
$editId = $_GET['edit'] ?? null;
|
||
$editField = null;
|
||
if ($editId) {
|
||
$stmt = $pdo->prepare('SELECT * FROM custom_fields WHERE id = ?');
|
||
$stmt->execute([$editId]);
|
||
$editField = $stmt->fetch();
|
||
}
|
||
|
||
$pageTitle = 'Ticket-Felder';
|
||
$activePage = 'custom_fields';
|
||
require __DIR__ . '/_header.php';
|
||
?>
|
||
|
||
<h1>Individuelle Ticket-Felder</h1>
|
||
<p class="muted">Diese Felder erscheinen zusätzlich zu Name, E-Mail, Betreff und Beschreibung auf dem Formular „Neues Ticket erstellen“. Die eingegebenen Werte werden im Ticket angezeigt.</p>
|
||
|
||
<?php foreach ($errors as $err): ?>
|
||
<div class="flash error"><?= e($err) ?></div>
|
||
<?php endforeach; ?>
|
||
|
||
<div style="display:flex; gap:24px; align-items:flex-start">
|
||
<div style="flex:2">
|
||
<div class="card">
|
||
<table>
|
||
<thead><tr><th>Bezeichnung</th><th>Typ</th><th>Hilfe-Thema</th><th>Pflichtfeld</th><th>Aktiv</th><th></th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($fields as $f): ?>
|
||
<tr>
|
||
<td><?= e($f['label']) ?></td>
|
||
<td><?= e($fieldTypes[$f['field_type']] ?? $f['field_type']) ?></td>
|
||
<td class="muted"><?= $f['help_topic_name'] ? e($f['help_topic_name']) : 'Alle Themen' ?></td>
|
||
<td><?= $f['is_required'] ? '✓' : '–' ?></td>
|
||
<td><?= $f['is_active'] ? '✓' : '–' ?></td>
|
||
<td>
|
||
<a href="/staff/custom_fields.php?edit=<?= $f['id'] ?>">Bearbeiten</a> ·
|
||
<form method="post" style="display:inline" onsubmit="return confirm('Feld wirklich löschen? Bereits erfasste Werte in bestehenden Tickets bleiben erhalten.');">
|
||
<?= csrf_field() ?>
|
||
<input type="hidden" name="action" value="delete">
|
||
<input type="hidden" name="id" value="<?= $f['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; ?>
|
||
<?php if (!$fields): ?>
|
||
<tr><td colspan="6" class="muted">Noch keine individuellen Felder angelegt.</td></tr>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div style="flex:1; min-width:300px">
|
||
<div class="card">
|
||
<h3><?= $editField ? 'Feld bearbeiten' : 'Neues Feld' ?></h3>
|
||
<form method="post">
|
||
<?= csrf_field() ?>
|
||
<input type="hidden" name="action" value="<?= $editField ? 'update' : 'create' ?>">
|
||
<?php if ($editField): ?><input type="hidden" name="id" value="<?= $editField['id'] ?>"><?php endif; ?>
|
||
|
||
<label for="label">Bezeichnung</label>
|
||
<input type="text" id="label" name="label" value="<?= e($editField['label'] ?? '') ?>" placeholder="z. B. Vertragsnummer" required>
|
||
|
||
<label for="field_type">Feldtyp</label>
|
||
<select name="field_type" id="field_type" onchange="document.getElementById('options-row').style.display = (this.value==='select' || this.value==='radio') ? 'block' : 'none'; document.getElementById('radio-row').style.display = this.value==='radio' ? 'block' : 'none'">
|
||
<?php foreach ($fieldTypes as $val => $lbl): ?>
|
||
<option value="<?= $val ?>" <?= ($editField['field_type'] ?? 'text') === $val ? 'selected' : '' ?>><?= e($lbl) ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
|
||
<div id="options-row" style="display:<?= in_array($editField['field_type'] ?? '', ['select', 'radio'], true) ? 'block' : 'none' ?>">
|
||
<label for="options">Optionen (eine pro Zeile)</label>
|
||
<textarea id="options" name="options" placeholder="Option 1 Option 2 Option 3"><?= e($editField['options'] ?? '') ?></textarea>
|
||
</div>
|
||
|
||
<?php $__rt = $editField['field_type'] ?? ''; $__ri = $editField['radio_inline'] ?? 0; ?>
|
||
<div id="radio-row" style="display:<?= ($__rt === 'radio') ? 'block' : 'none' ?>">
|
||
<label for="radio_inline">Anordnung der Optionen</label>
|
||
<select id="radio_inline" name="radio_inline">
|
||
<option value="0" <?= empty($__ri) ? 'selected' : '' ?>>Untereinander</option>
|
||
<option value="1" <?= !empty($__ri) ? 'selected' : '' ?>>Nebeneinander</option>
|
||
</select>
|
||
</div>
|
||
|
||
<?php $__hStored = $editField['help_text'] ?? ''; ?>
|
||
<?php [$__hPlain, $__hUrl, $__hWord] = form_help_split($__hStored); ?>
|
||
<label for="help_text">Hinweistext (optional)</label>
|
||
<textarea id="help_text" name="help_text" rows="3" placeholder="z. B. Ich habe die Nutzerbedingungen gelesen und akzeptiert."><?= e($__hPlain) ?></textarea>
|
||
<div class="field-row">
|
||
<div><label for="link_word">Verlinkter Teil des Textes</label><input type="text" id="link_word" name="link_word" value="<?= e($__hWord) ?>" placeholder="z. B. Nutzerbedingungen"></div>
|
||
<div><label for="link_url">Link-Adresse</label><input type="text" id="link_url" name="link_url" value="<?= e($__hUrl) ?>" placeholder="https://…"></div>
|
||
</div>
|
||
<p class="muted" style="font-size:.78rem;margin:3px 0 0">Bei einer <strong>Checkbox</strong> steht der Text neben dem Kästchen, bei anderen Feldern unter dem Feld. Das Wort aus „Verlinkter Teil“ wird im Text zum Link auf die Adresse. Eine Checkbox als <strong>Pflichtfeld</strong> muss angehakt werden.</p>
|
||
|
||
<label for="help_topic_id">Gilt für Hilfe-Thema</label>
|
||
<select name="help_topic_id" id="help_topic_id">
|
||
<option value="">Alle Themen (oder Formular ohne Themenauswahl)</option>
|
||
<?php foreach ($helpTopics as $t): ?>
|
||
<option value="<?= $t['id'] ?>" <?= (string) ($editField['help_topic_id'] ?? ($_GET['topic'] ?? '')) === (string) $t['id'] ? 'selected' : '' ?>><?= e($t['name']) ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<p class="muted" style="font-size:.78rem">Auf „Alle Themen“ belassen, damit das Feld unabhängig vom gewählten Anliegen erscheint.</p>
|
||
|
||
<label for="sort_order">Sortierung</label>
|
||
<input type="text" id="sort_order" name="sort_order" value="<?= e((string) ($editField['sort_order'] ?? '0')) ?>">
|
||
|
||
<label style="display:flex; align-items:center; gap:8px; margin-top:14px">
|
||
<input type="checkbox" name="is_required" style="width:auto" <?= !empty($editField['is_required']) ? 'checked' : '' ?>>
|
||
Pflichtfeld
|
||
</label>
|
||
<label style="display:flex; align-items:center; gap:8px; margin-top:8px">
|
||
<input type="checkbox" name="is_active" style="width:auto" <?= ($editField['is_active'] ?? 1) ? 'checked' : '' ?>>
|
||
Aktiv (auf dem Ticket-Formular sichtbar)
|
||
</label>
|
||
|
||
<div class="btn-row">
|
||
<button type="submit" class="btn"><?= $editField ? 'Speichern' : 'Erstellen' ?></button>
|
||
<?php if ($editField): ?><a href="/staff/custom_fields.php" class="btn secondary">Abbrechen</a><?php endif; ?>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php require __DIR__ . '/_footer.php'; ?>
|