Jul 8 - Update scheduled inspection

This commit is contained in:
2026-07-08 15:46:14 -04:00
parent f08ca997d7
commit 4d661e9776
15 changed files with 795 additions and 6 deletions
@@ -0,0 +1,67 @@
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-lg-7">
<div class="card shadow-sm">
<div class="card-header bg-light"><h5 class="mb-0">{{ title }}</h5></div>
<div class="card-body">
<form method="POST" novalidate>
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.facility_id.label(class="form-label fw-semibold") }}
{{ form.facility_id(class="form-select") }}
{% for e in form.facility_id.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
</div>
<div class="mb-3">
{{ form.template_id.label(class="form-label fw-semibold") }}
{{ form.template_id(class="form-select") }}
{% for e in form.template_id.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
</div>
<div class="mb-3">
{{ form.inspector_id.label(class="form-label fw-semibold") }}
{{ form.inspector_id(class="form-select") }}
{% for e in form.inspector_id.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
</div>
<div class="row">
<div class="col-md-6 mb-3">
{{ form.frequency.label(class="form-label fw-semibold") }}
{{ form.frequency(class="form-select") }}
</div>
<div class="col-md-6 mb-3">
{{ form.next_due_date.label(class="form-label fw-semibold") }}
{{ form.next_due_date(class="form-control", type="date") }}
{% for e in form.next_due_date.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
</div>
</div>
<div class="mb-3">
{{ form.notes.label(class="form-label fw-semibold") }}
{{ form.notes(class="form-control", rows=2, placeholder="Optional instructions for the inspector…") }}
</div>
<div class="form-check mb-3">
{{ form.active(class="form-check-input") }}
{{ form.active.label(class="form-check-label") }}
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Save</button>
<a href="{{ url_for('scheduled_inspections.index') }}" class="btn btn-outline-secondary">Cancel</a>
</div>
</form>
</div>
</div>
<p class="text-muted small mt-2">
Recurring schedules automatically roll their due date forward each time the
inspection is completed. The assigned inspector is reminded the day before
and on the due date; managers are alerted if it becomes overdue.
</p>
</div>
</div>
{% endblock %}
@@ -0,0 +1,96 @@
{% extends "base.html" %}
{% block title %}Scheduled Inspections{% endblock %}
{% block content %}
<div class="row mb-4 align-items-center">
<div class="col">
<h2><i class="bi bi-calendar-check"></i> Scheduled Inspections</h2>
<p class="text-muted mb-0">Planned and recurring inspection assignments.</p>
</div>
<div class="col-auto d-flex gap-2">
<a href="{{ url_for('inspections.index') }}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Inspections
</a>
{% if current_user.role in ['admin','director','project_manager'] %}
<a href="{{ url_for('scheduled_inspections.create') }}" class="btn btn-primary">
<i class="bi bi-plus-circle"></i> New Schedule
</a>
{% endif %}
</div>
</div>
<div class="card shadow-sm">
<div class="card-body p-0">
{% if schedules %}
<div class="table-responsive">
<table class="table table-hover mb-0 align-middle">
<thead class="table-light">
<tr>
<th>Facility</th>
<th>Template</th>
<th>Inspector</th>
<th>Frequency</th>
<th>Next Due</th>
<th>Status</th>
<th class="text-end"></th>
</tr>
</thead>
<tbody>
{% for s in schedules %}
{% set overdue = s.active and s.next_due_date < today %}
{% set due_soon = s.active and not overdue and (s.next_due_date - today).days <= 7 %}
<tr class="{{ 'table-danger' if overdue else 'table-warning' if due_soon else '' }}">
<td><strong>{{ s.facility.name if s.facility else '—' }}</strong></td>
<td>{{ s.template.name if s.template else '—' }}</td>
<td>{{ s.inspector.display_name if s.inspector else '— Unassigned —' }}</td>
<td><span class="badge bg-secondary">{{ s.frequency_label }}</span></td>
<td>
{{ s.next_due_date.strftime('%b %d, %Y') }}
{% if overdue %}
<span class="badge bg-danger ms-1"><i class="bi bi-alarm"></i> Overdue</span>
{% elif due_soon %}
<span class="badge bg-warning text-dark ms-1">Due soon</span>
{% endif %}
</td>
<td>
{% if s.active %}
<span class="badge bg-success">Active</span>
{% else %}
<span class="badge bg-secondary">Inactive</span>
{% endif %}
</td>
<td class="text-end text-nowrap">
{% if s.active and (current_user.role in ['admin','director','project_manager']
or (current_user.role == 'inspector' and s.inspector_id == current_user.id)) %}
<a href="{{ url_for('scheduled_inspections.start', schedule_id=s.id) }}"
class="btn btn-sm btn-success" title="Start this inspection">
<i class="bi bi-play-fill"></i> Start
</a>
{% endif %}
{% if current_user.role in ['admin','director','project_manager'] %}
<a href="{{ url_for('scheduled_inspections.edit', schedule_id=s.id) }}"
class="btn btn-sm btn-outline-primary"><i class="bi bi-pencil"></i></a>
<form method="POST" class="d-inline"
action="{{ url_for('scheduled_inspections.delete', schedule_id=s.id) }}"
onsubmit="return confirm('Delete this scheduled inspection?');">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-sm btn-outline-danger"><i class="bi bi-trash"></i></button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-4 text-muted text-center">
No scheduled inspections yet.
{% if current_user.role in ['admin','director','project_manager'] %}
<a href="{{ url_for('scheduled_inspections.create') }}">Create one</a>.
{% endif %}
</div>
{% endif %}
</div>
</div>
{% endblock %}