incidents.php
5.97 KB
<?php
require_once __DIR__ . '/../bootstrap.php';
require_once __DIR__ . '/../lib/feature_modules.php';
requireAuth();
if (!(isAdminRole() || hasPermission('management.access') || hasPermission('incidents.manage') || hasPermission('incidents.view'))) {
http_response_code(403);
die('Access denied.');
}
$pageTitle = 'Incidents';
if (isset($_GET['export']) && $_GET['export'] === 'csv') {
$stmt = $pdo->query("SELECT i.incident_code, i.incident_date, i.driver_name, i.porter_name, i.van_label, i.description, i.damage_cost, i.status, COUNT(p.id) AS photo_count, i.created_by_name, i.created_at, i.notes FROM incidents i LEFT JOIN incident_photos p ON p.incident_id = i.id GROUP BY i.id ORDER BY i.incident_date DESC, i.created_at DESC");
$rows = [];
foreach ($stmt->fetchAll() as $r) {
$rows[] = [$r['incident_code'], $r['incident_date'], $r['driver_name'], $r['porter_name'], $r['van_label'], $r['description'], $r['damage_cost'], $r['status'], $r['photo_count'], $r['created_by_name'], $r['created_at'], $r['notes']];
}
wp_feature_csv_download('incidents_' . date('Ymd_His') . '.csv', ['Incident','Date','Driver','Porter','Van','Description','Damage Cost','Status','Photo Count','Created By','Created At','Notes'], $rows);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && (hasPermission('incidents.manage') || isAdminRole())) {
$id = (int)($_POST['id'] ?? 0);
$status = trim((string)($_POST['status'] ?? 'Open'));
$notes = trim((string)($_POST['notes'] ?? ''));
if ($id > 0 && in_array($status, ['Open','Investigating','Resolved','Closed'], true)) {
$stmt = $pdo->prepare("UPDATE incidents SET status=?, notes=?, resolved_at=? WHERE id=?");
$stmt->execute([$status, $notes, in_array($status, ['Resolved','Closed'], true) ? date('Y-m-d H:i:s') : null, $id]);
logActivity('incident_updated', 'incident', $id, 'Incident status set to ' . $status);
wp_feature_flash_set('success', 'Incident updated.');
app_redirect('management/incidents');
}
}
$status = trim((string)($_GET['status'] ?? ''));
$where = [];
$params = [];
if ($status !== '') { $where[] = 'i.status = ?'; $params[] = $status; }
$sql = "SELECT i.*, COUNT(p.id) AS photo_count FROM incidents i LEFT JOIN incident_photos p ON p.incident_id = i.id";
if ($where) $sql .= " WHERE " . implode(' AND ', $where);
$sql .= " GROUP BY i.id ORDER BY i.incident_date DESC, i.created_at DESC LIMIT 250";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$incidents = $stmt->fetchAll() ?: [];
$flash = wp_feature_flash_get();
include __DIR__ . '/../partials/header.php';
?>
<div class="content-header">
<div>
<h1 class="content-title">🚨 Incidents</h1>
<p class="content-subtitle">Issues are submitted from the main dashboard. This page is the back-office queue for review, status updates and export.</p>
</div>
<div class="d-flex gap-md" style="flex-wrap:wrap;">
<a class="btn btn-secondary" href="<?= e(app_url('management/incidents?export=csv')) ?>">⬇️ Export CSV</a>
</div>
</div>
<?php if ($flash): ?><div class="alert alert-<?= e($flash['type'] === 'error' ? 'error' : 'success') ?>" style="margin-bottom:16px;"><?= e($flash['message']) ?></div><?php endif; ?>
<div class="card mb-lg">
<div class="card-header"><h3 class="card-title">Filters</h3></div>
<form method="get" class="d-flex gap-md" style="flex-wrap:wrap;align-items:end;">
<div><label class="field-label">Status</label><select class="input" name="status"><option value="">All</option><?php foreach (['Open','Investigating','Resolved','Closed'] as $opt): ?><option value="<?= e($opt) ?>" <?= $status === $opt ? 'selected' : '' ?>><?= e($opt) ?></option><?php endforeach; ?></select></div>
<div><button class="btn btn-secondary" type="submit">Apply</button></div>
<div><a class="btn btn-secondary" href="<?= e(app_url('management/incidents')) ?>">Reset</a></div>
</form>
</div>
<div class="card">
<div class="card-header"><h3 class="card-title">Incident Queue</h3></div>
<div class="table-wrap">
<table class="table" style="min-width:1200px;">
<thead><tr><th>Incident</th><th>Date</th><th>People</th><th>Vehicle</th><th>Description</th><th>Damage</th><th>Photos</th><th>Status</th><th>Actions</th></tr></thead>
<tbody>
<?php if (!$incidents): ?><tr><td colspan="9" class="text-muted">No incidents found.</td></tr>
<?php else: foreach ($incidents as $row): ?>
<tr>
<td><?= e($row['incident_code']) ?><br><small class="text-muted"><?= e((string)$row['created_at']) ?></small></td>
<td><?= e($row['incident_date']) ?></td>
<td><?= e($row['driver_name']) ?><?php if (!empty($row['porter_name'])): ?><br><small class="text-muted">Porter: <?= e($row['porter_name']) ?></small><?php endif; ?></td>
<td><?= e($row['van_label']) ?></td>
<td><?= e($row['description']) ?><br><small class="text-muted"><?= e((string)$row['notes']) ?></small></td>
<td><?= e(number_format((float)$row['damage_cost'], 2)) ?></td>
<td><?= (int)$row['photo_count'] ?></td>
<td><span class="badge badge-muted"><?= e($row['status']) ?></span></td>
<td>
<?php if (hasPermission('incidents.manage') || isAdminRole()): ?>
<form method="post" class="d-grid gap-sm">
<input type="hidden" name="id" value="<?= (int)$row['id'] ?>">
<select class="input" name="status"><?php foreach (['Open','Investigating','Resolved','Closed'] as $opt): ?><option value="<?= e($opt) ?>" <?= $row['status'] === $opt ? 'selected' : '' ?>><?= e($opt) ?></option><?php endforeach; ?></select>
<textarea class="input" name="notes" rows="2" placeholder="Notes"><?= e((string)$row['notes']) ?></textarea>
<button class="btn btn-secondary btn-xs" type="submit">Save</button>
</form>
<?php else: ?>—<?php endif; ?>
</td>
</tr>
<?php endforeach; endif; ?>
</tbody>
</table>
</div>
</div>
<?php include __DIR__ . '/../partials/footer.php'; ?>