From 936152d452ef3f0da0bcf9a1fd491a5860df155d Mon Sep 17 00:00:00 2001 From: louispaulb Date: Sat, 4 Jul 2026 20:02:11 -0400 Subject: [PATCH] =?UTF-8?q?feat(ui):=20T5=20=E2=80=94=20DynamicFilter=20su?= =?UTF-8?q?r=20Factures=20fournisseurs=20+=20File=20courriels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SupplierInvoices : toggle statut → (chips À traiter/Créées/Ignorées + recherche fournisseur/n°/expéditeur, client-side) ; presets 'filter.supplier-invoices'. - EmailQueue : select statut → chips (Not Sent/Sending/Sent/Error, → rechargement serveur via onFilterChange) + recherche destinataire/référence (client, displayRows) ; presets 'filter.email-queue'. Build vert, leak 0. DynamicFilter désormais sur 6 pages (Clients/Tickets/Évaluations/RDV/Factures fourn./File courriels). Co-Authored-By: Claude Opus 4.8 --- apps/ops/src/pages/EmailQueuePage.vue | 18 ++++++++++++++---- apps/ops/src/pages/SupplierInvoicesPage.vue | 20 +++++++++++--------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/apps/ops/src/pages/EmailQueuePage.vue b/apps/ops/src/pages/EmailQueuePage.vue index 48f67e8..a3a6c8b 100644 --- a/apps/ops/src/pages/EmailQueuePage.vue +++ b/apps/ops/src/pages/EmailQueuePage.vue @@ -2,9 +2,8 @@
File de courriels (ERPNext)
- - + @@ -25,7 +24,7 @@ byStatus.value['Not Sent'] || 0) +// Filtre dynamique : chips statut (→ rechargement serveur) + recherche destinataire/référence (client, sur les lignes chargées) + presets. +const filterState = ref({ search: '', chips: {} }) +const chipGroups = [{ key: 'statut', label: 'Statut', icon: 'label', options: statusOptions.filter(o => o.value !== '') }] +const displayRows = computed(() => { + const q = (filterState.value.search || '').toLowerCase().trim() + if (!q) return rows.value + return rows.value.filter(r => ((r.recipients || []).join(' ') + ' ' + (r.reference_doctype || '') + ' ' + (r.reference_name || '')).toLowerCase().includes(q)) +}) +function onFilterChange (s) { const ns = s.chips.statut || ''; if (ns !== status.value) { status.value = ns; load() } } + function statusColor (s) { return { 'Not Sent': 'orange-8', Sending: 'blue-6', Sent: 'green-7', Error: 'negative', Expired: 'grey-6' }[s] || 'grey-7' } diff --git a/apps/ops/src/pages/SupplierInvoicesPage.vue b/apps/ops/src/pages/SupplierInvoicesPage.vue index f5e31ac..281ebe6 100644 --- a/apps/ops/src/pages/SupplierInvoicesPage.vue +++ b/apps/ops/src/pages/SupplierInvoicesPage.vue @@ -19,11 +19,8 @@
-
- - - {{ filtered.length }} -
+
@@ -91,6 +88,7 @@ import { ref, computed, onMounted, watch } from 'vue' import { useQuasar } from 'quasar' import { HUB_URL } from 'src/config/hub' +import DynamicFilter from 'src/components/shared/DynamicFilter.vue' const $q = useQuasar() const list = ref([]) @@ -98,7 +96,9 @@ const loading = ref(false) const polling = ref(false) const creating = ref(false) const selected = ref(null) -const filter = ref('open') +// Filtre dynamique (client) : recherche fournisseur/n°/expéditeur + chips statut + presets. +const filterState = ref({ search: '', chips: { statut: 'open' } }) +const chipGroups = [{ key: 'statut', label: 'Statut', icon: 'label', options: [{ value: 'open', label: 'À traiter' }, { value: 'Created', label: 'Créées' }, { value: 'Ignored', label: 'Ignorées' }] }] const invoiceTo = ref('factures@targointernet.com') const erpBase = ref('https://erp.gigafibre.ca') const imgError = ref(false) @@ -106,9 +106,11 @@ const imgError = ref(false) watch(selected, () => { imgError.value = false }) const filtered = computed(() => { - if (filter.value === 'all') return list.value - if (filter.value === 'open') return list.value.filter(r => r.status === 'New' || r.status === 'Error') - return list.value.filter(r => r.status === filter.value) + const st = filterState.value.chips.statut || 'all' + let arr = st === 'all' ? list.value : (st === 'open' ? list.value.filter(r => r.status === 'New' || r.status === 'Error') : list.value.filter(r => r.status === st)) + const q = (filterState.value.search || '').toLowerCase().trim() + if (q) arr = arr.filter(r => (String(r.vendor || '') + ' ' + String(r.invoice_number || '') + ' ' + String(r.email_from || '')).toLowerCase().includes(q)) + return arr }) function fmtMoney (v, cur) { if (v == null || v === '') return '—'; return Number(v).toLocaleString('fr-CA', { style: 'currency', currency: cur || 'CAD' }) }