diff --git a/.claude/settings.json b/.claude/settings.json index 59b344b..6162dc8 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -13,7 +13,8 @@ "Bash(python -c \"print\\(len\\('phase47_sched_acknowledged'\\)\\)\")", "Bash(python -c \"import ast,io; ast.parse\\(io.open\\('app/routes/scheduled_inspections.py',encoding='utf-8'\\).read\\(\\)\\); print\\('route OK'\\)\")", "Bash(python -c \"import ast,io; ast.parse\\(io.open\\('app/utils/notifications.py',encoding='utf-8'\\).read\\(\\)\\); print\\('notif OK'\\)\")", - "Bash(SECRET_KEY=x DATABASE_URL=sqlite:///:memory: DIGEST_SECRET=x MAIL_SERVER=localhost MAIL_USERNAME=x MAIL_PASSWORD=x MAIL_PORT=587 APP_BASE_URL=http://localhost MAIL_DEFAULT_SENDER=x@x.com python -c ' *)" + "Bash(SECRET_KEY=x DATABASE_URL=sqlite:///:memory: DIGEST_SECRET=x MAIL_SERVER=localhost MAIL_USERNAME=x MAIL_PASSWORD=x MAIL_PORT=587 APP_BASE_URL=http://localhost MAIL_DEFAULT_SENDER=x@x.com python -c ' *)", + "Bash(python -c \"import ast,io; ast.parse\\(io.open\\('app/routes/dashboard.py',encoding='utf-8'\\).read\\(\\)\\); print\\('dashboard route OK'\\)\")" ] } } diff --git a/app/routes/dashboard.py b/app/routes/dashboard.py index dc747d6..1e7a278 100644 --- a/app/routes/dashboard.py +++ b/app/routes/dashboard.py @@ -294,6 +294,23 @@ def index(): stale_q = stale_q.filter(False) stale_in_progress = stale_q.count() + # ── In-progress inspections (all, not just stale) — "In Progress" tile ───── + inprog_q = Inspection.query.filter(Inspection.status == 'in_progress') + if is_inspector: + if not inspector_facility_ids: + inprog_q = inprog_q.filter(False) + else: + inprog_q = inprog_q.filter( + Inspection.facility_id.in_(inspector_facility_ids), + Inspection.inspector_id == current_user.id, + ) + elif is_customer: + if customer_facility_ids: + inprog_q = inprog_q.filter(Inspection.facility_id.in_(customer_facility_ids)) + else: + inprog_q = inprog_q.filter(False) + in_progress_total = inprog_q.count() + # ── Unassigned open issues ──────────────────────────────────────────────── from app.models.facility import Area as _AreaU unassigned_q = Issue.query.outerjoin(_AreaU, Issue.area_id == _AreaU.id).filter( @@ -361,6 +378,7 @@ def index(): # ── Scheduled inspections (phase36): upcoming / overdue ────────────── sched_upcoming = [] sched_overdue_count = 0 + sched_total = 0 sched_open_inspections = {} if not is_customer: from app.models.scheduled_inspection import ScheduledInspection @@ -370,6 +388,7 @@ def index(): if is_inspector: _sq = _sq.filter(ScheduledInspection.inspector_id == current_user.id) _all_sched = _sq.order_by(ScheduledInspection.next_due_date.asc()).all() + sched_total = len(_all_sched) # active scheduled inspection plans ("On Schedules") sched_overdue_count = sum(1 for s in _all_sched if s.next_due_date < _today) # Upcoming = due today through the next 7 days (overdue shown separately) sched_upcoming = [ @@ -383,7 +402,9 @@ def index(): 'dashboard.html', sched_upcoming = sched_upcoming, sched_overdue_count = sched_overdue_count, + sched_total = sched_total, sched_open_inspections = sched_open_inspections, + in_progress_total = in_progress_total, submitted_this_week = submitted_this_week, completed_today = completed_today, open_issues = open_issues, diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 73db548..4e620b5 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -3,8 +3,34 @@ {% block content %} -{# Handler ("Handled by") breakdown chips for an issue KPI card. `base` is a - dict of extra issues.index query params identifying the card's scope. #} +{# ── Grouped dashboard styling (colored section cards + white stat tiles) ──── #} + + +{# Handler ("Handled by") breakdown chips for an issue KPI tile. `base` is a + dict of extra issues.index query params identifying the tile's scope. #} {% macro handler_chips(bd, base) %}
| Facility | Template | Inspector | Repeats | Due | |
|---|---|---|---|---|---|
| {{ s.facility.name if s.facility else '—' }} | -{{ s.template.name if s.template else '—' }} | -{{ s.inspector.display_name if s.inspector else '—' }} | -{{ s.recurrence_label }} | -{{ s.next_due_date.strftime('%b %d') }} | -- {# Start is shown only to the assignee — the inspection is theirs to do. #} - {% if s.inspector_id and s.inspector_id == current_user.id %} - {# Receipt confirmation (phase47) — assignee confirms, or shows confirmed. #} - {% if s.is_acknowledged %} - Confirmed - {% else %} - - {% endif %} - {% set open_id = sched_open_inspections.get(s.id) %} - {% if open_id %} - - Continue - {% else %} - Start - {% endif %} - {% endif %} - | -
No inspections due in the next 7 days.
- {% endif %} +{# ══════════════════════════════════════════════════════════════════════════ + A. SCHEDULED INSPECTION (blue) + ══════════════════════════════════════════════════════════════════════════ #} +{% if current_user.role != 'customer' %} +| Facility Name | Inspection Template | Inspector Name | +How Often? | Due | + |
|---|---|---|---|---|---|
| {{ s.facility.name if s.facility else '—' }} | +{{ s.template.name if s.template else '—' }} | +{{ s.inspector.display_name if s.inspector else '—' }} | +{{ s.recurrence_label }} | +{{ s.next_due_date.strftime('%b %d') }} | ++ {# Start is shown only to the assignee — the inspection is theirs to do. #} + {% if s.inspector_id and s.inspector_id == current_user.id %} + {# Receipt confirmation (phase47) — assignee confirms, or shows confirmed. #} + {% if s.is_acknowledged %} + Confirmed + {% else %} + + {% endif %} + {% set open_id = sched_open_inspections.get(s.id) %} + {% if open_id %} + + Continue + {% else %} + Start + {% endif %} + {% endif %} + | +