Files
JQC_multi_tenant/app/templates/reports/issues_aging.html
T
2026-06-26 09:04:34 -04:00

176 lines
7.1 KiB
HTML
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.
{% extends "base.html" %}
{% block title %}Issues Aging{% endblock %}
{% block content %}
{# ── Sub-nav ── #}
{% include 'reports/_subnav.html' %}
<div class="d-flex justify-content-between align-items-start mb-4">
<div>
<h2><i class="bi bi-clock-history text-danger me-2"></i>Issues Aging</h2>
<p class="text-muted mb-0">All currently open issues grouped by how long they have been waiting.</p>
</div>
<a href="{{ url_for('reports.export_issues_aging', severity=severity_filter, facility_id=facility_id_filter or '') }}"
class="btn btn-sm btn-outline-success">
<i class="bi bi-file-earmark-excel me-1"></i>Export Excel
</a>
</div>
{# ── Filters ── #}
<div class="card shadow-sm mb-4">
<div class="card-body py-2">
<form method="get" class="row g-2 align-items-end">
<div class="col-md-2">
<label class="form-label small mb-1">Severity</label>
<select name="severity" class="form-select form-select-sm">
<option value="">All</option>
{% for s in ['critical','high','medium','low'] %}
<option value="{{ s }}" {{ 'selected' if severity_filter == s }}>{{ s|title }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-4">
<label class="form-label small mb-1">Facility</label>
<select name="facility_id" class="form-select form-select-sm">
<option value="">All Facilities</option>
{% for f in facilities %}
<option value="{{ f.id }}" {{ 'selected' if facility_id_filter == f.id }}>{{ f.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-primary">Apply</button>
<a href="{{ url_for('reports.issues_aging') }}" class="btn btn-sm btn-outline-secondary">Clear</a>
</div>
</form>
</div>
</div>
{# ── KPI row ── #}
<div class="row g-3 mb-4">
<div class="col-6 col-md-4">
<div class="card shadow-sm border-0 h-100" style="background:#fff7ed;">
<div class="card-body">
<div class="small fw-semibold text-muted mb-1">Total Open</div>
<div class="fs-1 fw-bold" style="color:#ea580c;">{{ total }}</div>
<div class="small text-muted">unresolved issues</div>
</div>
</div>
</div>
<div class="col-6 col-md-4">
<div class="card shadow-sm border-0 h-100" style="background:#fef2f2;">
<div class="card-body">
<div class="small fw-semibold text-muted mb-1">SLA Breached</div>
<div class="fs-1 fw-bold text-danger">{{ sla_breached }}</div>
<div class="small text-muted">past resolution deadline</div>
</div>
</div>
</div>
<div class="col-6 col-md-4">
<div class="card shadow-sm border-0 h-100" style="background:#fefce8;">
<div class="card-body">
<div class="small fw-semibold text-muted mb-1">SLA At Risk</div>
<div class="fs-1 fw-bold text-warning">{{ sla_at_risk }}</div>
<div class="small text-muted">approaching deadline</div>
</div>
</div>
</div>
</div>
{# ── Bucket accordions ── #}
<div class="accordion" id="agingAccordion">
{% for label in bucket_labels %}
{% set bucket = buckets[label] %}
{% set bucket_id = 'bucket-' ~ loop.index %}
{% set is_danger = label in ['>4 weeks', '14 weeks'] %}
{% set is_warning = label == '37 days' %}
<div class="accordion-item mb-2 shadow-sm border-0">
<h2 class="accordion-header">
<button class="accordion-button {{ 'collapsed' if loop.index > 1 else '' }} fw-semibold"
type="button" data-bs-toggle="collapse"
data-bs-target="#{{ bucket_id }}">
<span class="badge rounded-pill me-2
{{ 'bg-danger' if is_danger else 'bg-warning text-dark' if is_warning else 'bg-secondary' }}">
{{ bucket|length }}
</span>
{{ label }}
{% if is_danger and bucket|length > 0 %}
<span class="ms-2 badge bg-danger bg-opacity-25 text-danger" style="font-size:.7rem;">Needs attention</span>
{% endif %}
</button>
</h2>
<div id="{{ bucket_id }}" class="accordion-collapse collapse {{ 'show' if loop.index == 1 else '' }}"
data-bs-parent="#agingAccordion">
<div class="accordion-body p-0">
{% if bucket %}
<div class="table-responsive">
<table class="table table-hover table-sm mb-0">
<thead class="table-light">
<tr>
<th>#</th>
<th>Age</th>
<th>Severity</th>
<th>Facility / Area</th>
<th>Description</th>
<th>Status</th>
<th>SLA</th>
<th>Assigned</th>
<th></th>
</tr>
</thead>
<tbody>
{% for item in bucket %}
{% set issue = item.issue %}
{% set sla = item.sla %}
<tr class="{{ 'table-danger' if sla == 'breached' else 'table-warning' if sla == 'at_risk' else '' }}">
<td class="text-muted small">#{{ issue.id }}</td>
<td class="text-nowrap small">{{ item.age_h }}h</td>
<td>
<span class="badge bg-{{ 'danger' if issue.severity in ['critical','high'] else 'warning text-dark' if issue.severity == 'medium' else 'secondary' }}">
{{ issue.severity|title }}
</span>
</td>
<td class="small">
{{ issue.resolved_facility.name if issue.resolved_facility else '—' }}<br>
<span class="text-muted">{{ issue.area.name if issue.area else '—' }}</span>
</td>
<td class="small">{{ issue.description[:70] }}{% if issue.description|length > 70 %}…{% endif %}</td>
<td>
<span class="badge bg-{{ 'info text-dark' if issue.status == 'pending_verification' else 'warning text-dark' if issue.status == 'in_progress' else 'secondary' }}">
{{ issue.status|replace('_',' ')|title }}
</span>
</td>
<td>
{% if sla == 'breached' %}<span class="badge bg-danger"><i class="bi bi-alarm me-1"></i>Breached</span>
{% elif sla == 'at_risk' %}<span class="badge bg-warning text-dark">At Risk</span>
{% elif sla == 'ok' %}<span class="badge bg-secondary">OK</span>
{% else %}<span class="text-muted small"></span>{% endif %}
</td>
<td class="small">{{ issue.assigned_user.display_name if issue.assigned_user else '—' }}</td>
<td>
<a href="{{ url_for('issues.view', issue_id=issue.id) }}" class="btn btn-sm btn-outline-secondary">
<i class="bi bi-eye"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-3 text-muted small">No issues in this age range.</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
{% if total == 0 %}
<div class="alert alert-success mt-3">
<i class="bi bi-check-circle me-2"></i>No open issues match the selected filters.
</div>
{% endif %}
{% endblock %}