{% extends "base.html" %} {% block title %}Inspections{% endblock %} {# MODERN inspections list (design A/B test). Same context variables, same query params, same form field names and the same three JS blocks as templates/inspections/list.html — only the chrome differs. Nothing was dropped: every filter, column, badge, the pagination links and the delete modal are carried over verbatim. `insp-list-link` is preserved on the View/Continue buttons so filter-state restore on Back still works. #} {% block content %} {# Any non-empty query param other than the page number means the user has actually filtered — used to show the match count only when it is meaningful. #} {% set active_filters = [] %} {% for _k, _v in request.args.items() %} {% if _k != 'page' and _v %}{% set _ = active_filters.append(_k) %}{% endif %} {% endfor %} {# ── Header ───────────────────────────────────────────────────────────── #}
Inspections
{# Customer Directors schedule inspections for their own facilities, so the Scheduled link is theirs too — but starting an ad-hoc inspection is not. #}
Scheduled {% if current_user.role != 'customer' %} New Inspection {% endif %}
{# ── Filters ──────────────────────────────────────────────────────────── #} {# Layout: fields fill two rows on the left; the actions sit in a block on the right that spans both rows — Filter full-height, Clear above Export PDF. Below the md breakpoint the action block wraps underneath, full width. #}
{# ── Fields ──────────────────────────────────────────────────────── #}
{# Second row. The score fields absorb the Inspector column's width when the viewer is an inspector (they only ever see their own work, so the dropdown is not rendered for them) — the row always totals 12. #}
{% if inspectors %}
{% endif %}
{# ── Actions — spans both field rows ─────────────────────────────── #} {# mt-md-4 drops the block by roughly one label's height, so the buttons line up with the first row's INPUTS rather than its labels — that is what makes them shorter, since they still stretch to the bottom of the second row. The margin is md-only; below that the block wraps underneath the fields and needs its full width and natural height. #}
{# ── Results ──────────────────────────────────────────────────────────── #}
{% if active_filters %}
{{ inspections.total }} inspection{{ 's' if inspections.total != 1 }} match {{ 'es' if inspections.total == 1 }} your filters
{% endif %} {% if inspections.items %} {% include 'partials/bulk_inspections_toolbar.html' %}
{% for ins in inspections.items %} {% endfor %}
#DateContractFacilityArea TemplateInspectorScore Status
#{{ ins.id }} {{ ins.inspection_date.strftime('%Y-%m-%d %H:%M') }} {{ ins.facility.project.name if ins.facility and ins.facility.project else '—' }} {{ ins.facility.name }} {% if ins.area %}{{ ins.area.name }}{% else %}{% endif %} {{ ins.template.name }} {% if ins.scheduled_inspection_id %} Scheduled {% endif %} {{ ins.inspector.display_name }} {% if ins.overall_score %} {{ ins.overall_score }}% {% else %}{% endif %} {{ 'Submitted' if ins.status == 'completed' else ins.status|replace('_',' ')|title }} {% if ins.status == 'in_progress' %} {% set hours_open = ((now - ins.inspection_date).total_seconds() / 3600) %} {% if hours_open > 24 %} Stale {% endif %} {% endif %} {% if ins.follow_up_required and not ins.follow_ups.count() %} Follow-up {% endif %} {% if ins.status == 'in_progress' or ins.status == 'flagged' %} Continue {% else %} View {% endif %} {% if current_user.role in ['admin', 'director'] %} {% endif %}
{# Pagination #} {% if inspections.pages > 1 %}
{% endif %} {% else %}
No inspections found.
{% endif %}
{% if current_user.role in ['admin', 'director'] %} {% endif %} {% endblock %} {% block extra_js %} {% include 'partials/bulk_select_js.html' %} {% if current_user.role in ['admin', 'director'] %} {% endif %} {% endblock %}