feat(projects): projects page overhaul — events, header, module toolbars, cards

Addresses a batch of projects-page UX issues:

1. Vibration Events sub-tab: add a Location filter + clickable column
   sorting (Timestamp/Location/Serial/Tran/Vert/Long/PVS/Mic). Events are
   cached client-side so location-filter and sort are instant (no SFM refetch).

3. Drop the misleading single-module "Sound Monitoring" subtitle on the
   Overview card (combined projects have multiple modules); show the
   project number · client identity instead.

4. Header cleanup: move the sound-only actions (Generate Combined Report,
   Night Report, Report Settings) and the Manual/Remote chip out of the
   global project header and into the Sound tab's module toolbar. The header
   now carries project-level concerns only (status, modules, merge). The
   Night Report / Report Settings modals stay defined in the header partial
   (global), so the relocated buttons still call them.

2. Per-module status UI: each module tab gets a status dropdown
   (active/on_hold/completed) wired to the new endpoint; the header module
   chips show a "✓ Done" / "On hold" badge.

5. Project cards redesigned: module mix accent strip, Sound/Vibration chips
   with per-module status, project number · client identity, and per-module
   "Sound"/"Vibration" quick-open buttons that deep-link into that module's
   tab (#sound / #vibration).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015m9FuJvk65kJmmP3c9c6r1
This commit is contained in:
2026-06-22 20:24:40 +00:00
parent 092b72f63c
commit f54c62b332
4 changed files with 293 additions and 129 deletions
@@ -3,13 +3,14 @@
<div class="flex flex-col md:flex-row md:items-start md:justify-between gap-4">
<div>
<h2 class="text-2xl font-semibold text-gray-900 dark:text-white">{{ project.name }}</h2>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">
{% if project_type %}
{{ project_type.name }}
{% else %}
Project
{% endif %}
</p>
{# Identity line — project number / client, not a module name. The
enabled modules are already shown as chips in the page header. #}
{% set _idbits = [] %}
{% if project.project_number %}{% set _ = _idbits.append(project.project_number) %}{% endif %}
{% if project.client_name %}{% set _ = _idbits.append(project.client_name) %}{% endif %}
{% if _idbits %}
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ _idbits | join(' · ') }}</p>
{% endif %}
</div>
{% if project.status == 'upcoming' %}
<span class="px-3 py-1 text-xs font-medium bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300 rounded-full">Upcoming</span>