feat(ui): T5 — DynamicFilter sur Tickets (recherche + chips statut/type/priorité + presets)
Remplace search + 3 q-select par <DynamicFilter> ('filter.tickets') ; chipGroups computed (types dynamiques) ;
statut défaut = not_closed préservé ; mappe l'état → refs existantes (search/statusFilter/typeFilter/priorityFilter) → resetAndLoad débouncé.
La PORTÉE « Mes tickets / Mes départements / Tous » reste un toggle séparé (logique de scope/pagination distincte). Compte redondant retiré.
Vérifié préview : 3 groupes, « Non fermés » actif par défaut, chip Urgent 542→3, toggle portée conservé. Build vert, leak 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
3d52ae32c4
commit
4d940eefc4
|
|
@ -2,30 +2,12 @@
|
|||
<q-page padding>
|
||||
<!-- Filters row -->
|
||||
<div class="row q-col-gutter-sm q-mb-md items-end">
|
||||
<div class="col-12 col-md-3">
|
||||
<div class="filter-label">Recherche</div>
|
||||
<q-input v-model="search" dense outlined placeholder="Sujet, client, #ticket..." class="ops-search"
|
||||
@keyup.enter="loadTickets" clearable @clear="loadTickets">
|
||||
<template #prepend><q-icon name="search" /></template>
|
||||
</q-input>
|
||||
<div class="col-12 col-md">
|
||||
<DynamicFilter v-model="filterState" search-placeholder="Sujet, client, #ticket…"
|
||||
:chip-groups="chipGroups" preset-key="filter.tickets" :filtered-count="total" @change="onFilterChange" />
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="filter-label">Statut</div>
|
||||
<q-select v-model="statusFilter" dense outlined emit-value map-options
|
||||
:options="statusOptions" @update:model-value="resetAndLoad" />
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="filter-label">Type / Departement</div>
|
||||
<q-select v-model="typeFilter" dense outlined emit-value map-options clearable
|
||||
:options="issueTypes" @update:model-value="resetAndLoad" placeholder="Tous" />
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="filter-label">Priorite</div>
|
||||
<q-select v-model="priorityFilter" dense outlined emit-value map-options clearable
|
||||
:options="priorityOptions" @update:model-value="resetAndLoad" placeholder="Toutes" />
|
||||
</div>
|
||||
<div class="col-6 col-md-2">
|
||||
<div class="filter-label">Mes tickets</div>
|
||||
<div class="filter-label">Portée</div>
|
||||
<q-btn-toggle v-model="ownerFilter" no-caps dense unelevated
|
||||
toggle-color="primary" color="grey-3" text-color="grey-8"
|
||||
:options="[
|
||||
|
|
@ -36,9 +18,6 @@
|
|||
@update:model-value="resetAndLoad"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="text-caption text-grey-6 q-mt-sm">{{ total.toLocaleString() }} tickets</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<FlowQuickButton flat dense icon="account_tree" label="Flows tickets"
|
||||
tooltip="Configurer les automatisations pour les tickets"
|
||||
|
|
@ -185,6 +164,7 @@ import { formatDate } from 'src/composables/useFormatters'
|
|||
import { ticketStatusClass as statusClass, priorityClass } from 'src/composables/useStatusClasses'
|
||||
import { useDetailModal } from 'src/composables/useDetailModal'
|
||||
import { statusOptions, priorityOptions, columns, buildFilters, getSortField } from 'src/config/ticket-config'
|
||||
import DynamicFilter from 'src/components/shared/DynamicFilter.vue'
|
||||
import { useSla, SLA_BADGE } from 'src/composables/useSla'
|
||||
import { useAuthStore } from 'src/stores/auth'
|
||||
import { HUB_URL } from 'src/config/hub' // pour résoudre « mes files » (queue-members) → issue_types de mes départements
|
||||
|
|
@ -206,6 +186,22 @@ const statusFilter = ref('not_closed') // défaut = NON FERMÉS → évite les v
|
|||
const typeFilter = ref(null)
|
||||
const priorityFilter = ref(null)
|
||||
const ownerFilter = ref('mine') // défaut « façon F » : on atterrit sur MES tickets assignés (priorisés), bascule « Tous » dispo
|
||||
// DynamicFilter (recherche + chips statut/type/priorité + presets) → mappe vers les refs existantes qui alimentent buildFilters.
|
||||
const filterState = ref({ search: '', chips: { statut: statusFilter.value } }) // statut défaut = not_closed
|
||||
const chipGroups = computed(() => [
|
||||
{ key: 'statut', label: 'Statut', icon: 'label', options: statusOptions.filter(o => o.value !== 'all') },
|
||||
{ key: 'type', label: 'Type', icon: 'category', options: issueTypes.value },
|
||||
{ key: 'priorite', label: 'Priorité', icon: 'priority_high', options: priorityOptions },
|
||||
])
|
||||
let filterTimer = null
|
||||
function onFilterChange (s) {
|
||||
search.value = s.search || ''
|
||||
statusFilter.value = s.chips.statut || 'all'
|
||||
typeFilter.value = s.chips.type || null
|
||||
priorityFilter.value = s.chips.priorite || null
|
||||
clearTimeout(filterTimer)
|
||||
filterTimer = setTimeout(() => resetAndLoad(), 300)
|
||||
}
|
||||
const tickets = ref([])
|
||||
// Tri « façon F » : dans les vues scopées (Mes tickets), RANGER par priorité (Urgent→Bas) côté client —
|
||||
// ERPNext+Postgres ne range pas une priorité Select dans l'ORDER BY, et l'ensemble scopé tient sur 1 page.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user