From 3d52ae32c4b99bf6e92fbbb2a507025f51a56f5f Mon Sep 17 00:00:00 2001 From: louispaulb Date: Sat, 4 Jul 2026 19:13:37 -0400 Subject: [PATCH] =?UTF-8?q?feat(ui):=20T5=20audit=20=E2=80=94=20composant?= =?UTF-8?q?=20DynamicFilter=20r=C3=A9utilisable=20+=20int=C3=A9gr=C3=A9=20?= =?UTF-8?q?sur=20Clients?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DynamicFilter.vue : recherche + groupes de chips (tag/statut/…) + PRESETS sauvegardés par utilisateur (useUserPrefs, clé presetKey) ; contrôleur d'état ({search,chips}) émis → le parent applique (client OU serveur). - ClientsPage : remplace search+toggle par ; AJOUTE chips Statut/Groupe/Territoire (avant : statut seul) → pilotent la requête serveur ; presets 'filter.clients'. - fix(erp): countDocs comptait FAUX avec or_filters (get_count ignore or_filters → 0 pendant une recherche) → compte via get_list quand or_filters présent. Vérifié : « bourdon » 0→33. Vérifié préview : chips (Actifs 9008), recherche (bourdon 33 = lignes), menu presets. Build vert, leak 0. Réutilisable : Tickets/Network/Évaluations/Boîte ensuite. Co-Authored-By: Claude Opus 4.8 --- apps/ops/src/api/erp.js | 23 +++-- .../src/components/shared/DynamicFilter.vue | 98 +++++++++++++++++++ apps/ops/src/pages/ClientsPage.vue | 70 +++++-------- 3 files changed, 142 insertions(+), 49 deletions(-) create mode 100644 apps/ops/src/components/shared/DynamicFilter.vue diff --git a/apps/ops/src/api/erp.js b/apps/ops/src/api/erp.js index 44003ea..0b30e76 100644 --- a/apps/ops/src/api/erp.js +++ b/apps/ops/src/api/erp.js @@ -83,13 +83,24 @@ export async function deleteDoc (doctype, name) { return true } -// Count documents +// Count documents. ⚠️ frappe.client.get_count IGNORE or_filters (recherche OR) → il renverrait un compte +// faux (souvent 0) dès qu'on cherche. Quand or_filters est présent, on compte via get_list (fields=name, +// sans limite) — les jeux de recherche sont bornés par le terme tapé. Sinon (chips seuls) : get_count rapide. export async function countDocs (doctype, filters = {}, or_filters) { - const params = new URLSearchParams({ - doctype, - filters: JSON.stringify(filters), - }) - if (or_filters) params.set('or_filters', JSON.stringify(or_filters)) + if (or_filters && or_filters.length) { + const p = new URLSearchParams({ + doctype, + filters: JSON.stringify(filters), + or_filters: JSON.stringify(or_filters), + fields: JSON.stringify(['name']), + limit_page_length: '0', + }) + const r = await authFetch(BASE_URL + '/api/method/frappe.client.get_list?' + p) + if (!r.ok) return 0 + const d = await r.json() + return ((d.message || d.data) || []).length + } + const params = new URLSearchParams({ doctype, filters: JSON.stringify(filters) }) const res = await authFetch(BASE_URL + '/api/method/frappe.client.get_count?' + params) if (!res.ok) return 0 const data = await res.json() diff --git a/apps/ops/src/components/shared/DynamicFilter.vue b/apps/ops/src/components/shared/DynamicFilter.vue new file mode 100644 index 0000000..7d309e8 --- /dev/null +++ b/apps/ops/src/components/shared/DynamicFilter.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/apps/ops/src/pages/ClientsPage.vue b/apps/ops/src/pages/ClientsPage.vue index 9397606..3b6feec 100644 --- a/apps/ops/src/pages/ClientsPage.vue +++ b/apps/ops/src/pages/ClientsPage.vue @@ -1,32 +1,9 @@