prepare('SELECT * FROM departments WHERE id = ?'); $stmt->execute([$deptId]); $dept = $stmt->fetch(); if (!$dept) { flash('error', 'Abteilung nicht gefunden.'); redirect('/staff/departments.php'); } $fieldTypes = [ 'text' => 'Einzeiliger Text', 'textarea' => 'Mehrzeiliger Text', 'select' => 'Dropdown-Auswahl', 'radio' => 'Radio-Auswahl (Punkte)', 'checkbox' => 'Checkbox (Ja/Nein)', 'number' => 'Zahl', 'date' => 'Datum', ]; $errors = []; // Feldpositionen: Schlüssel => [Gruppe, Beschriftung]; "@"-Schlüssel stehen in custom_fields.form_section $positions = [ '@topic_top' => ['Abschnitt 1 – Themenauswahl', 'vor der Themenauswahl'], '@topic' => ['Abschnitt 1 – Themenauswahl', 'nach der Themenauswahl'], '@contact_top' => ['Abschnitt 2 – Kontaktdaten', 'vor Name/E-Mail'], '@contact' => ['Abschnitt 2 – Kontaktdaten', 'nach Name/E-Mail'], '@details_top' => ['Abschnitt 3 – Betreff und Beschreibung', 'vor dem Betreff'], '@details_mid' => ['Abschnitt 3 – Betreff und Beschreibung', 'zwischen Betreff und Beschreibung'], '@details' => ['Abschnitt 3 – Betreff und Beschreibung', 'nach der Beschreibung'], ]; $self = '/staff/department_form.php?dept=' . $deptId; if ($_SERVER['REQUEST_METHOD'] === 'POST') { verify_csrf(); $action = $_POST['action'] ?? ''; if ($action === 'save_form') { $clip = fn(string $k, int $max) => mb_substr(trim((string) ($_POST[$k] ?? '')), 0, $max); $cfg = [ 'title' => $clip('title', 150), 'contact_title' => $clip('contact_title', 100), 'issue_title' => $clip('issue_title', 100), 'details_title' => $clip('details_title', 100), 'intro' => $clip('intro', 1000), 'subject_show' => !empty($_POST['subject_show']), 'subject_label' => $clip('subject_label', 100), 'message_label' => $clip('message_label', 100), 'message_show' => !empty($_POST['message_show']), 'subject_width' => in_array($_POST['subject_width'] ?? '', ['half', 'third', 'twothirds'], true) ? $_POST['subject_width'] : 'full', 'message_width' => in_array($_POST['message_width'] ?? '', ['half', 'third', 'twothirds'], true) ? $_POST['message_width'] : 'full', 'message_hint' => $clip('message_hint', 200), 'attachment_show' => !empty($_POST['attachment_show']), 'submit_label' => $clip('submit_label', 60), ]; $pdo->prepare('UPDATE departments SET own_form = ?, form_config = ?, updated_at = ? WHERE id = ?') ->execute([!empty($_POST['own_form']) ? 1 : 0, json_encode($cfg, JSON_UNESCAPED_UNICODE), db_now(), $deptId]); audit_log($staff['id'], 'Abteilungsformular gespeichert: ' . $dept['name']); flash('success', 'Formular gespeichert.'); redirect($self); } if ($action === 'save_field') { $fid = (int) ($_POST['id'] ?? 0); $label = trim((string) ($_POST['label'] ?? '')); $type = array_key_exists($_POST['field_type'] ?? '', $fieldTypes) ? $_POST['field_type'] : 'text'; $options = trim((string) ($_POST['options'] ?? '')); $required = !empty($_POST['is_required']) ? 1 : 0; $active = !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); $width = in_array($_POST['form_width'] ?? '', ['half', 'third', 'twothirds'], true) ? $_POST['form_width'] : null; $secPick = (string) ($_POST['form_section'] ?? ''); $section = ($secPick === '' || isset($positions[$secPick])) ? $secPick : mb_substr(trim((string) ($_POST['form_section_custom'] ?? '')), 0, 100); if ($label === '') $errors[] = 'Bitte eine Bezeichnung angeben.'; if (in_array($type, ['select', 'radio'], true) && $options === '') $errors[] = 'Bitte mindestens eine Option angeben (eine pro Zeile).'; if (!$errors) { if ($fid) { $pdo->prepare('UPDATE custom_fields SET label=?, field_type=?, options=?, is_required=?, is_active=?, sort_order=?, form_section=?, form_width=?, radio_inline=?, help_text=? WHERE id=? AND department_id=?') ->execute([$label, $type, $options ?: null, $required, $active, $sort, $section ?: null, $width, $radioInline, $helpText ?: null, $fid, $deptId]); } else { $pdo->prepare('INSERT INTO custom_fields (label, field_type, options, help_topic_id, department_id, is_required, is_active, sort_order, form_section, form_width, radio_inline, help_text, created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)') ->execute([$label, $type, $options ?: null, null, $deptId, $required, $active, $sort, $section ?: null, $width, $radioInline, $helpText ?: null, db_now()]); } audit_log($staff['id'], "Abteilungsfeld gespeichert ({$dept['name']}): {$label}"); flash('success', 'Feld gespeichert.'); redirect($self); } } if ($action === 'delete_field') { $pdo->prepare('DELETE FROM custom_fields WHERE id = ? AND department_id = ?')->execute([(int) ($_POST['id'] ?? 0), $deptId]); audit_log($staff['id'], "Abteilungsfeld gelöscht ({$dept['name']})"); flash('success', 'Feld gelöscht (bereits erfasste Werte in Tickets bleiben erhalten).'); redirect($self); } } $cfg = json_decode((string) ($dept['form_config'] ?? ''), true); $cfg = is_array($cfg) ? $cfg : []; $cv = fn(string $k, string $def = '') => (string) ($cfg[$k] ?? $def); $flag = fn(string $k) => !array_key_exists($k, $cfg) || !empty($cfg[$k]); $fieldsStmt = $pdo->prepare('SELECT * FROM custom_fields WHERE department_id = ? ORDER BY sort_order, label'); $fieldsStmt->execute([$deptId]); $fields = $fieldsStmt->fetchAll(); $editField = null; if (!empty($_GET['edit'])) { foreach ($fields as $f) if ((int) $f['id'] === (int) $_GET['edit']) $editField = $f; } $pageTitle = 'Formular: ' . $dept['name']; $activePage = 'departments'; require __DIR__ . '/_header.php'; ?>
Hier legst du fest, wie das Formular „Neues Ticket“ aussieht, wenn ein Kunde diese Abteilung wählt (direkt oder über ein Hilfe-Thema dieser Abteilung).
| Reihenfolge | Abschnitt | Bezeichnung | Typ | Pflicht | Aktiv | |
|---|---|---|---|---|---|---|
| = (int) $f['sort_order'] ?> | = e($f['label']) ?> | = e($fieldTypes[$f['field_type']] ?? $f['field_type']) ?> | = $f['is_required'] ? '✓' : '–' ?> | = $f['is_active'] ? '✓' : '–' ?> | Bearbeiten · | |
| Noch keine eigenen Felder. Rechts kannst du das erste anlegen. | ||||||