Jul 10 - Update codes to catch up with the single tenant project
This commit is contained in:
@@ -178,6 +178,54 @@
|
||||
|
||||
</div>
|
||||
|
||||
{# ── Open Issues by Handler (phase39) — staff only ──────────────────────── #}
|
||||
{% if current_user.role not in ['customer'] %}
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-12 col-md-4">
|
||||
<a href="{{ url_for('issues.index', status='open', handler_type='internal') }}" class="text-decoration-none">
|
||||
<div class="card h-100 border-0" style="background:#e0f2fe;">
|
||||
<div class="card-body d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="small fw-semibold text-muted text-uppercase mb-1" style="font-size:.7rem;">Janitorial Staff</div>
|
||||
<div class="fs-2 fw-bold" style="color:#0369a1;">{{ handler_breakdown.internal }}</div>
|
||||
<div class="small text-muted">Open issues — our team</div>
|
||||
</div>
|
||||
<i class="bi bi-people" style="font-size:1.8rem;color:#0ea5e9;opacity:.35;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<a href="{{ url_for('issues.index', status='open', handler_type='facility') }}" class="text-decoration-none">
|
||||
<div class="card h-100 border-0" style="background:#fef9c3;">
|
||||
<div class="card-body d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="small fw-semibold text-muted text-uppercase mb-1" style="font-size:.7rem;">Facility Staff</div>
|
||||
<div class="fs-2 fw-bold" style="color:#a16207;">{{ handler_breakdown.facility }}</div>
|
||||
<div class="small text-muted">Open issues — facility contact</div>
|
||||
</div>
|
||||
<i class="bi bi-building" style="font-size:1.8rem;color:#eab308;opacity:.35;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<a href="{{ url_for('issues.index', status='open', handler_type='vendor') }}" class="text-decoration-none">
|
||||
<div class="card h-100 border-0" style="background:#fce7f3;">
|
||||
<div class="card-body d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="small fw-semibold text-muted text-uppercase mb-1" style="font-size:.7rem;">External Vendor</div>
|
||||
<div class="fs-2 fw-bold" style="color:#9d174d;">{{ handler_breakdown.vendor }}</div>
|
||||
<div class="small text-muted">Open issues — contractor</div>
|
||||
</div>
|
||||
<i class="bi bi-person-gear" style="font-size:1.8rem;color:#ec4899;opacity:.35;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# ── SLA Summary ─────────────────────────────────────────────────────────── #}
|
||||
{% if sla_breached > 0 or sla_at_risk > 0 %}
|
||||
<div class="row g-3 mb-4">
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
<body>
|
||||
<div class="fq-wrap">
|
||||
|
||||
{% if request.args.get('reported') == '1' %}
|
||||
<div class="alert alert-success d-flex align-items-center gap-2 mb-3" role="alert">
|
||||
<i class="bi bi-check-circle-fill fs-5"></i>
|
||||
<div><strong>Report submitted.</strong> Our team has been notified and will follow up.</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<i class="bi bi-building fs-3 text-primary"></i>
|
||||
<div>
|
||||
@@ -170,6 +177,42 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{# ── Report a problem ── #}
|
||||
<div class="card shadow-sm mb-3">
|
||||
<div class="card-header bg-white fw-semibold py-2">
|
||||
<i class="bi bi-megaphone text-danger"></i> Report a Problem
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted small mb-3">
|
||||
See something that needs attention? Let our team know and we'll take care of it.
|
||||
</p>
|
||||
<form method="POST" action="{{ url_for('facility_qr.report', token=token) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
{# Honeypot — invisible to humans, filled by bots #}
|
||||
<div style="position:absolute;left:-9999px;top:-9999px;" aria-hidden="true">
|
||||
<input type="text" name="website" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">What did you observe? <span class="text-danger">*</span></label>
|
||||
<textarea name="description" class="form-control form-control-sm" rows="3"
|
||||
placeholder="Describe the issue (e.g. restroom out of paper towels, spill in lobby…)"
|
||||
required maxlength="2000"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Urgency</label>
|
||||
<select name="severity" class="form-select form-select-sm">
|
||||
<option value="low">Low — not urgent</option>
|
||||
<option value="medium" selected>Medium — needs attention soon</option>
|
||||
<option value="high">High — urgent</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-danger btn-sm w-100">
|
||||
<i class="bi bi-send me-1"></i> Submit Report
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center text-muted small mt-2 mb-1">
|
||||
{% if last_date %}Last inspected {{ last_date.strftime('%b %d, %Y') }} · {% endif %}
|
||||
Snapshot generated {{ generated_at.strftime('%b %d, %Y %I:%M %p') }} ET
|
||||
|
||||
@@ -82,6 +82,24 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% if current_user.role not in ['customer'] %}
|
||||
<div class="col-md-2">
|
||||
<label class="form-label small mb-1">Handled By</label>
|
||||
<select name="handler_type" class="form-select form-select-sm">
|
||||
<option value="">All</option>
|
||||
<option value="internal" {{ 'selected' if handler_type_filter == 'internal' }}>Janitorial Staff</option>
|
||||
<option value="facility" {{ 'selected' if handler_type_filter == 'facility' }}>Facility Staff</option>
|
||||
<option value="vendor" {{ 'selected' if handler_type_filter == 'vendor' }}>External Vendor</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<div class="form-check form-switch mb-0">
|
||||
<input class="form-check-input" type="checkbox" name="unassigned" value="1" id="unassignedCheck"
|
||||
{{ 'checked' if unassigned_filter }}>
|
||||
<label class="form-check-label small" for="unassignedCheck">Unassigned only</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col-auto d-flex align-items-end gap-2 flex-wrap">
|
||||
<button type="submit" class="btn btn-sm btn-outline-primary">Filter</button>
|
||||
<a href="{{ url_for('issues.index') }}" class="btn btn-sm btn-outline-secondary">Clear</a>
|
||||
|
||||
@@ -76,6 +76,28 @@
|
||||
<dt class="col-sm-3">Assigned To</dt>
|
||||
<dd class="col-sm-9">{{ issue.assigned_user.display_name if issue.assigned_user else '— Unassigned —' }}</dd>
|
||||
|
||||
{% if issue.handler_type and issue.handler_type != 'internal' %}
|
||||
<dt class="col-sm-3">Handled By</dt>
|
||||
<dd class="col-sm-9">
|
||||
{% if issue.handler_type == 'facility' %}
|
||||
<span class="badge bg-secondary">
|
||||
<i class="bi bi-building me-1"></i>Facility Staff
|
||||
</span>
|
||||
{% if issue.facility_handler_name %}
|
||||
<span class="ms-2 fw-semibold">{{ issue.facility_handler_name }}</span>
|
||||
{% if issue.facility_handler_contact %}
|
||||
<span class="text-muted ms-2">{{ issue.facility_handler_contact }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if issue.facility_handler_notes %}
|
||||
<div class="text-muted small mt-1" style="white-space:pre-wrap;">{{ issue.facility_handler_notes }}</div>
|
||||
{% endif %}
|
||||
{% elif issue.handler_type == 'vendor' %}
|
||||
<span class="badge bg-dark"><i class="bi bi-person-gear me-1"></i>External Vendor</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if issue.vendor_name %}
|
||||
<dt class="col-sm-3">Contractor</dt>
|
||||
<dd class="col-sm-9">
|
||||
@@ -366,6 +388,46 @@
|
||||
</div>
|
||||
{% if current_user.role in ['admin','director','project_manager'] %}
|
||||
<hr class="my-3">
|
||||
<p class="fw-semibold small mb-2">
|
||||
<i class="bi bi-person-check me-1 text-secondary"></i>Handler / Ownership
|
||||
</p>
|
||||
<div class="mb-3">
|
||||
{{ form.handler_type.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.handler_type(class="form-select form-select-sm",
|
||||
id="handlerTypeSelect") }}
|
||||
</div>
|
||||
<div id="facilityHandlerFields"
|
||||
style="{{ '' if issue.handler_type == 'facility' else 'display:none;' }}">
|
||||
<div class="mb-2">
|
||||
{{ form.facility_handler_name.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.facility_handler_name(class="form-control form-control-sm",
|
||||
placeholder="Contact name at the facility",
|
||||
value=issue.facility_handler_name or '') }}
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
{{ form.facility_handler_contact.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.facility_handler_contact(class="form-control form-control-sm",
|
||||
placeholder="Phone or email",
|
||||
value=issue.facility_handler_contact or '') }}
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{{ form.facility_handler_notes.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.facility_handler_notes(class="form-control form-control-sm", rows=2,
|
||||
placeholder="Notes about what they are handling…") }}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function(){
|
||||
var sel = document.getElementById('handlerTypeSelect');
|
||||
var box = document.getElementById('facilityHandlerFields');
|
||||
if(sel && box){
|
||||
sel.addEventListener('change', function(){
|
||||
box.style.display = (this.value === 'facility') ? '' : 'none';
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<hr class="my-3">
|
||||
<p class="fw-semibold small mb-2">
|
||||
<i class="bi bi-person-gear me-1 text-secondary"></i>External Contractor
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user