feat: add assigned and in-progress technician dashboard panels

This commit is contained in:
Marco0300
2026-09-02 00:08:55 +02:00
parent ee7c24644a
commit 80031ae7a4
+6 -1
View File
@@ -130,16 +130,21 @@ if ($route === 'dashboard') {
$slaRows = $slaRowsStmt->fetchAll();
}
$urgentJobcards = [];
$assignedJobcards = [];
$inProgressJobcards = [];
if ($user['role_name'] === 'Technician') {
$urgentStmt = db()->prepare("SELECT DISTINCT j.id, j.reference_no, j.status, j.priority, c.name AS client_name FROM jobcards j JOIN clients c ON c.id = j.client_id JOIN jobcard_assignments ja ON ja.jobcard_id = j.id AND ja.user_id = :user WHERE j.priority IN ('high', 'critical') AND j.status <> 'closed' ORDER BY FIELD(j.priority, 'critical', 'high'), j.created_at ASC LIMIT 10");
$urgentStmt->execute(['user' => $user['id']]);
$urgentJobcards = $urgentStmt->fetchAll();
$workloadStmt = db()->prepare("SELECT DISTINCT j.id, j.reference_no, j.status, j.priority, c.name AS client_name FROM jobcards j JOIN clients c ON c.id = j.client_id JOIN jobcard_assignments ja ON ja.jobcard_id = j.id AND ja.user_id = :user WHERE j.status IN ('assigned', 'in_progress') ORDER BY FIELD(j.status, 'in_progress', 'assigned'), j.created_at ASC LIMIT 50");
$workloadStmt->execute(['user' => $user['id']]);
foreach ($workloadStmt->fetchAll() as $workItem) { if ($workItem['status'] === 'assigned') $assignedJobcards[] = $workItem; else $inProgressJobcards[] = $workItem; }
}
$slaClassifier = new \App\Domain\SLA\SlaThresholdClassifier();
$slaWarnings = 0;
foreach ($slaRows as $slaRow) if (in_array($slaClassifier->classify((float)$slaRow['used_hours'], (float)$slaRow['allocated_hours']), ['warning', 'critical', 'exceeded'], true)) $slaWarnings++;
render_header('Dashboard'); ?><div class="d-flex justify-content-between align-items-center mb-4"><div><h1 class="h3 mb-1">Dashboard</h1><p class="text-muted mb-0">Your operational overview.</p></div><span class="badge text-bg-primary"><?= e($user['role_name']) ?></span></div><div class="row g-3"><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">New jobcards</div><div class="display-6 fw-semibold"><?= (int)($jobcardMetrics['new_count'] ?? 0) ?></div></div></div></div><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">Open jobcards</div><div class="display-6 fw-semibold"><?= (int)($jobcardMetrics['open_count'] ?? 0) ?></div></div></div></div><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">Hours this week</div><div class="display-6 fw-semibold"><?= e(number_format($hoursThisWeek, 2)) ?></div></div></div></div><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">SLA warnings</div><div class="display-6 fw-semibold"><?= $slaWarnings ?></div></div></div></div></div><div class="card mt-4"><div class="card-body"><h2 class="h5">Operations</h2><p class="mb-0 text-muted">Use Jobcards to manage assignments, status, technician notes and time entries. SLA threshold metrics will activate after period and rollover rules are configured.</p></div></div><?php if ($user['role_name'] === 'Technician') { ?><div class="card mt-4 border-warning"><div class="card-body"><div class="d-flex justify-content-between align-items-center mb-3"><div><h2 class="h5 mb-1">Urgent jobcards</h2><p class="text-muted mb-0">High and critical priority work assigned to you.</p></div><span class="badge text-bg-warning"><?= count($urgentJobcards) ?></span></div><?php if (!$urgentJobcards): ?><p class="text-muted mb-0">No urgent active jobcards.</p><?php else: ?><div class="list-group list-group-flush"><?php foreach ($urgentJobcards as $urgent): ?><a class="list-group-item list-group-item-action px-0 d-flex justify-content-between align-items-center" href="/?route=jobcard&id=<?= (int)$urgent['id'] ?>"><span><strong><?= e($urgent['reference_no']) ?></strong><span class="text-muted ms-2"><?= e($urgent['client_name']) ?></span></span><span><span class="badge text-bg-<?= $urgent['priority'] === 'critical' ? 'danger' : 'warning' ?> me-2"><?= e(ucfirst($urgent['priority'])) ?></span><?= e(ucwords(str_replace('_', ' ', $urgent['status']))) ?></span></a><?php endforeach; ?></div><?php endif; ?></div></div><?php } ?><?php render_footer(); exit;
render_header('Dashboard'); ?><div class="d-flex justify-content-between align-items-center mb-4"><div><h1 class="h3 mb-1">Dashboard</h1><p class="text-muted mb-0">Your operational overview.</p></div><span class="badge text-bg-primary"><?= e($user['role_name']) ?></span></div><div class="row g-3"><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">New jobcards</div><div class="display-6 fw-semibold"><?= (int)($jobcardMetrics['new_count'] ?? 0) ?></div></div></div></div><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">Open jobcards</div><div class="display-6 fw-semibold"><?= (int)($jobcardMetrics['open_count'] ?? 0) ?></div></div></div></div><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">Hours this week</div><div class="display-6 fw-semibold"><?= e(number_format($hoursThisWeek, 2)) ?></div></div></div></div><div class="col-sm-6 col-xl-3"><div class="card metric-card"><div class="card-body"><div class="text-muted small">SLA warnings</div><div class="display-6 fw-semibold"><?= $slaWarnings ?></div></div></div></div></div><div class="card mt-4"><div class="card-body"><h2 class="h5">Operations</h2><p class="mb-0 text-muted">Use Jobcards to manage assignments, status, technician notes and time entries. SLA threshold metrics will activate after period and rollover rules are configured.</p></div></div><?php if ($user['role_name'] === 'Technician') { ?><div class="card mt-4 border-warning"><div class="card-body"><div class="d-flex justify-content-between align-items-center mb-3"><div><h2 class="h5 mb-1">Urgent jobcards</h2><p class="text-muted mb-0">High and critical priority work assigned to you.</p></div><span class="badge text-bg-warning"><?= count($urgentJobcards) ?></span></div><?php if (!$urgentJobcards): ?><p class="text-muted mb-0">No urgent active jobcards.</p><?php else: ?><div class="list-group list-group-flush"><?php foreach ($urgentJobcards as $urgent): ?><a class="list-group-item list-group-item-action px-0 d-flex justify-content-between align-items-center" href="/?route=jobcard&id=<?= (int)$urgent['id'] ?>"><span><strong><?= e($urgent['reference_no']) ?></strong><span class="text-muted ms-2"><?= e($urgent['client_name']) ?></span></span><span><span class="badge text-bg-<?= $urgent['priority'] === 'critical' ? 'danger' : 'warning' ?> me-2"><?= e(ucfirst($urgent['priority'])) ?></span><?= e(ucwords(str_replace('_', ' ', $urgent['status']))) ?></span></a><?php endforeach; ?></div><?php endif; ?></div></div><?php } ?><?php if ($user['role_name'] === 'Technician'): ?><div class="row g-4 mt-1"><?php foreach ([['title' => 'Assigned jobcards', 'items' => $assignedJobcards, 'description' => 'Newly assigned work waiting to be started.', 'border' => 'border-primary', 'badge' => 'primary'], ['title' => 'In-progress jobcards', 'items' => $inProgressJobcards, 'description' => 'Work currently being handled by you.', 'border' => 'border-info', 'badge' => 'info']] as $panel): ?><div class="col-lg-6"><div class="card h-100 <?= $panel['border'] ?>"><div class="card-body"><div class="d-flex justify-content-between align-items-center mb-3"><div><h2 class="h5 mb-1"><?= e($panel['title']) ?></h2><p class="text-muted mb-0"><?= e($panel['description']) ?></p></div><span class="badge text-bg-<?= e($panel['badge']) ?>"><?= count($panel['items']) ?></span></div><?php if (!$panel['items']): ?><p class="text-muted mb-0">None currently.</p><?php else: ?><div class="list-group list-group-flush"><?php foreach ($panel['items'] as $item): ?><a class="list-group-item list-group-item-action px-0 d-flex justify-content-between align-items-center" href="/?route=jobcard&id=<?= (int)$item['id'] ?>"><span><strong><?= e($item['reference_no']) ?></strong><span class="text-muted ms-2"><?= e($item['client_name']) ?></span></span><span class="badge text-bg-<?= $item['priority'] === 'critical' ? 'danger' : ($item['priority'] === 'high' ? 'warning' : 'secondary') ?>"><?= e(ucfirst($item['priority'])) ?></span></a><?php endforeach; ?></div><?php endif; ?></div></div></div><?php endforeach; ?></div><?php endif; ?><?php render_footer(); exit;
}
$permissionByRoute = ['clients'=>'clients.view','jobcards'=>'jobcards.view','reports'=>'reports.view','users'=>'users.manage','audit'=>'audit.view'];