From d7412fcced0fd14a16834e8b78176bcf5396aab1 Mon Sep 17 00:00:00 2001 From: louispaulb Date: Wed, 8 Jul 2026 14:31:39 -0400 Subject: [PATCH] #27 Standardise ticket-detail rendering (status / tags / row component) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converge every ticket-detail surface onto the canonical IssueDetail (in DetailModal) + TicketCard, per reference_ticket_detail_disparities. STATUS — one model: - IssueDetail no longer double-renders status. The green button (shared TicketStatusControl) is relabelled "Reporter" with a schedule icon — it is a postpone/snooze + quick-close control, not a 2nd status setter. The single 5-value status select (Open/Replied/On Hold/Resolved/Closed) is canonical. TAGS — one source, via the shared TagEditor: - New useTagCatalog composable unifies the tag catalogue: ERPNext "Dispatch Tag" ∪ roster technician skills (hub /roster/technicians). Roster skills like "sans-fil"/"épissure" now appear on ticket tags (were missing before). - IssueDetail replaces its bespoke q-select + chip row with TagEditor; the tag manager (rename/recolor/delete) is delegated to the composable's CRUD. ONE ticket-row component (TicketCard): - LocationCard's ad-hoc per-address ticket list now renders TicketCard. - TicketsPage mobile card mode (DataTable #item slot) renders TicketCard. - assignee handling (assigned_staff/opened_by_staff avatars) is now consistent across fiche, location, and /tickets. Verified in local preview against live backend: Reporter button + single status select, TagEditor dropdown surfacing roster skills ("sans-fil" under "Compétence"), TicketCard rows on fiche + LocationCard, no component errors. Co-Authored-By: Claude Opus 4.8 --- .../src/components/customer/LocationCard.vue | 32 +--- .../components/shared/TicketStatusControl.vue | 8 +- .../shared/detail-sections/IssueDetail.vue | 155 +++++------------- apps/ops/src/composables/useTagCatalog.js | 112 +++++++++++++ apps/ops/src/pages/TicketsPage.vue | 8 + 5 files changed, 177 insertions(+), 138 deletions(-) create mode 100644 apps/ops/src/composables/useTagCatalog.js diff --git a/apps/ops/src/components/customer/LocationCard.vue b/apps/ops/src/components/customer/LocationCard.vue index 2aa999f..54d4dd7 100644 --- a/apps/ops/src/components/customer/LocationCard.vue +++ b/apps/ops/src/components/customer/LocationCard.vue @@ -246,29 +246,10 @@ Créer un ticket pour cette adresse -
-
- -
- {{ t.legacy_ticket_id || t.name }} - {{ t.subject }} -
-
- - {{ staffInitials(t.opened_by_staff) }} - {{ t.opened_by_staff }} - - - {{ staffInitials(t.assigned_staff) }} - {{ t.assigned_staff }} - -
- {{ t.opening_date }} - {{ t.status }} -
-
+ + @@ -284,9 +265,10 @@ // comportement identique (mêmes closures, même invalidation de cache). import InlineField from 'src/components/shared/InlineField.vue' import DeviceStrip from 'src/components/customer/DeviceStrip.vue' +import TicketCard from 'src/components/customer/TicketCard.vue' import draggable from 'vuedraggable' -import { formatMoney, formatDate, staffColor, staffInitials } from 'src/composables/useFormatters' -import { locStatusClass, ticketStatusClass } from 'src/composables/useStatusClasses' +import { formatMoney, formatDate } from 'src/composables/useFormatters' +import { locStatusClass } from 'src/composables/useStatusClasses' import { isRebate, subMainLabel, sectionTotal, annualPrice } from 'src/composables/useSubscriptionGroups' import { usePermissions } from 'src/composables/usePermissions' import { locInlineFields } from 'src/data/client-constants' diff --git a/apps/ops/src/components/shared/TicketStatusControl.vue b/apps/ops/src/components/shared/TicketStatusControl.vue index e7f09c4..5de3492 100644 --- a/apps/ops/src/components/shared/TicketStatusControl.vue +++ b/apps/ops/src/components/shared/TicketStatusControl.vue @@ -1,7 +1,9 @@ + +