06/10 Reorganize customer dashboard sections
This commit is contained in:
+112
-97
@@ -126,103 +126,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# ── Customer portal: scoped facilities panel ───────────────────────────── #}
|
|
||||||
{% if current_user.role == 'customer' %}
|
|
||||||
<div class="row g-3 mb-4">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<div class="card-header bg-light fw-semibold d-flex justify-content-between align-items-center">
|
|
||||||
<span><i class="bi bi-building me-1"></i> Your Facilities</span>
|
|
||||||
{% if customer_facilities %}
|
|
||||||
<span class="badge bg-secondary rounded-pill">{{ customer_facilities|length }}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% if customer_facilities %}
|
|
||||||
<div class="card-body pb-2">
|
|
||||||
{% if customer_facilities|length > 6 %}
|
|
||||||
<div class="mb-3">
|
|
||||||
<input type="text" id="facilitySearch" class="form-control form-control-sm"
|
|
||||||
placeholder="Search facilities…">
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row g-2" id="facilityGrid">
|
|
||||||
{% for f in customer_facilities %}
|
|
||||||
<div class="col-12 col-sm-6 col-lg-4 facility-col">
|
|
||||||
<div class="border rounded p-2 h-100 d-flex flex-column facility-card">
|
|
||||||
<div class="fw-semibold mb-1 small">{{ f.name }}</div>
|
|
||||||
<div class="text-muted" style="font-size:.8rem;">{{ f.address or '—' }}</div>
|
|
||||||
<div class="my-1">
|
|
||||||
<span class="badge bg-light text-dark border" style="font-size:.75rem;">
|
|
||||||
{{ f.project.name if f.project else '—' }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="mt-auto pt-1">
|
|
||||||
<a href="{{ url_for('facilities.view_facility', facility_id=f.id) }}"
|
|
||||||
class="btn btn-sm btn-outline-primary">
|
|
||||||
<i class="bi bi-eye"></i> View
|
|
||||||
</a>
|
|
||||||
<a href="{{ url_for('reports.facility_report', facility_id=f.id) }}"
|
|
||||||
class="btn btn-sm btn-outline-secondary ms-1">
|
|
||||||
<i class="bi bi-graph-up"></i> Report
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% if customer_facilities|length > 9 %}
|
|
||||||
<div id="facilityShowMore" class="text-center mt-3">
|
|
||||||
<button class="btn btn-sm btn-link text-muted" id="toggleFacilities">
|
|
||||||
Show all {{ customer_facilities|length }} facilities <i class="bi bi-chevron-down"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="card-body text-muted small">
|
|
||||||
<i class="bi bi-info-circle me-1"></i>
|
|
||||||
No facilities have been assigned to your account yet. Please contact your administrator.
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if current_user.role == 'customer' and customer_facilities and customer_facilities|length > 9 %}
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
const VISIBLE = 9;
|
|
||||||
const cols = document.querySelectorAll('#facilityGrid .facility-col');
|
|
||||||
const btn = document.getElementById('toggleFacilities');
|
|
||||||
const more = document.getElementById('facilityShowMore');
|
|
||||||
let expanded = false;
|
|
||||||
|
|
||||||
cols.forEach((c, i) => { if (i >= VISIBLE) c.style.display = 'none'; });
|
|
||||||
|
|
||||||
btn.addEventListener('click', function () {
|
|
||||||
expanded = !expanded;
|
|
||||||
cols.forEach((c, i) => {
|
|
||||||
if (i >= VISIBLE) c.style.display = expanded ? '' : 'none';
|
|
||||||
});
|
|
||||||
btn.innerHTML = expanded
|
|
||||||
? 'Show fewer <i class="bi bi-chevron-up"></i>'
|
|
||||||
: 'Show all {{ customer_facilities|length }} facilities <i class="bi bi-chevron-down"></i>';
|
|
||||||
});
|
|
||||||
|
|
||||||
{% if customer_facilities|length > 6 %}
|
|
||||||
document.getElementById('facilitySearch').addEventListener('input', function () {
|
|
||||||
const q = this.value.toLowerCase();
|
|
||||||
cols.forEach(col => {
|
|
||||||
const match = col.querySelector('.facility-card').textContent.toLowerCase().includes(q);
|
|
||||||
col.style.display = match ? '' : 'none';
|
|
||||||
});
|
|
||||||
more.style.display = this.value ? 'none' : '';
|
|
||||||
});
|
|
||||||
{% endif %}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{# ── System quick stats (admin/director) ─────────────────────────────────── #}
|
{# ── System quick stats (admin/director) ─────────────────────────────────── #}
|
||||||
{% if current_user.role in ['admin', 'director'] %}
|
{% if current_user.role in ['admin', 'director'] %}
|
||||||
@@ -464,6 +367,118 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# ── Customer portal: scoped facilities panel ───────────────────────────── #}
|
||||||
|
{% if current_user.role == 'customer' %}
|
||||||
|
<div class="row g-3 mt-2">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-light fw-semibold d-flex justify-content-between align-items-center"
|
||||||
|
role="button" data-bs-toggle="collapse" data-bs-target="#facilitiesBody"
|
||||||
|
aria-expanded="true" aria-controls="facilitiesBody" style="cursor:pointer;">
|
||||||
|
<span><i class="bi bi-building me-1"></i> Your Facilities
|
||||||
|
<i class="bi bi-chevron-down ms-1 small" id="facilitiesChevron"></i>
|
||||||
|
</span>
|
||||||
|
{% if customer_facilities %}
|
||||||
|
<span class="badge bg-secondary rounded-pill">{{ customer_facilities|length }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="collapse show" id="facilitiesBody">
|
||||||
|
{% if customer_facilities %}
|
||||||
|
<div class="card-body pb-2">
|
||||||
|
{% if customer_facilities|length > 6 %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="text" id="facilitySearch" class="form-control form-control-sm"
|
||||||
|
placeholder="Search facilities…">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row g-2" id="facilityGrid">
|
||||||
|
{% for f in customer_facilities %}
|
||||||
|
<div class="col-12 col-sm-6 col-lg-4 facility-col">
|
||||||
|
<div class="border rounded p-2 h-100 d-flex flex-column facility-card">
|
||||||
|
<div class="fw-semibold mb-1 small">{{ f.name }}</div>
|
||||||
|
<div class="text-muted" style="font-size:.8rem;">{{ f.address or '—' }}</div>
|
||||||
|
<div class="my-1">
|
||||||
|
<span class="badge bg-light text-dark border" style="font-size:.75rem;">
|
||||||
|
{{ f.project.name if f.project else '—' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-auto pt-1">
|
||||||
|
<a href="{{ url_for('facilities.view_facility', facility_id=f.id) }}"
|
||||||
|
class="btn btn-sm btn-outline-primary">
|
||||||
|
<i class="bi bi-eye"></i> View
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('reports.facility_report', facility_id=f.id) }}"
|
||||||
|
class="btn btn-sm btn-outline-secondary ms-1">
|
||||||
|
<i class="bi bi-graph-up"></i> Report
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% if customer_facilities|length > 9 %}
|
||||||
|
<div id="facilityShowMore" class="text-center mt-3">
|
||||||
|
<button class="btn btn-sm btn-link text-muted" id="toggleFacilities">
|
||||||
|
Show all {{ customer_facilities|length }} facilities <i class="bi bi-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="card-body text-muted small">
|
||||||
|
<i class="bi bi-info-circle me-1"></i>
|
||||||
|
No facilities have been assigned to your account yet. Please contact your administrator.
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var collapseEl = document.getElementById('facilitiesBody');
|
||||||
|
var chevron = document.getElementById('facilitiesChevron');
|
||||||
|
collapseEl.addEventListener('hide.bs.collapse', function () {
|
||||||
|
chevron.classList.replace('bi-chevron-down', 'bi-chevron-up');
|
||||||
|
});
|
||||||
|
collapseEl.addEventListener('show.bs.collapse', function () {
|
||||||
|
chevron.classList.replace('bi-chevron-up', 'bi-chevron-down');
|
||||||
|
});
|
||||||
|
{% if customer_facilities and customer_facilities|length > 9 %}
|
||||||
|
var VISIBLE = 9;
|
||||||
|
var cols = document.querySelectorAll('#facilityGrid .facility-col');
|
||||||
|
var btn = document.getElementById('toggleFacilities');
|
||||||
|
var more = document.getElementById('facilityShowMore');
|
||||||
|
var expanded = false;
|
||||||
|
|
||||||
|
cols.forEach(function (c, i) { if (i >= VISIBLE) c.style.display = 'none'; });
|
||||||
|
|
||||||
|
btn.addEventListener('click', function () {
|
||||||
|
expanded = !expanded;
|
||||||
|
cols.forEach(function (c, i) {
|
||||||
|
if (i >= VISIBLE) c.style.display = expanded ? '' : 'none';
|
||||||
|
});
|
||||||
|
btn.innerHTML = expanded
|
||||||
|
? 'Show fewer <i class="bi bi-chevron-up"></i>'
|
||||||
|
: 'Show all {{ customer_facilities|length }} facilities <i class="bi bi-chevron-down"></i>';
|
||||||
|
});
|
||||||
|
{% endif %}
|
||||||
|
{% if customer_facilities and customer_facilities|length > 6 %}
|
||||||
|
document.getElementById('facilitySearch').addEventListener('input', function () {
|
||||||
|
var q = this.value.toLowerCase();
|
||||||
|
document.querySelectorAll('#facilityGrid .facility-col').forEach(function (col) {
|
||||||
|
var match = col.querySelector('.facility-card').textContent.toLowerCase().includes(q);
|
||||||
|
col.style.display = match ? '' : 'none';
|
||||||
|
});
|
||||||
|
var more2 = document.getElementById('facilityShowMore');
|
||||||
|
if (more2) more2.style.display = this.value ? 'none' : '';
|
||||||
|
});
|
||||||
|
{% endif %}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||||
|
|
||||||
{% if trend_labels %}
|
{% if trend_labels %}
|
||||||
|
|||||||
Reference in New Issue
Block a user