1+ <template lang="pug">
2+ .q-pa-sm ( @keydown.enter ="addFilter" )
3+ .row.q-gutter-sm.items-center
4+ .col-1
5+ q-toggle( v-model ="inclus" : label= "inclus ? 'Inclus' : 'Exclus'" )
6+ .col-1
7+ q-select( :options ="fieldTypes" label ="Type de champ" v-model ="fieldType" )
8+ .col-2
9+ q-select( :options ="fields" label ="Champs" v-model ="field" )
10+ .col-1
11+ q-select( :options ="comparatorTypes" label ="Comparateurs" v-model ="comparator" )
12+ template( v-slot:selected-item ="scope" )
13+ q-icon( :name ="scope.opt.icon" size ="xs" )
14+
15+ template( v-slot:option ="scope" )
16+ q-item( v-bind ="scope.itemProps" )
17+ q-item-section( avatar )
18+ q-icon( :name ="scope.opt.icon" )
19+ q-item-section
20+ q-item-label
21+ span {{ scope.opt.label }}
22+
23+ .col-2
24+ q-input( v-model ="search" label ="Rechercher" )
25+ .col-2
26+ q-btn( flat icon ="mdi-plus" color ="primary" @click ="addFilter" )
27+ q-tooltip.text-body2 ( transition-show ="scale" transition-hide ="scale" ) Ajouter
28+
29+ //Filters chips
30+ .row.q-gutter-sm.items-center.q-mt-sm
31+ q-chip(
32+ v-for ="filter in filterArray" : key= "filter.field"
33+ removable @remove ="removeFilter(filter)"
34+ ) {{ filter.label }} {{ filter.comparator }} {{ filter.search }}
35+ </template >
36+
37+ <script lang="ts" setup>
38+ import { ref } from ' vue'
39+ import type { PropType } from ' vue'
40+ import { useRouter , useRoute } from ' nuxt/app'
41+
42+ type Filter = {
43+ field: string
44+ comparator: string
45+ search: string
46+ }
47+
48+ type Field = {
49+ name: string
50+ label: string
51+ }
52+
53+ type Comparator = {
54+ label: string
55+ value: string
56+ icon: string
57+ }
58+
59+ const props = defineProps ({
60+ fields: {
61+ type: Array as PropType <Field []>,
62+ required: true
63+ }
64+ })
65+
66+ const router = useRouter ()
67+ const route = useRoute ()
68+
69+ const inclus = ref (true )
70+ const fieldType = ref (' ' )
71+ let field = ref <Field >()
72+ let comparator = ref <Comparator >()
73+ const search = ref (' ' )
74+
75+ const filters = ref <Filter []>([])
76+
77+ const fieldTypes = ref ([
78+ { label: ' Texte' , value: ' text' },
79+ { label: ' Nombre' , value: ' number' },
80+ { label: ' Date' , value: ' date' },
81+ { label: ' Heure' , value: ' time' },
82+ { label: ' Date et heure' , value: ' datetime' },
83+ { label: ' Liste' , value: ' list' },
84+ { label: ' Liste de valeurs' , value: ' listOfValues' },
85+ { label: ' Liste de valeurs multiples' , value: ' listOfValuesMultiple' },
86+ ])
87+
88+ const comparatorTypes = ref <Comparator []>([
89+ { label: ' Egal' , value: ' =' , icon: ' mdi-equal' },
90+ { label: ' Différent' , value: ' !=' , icon: ' mdi-exclamation' },
91+ { label: ' Est supérieur à' , value: ' >' , icon: ' mdi-greater-than' },
92+ { label: ' Est supérieur ou égal à' , value: ' >=' , icon: ' mdi-greater-than-or-equal' },
93+ { label: ' Est inférieur à' , value: ' <' , icon: ' mdi-less-than' },
94+ { label: ' Est inférieur ou égal à' , value: ' <=' , icon: ' mdi-less-than-or-equal' },
95+ { label: ' Est entre' , value: ' between' , icon: ' mdi-arrow-expand-horizontal' },
96+ ])
97+
98+ const addFilter = () => {
99+ if (
100+ ! field .value ||
101+ ! comparator .value ||
102+ ! search .value
103+ ) return
104+
105+ const object = {
106+ field: field .value .name ,
107+ comparator: comparator .value .value ,
108+ search: search .value
109+ }
110+ const key = ` filter[${object .comparator }${object .field }] `
111+ const value = object .search
112+ const query = {
113+ ... route .query ,
114+ }
115+ query [key ] = value
116+ router .push ({
117+ query
118+ })
119+ }
120+
121+ const removeFilter = (filter : Filter ) => {
122+ const key = ` filter[${filter .comparator }${filter .field }] `
123+ const query = {
124+ ... route .query ,
125+ }
126+ delete query [key ]
127+ router .push ({
128+ query
129+ })
130+ }
131+
132+ const getLabelByName = (name : string ) => {
133+ const field = props .fields .find (field => field .name === name )
134+ if (! field ) return
135+ return field .label
136+ }
137+
138+
139+ const exctractComparator = (key : string ): {
140+ comparator: string
141+ field: string
142+ } | null => {
143+ const match = key .match (/ ^ (\= | \? | \# | \! | \> | \< | \^ | \@ )+ / )
144+ if (! match ) return
145+ const comparator = match [0 ]
146+ const field = key .replace (comparator , ' ' )
147+ return {
148+ comparator ,
149+ field
150+ }
151+ }
152+
153+ const filterArray = computed (() => {
154+ const queries = { ... route .query }
155+ const filters: Record <string , string > = {};
156+
157+ // Iterate through the keys and values in the input object
158+ for (const key in queries ) {
159+ if (queries .hasOwnProperty (key ) && key .includes (" filter" )) {
160+
161+ // Extract the key without the "filter[" and "]" parts
162+ const filteredKey = key .replace (" filter[" , " " ).replace (" ]" , " " );
163+ const exctract = exctractComparator (filteredKey )
164+ if (! exctract ) continue
165+ const { comparator, field } = exctract
166+ // Assign the value to the extracted key in the filter array
167+ filters [field ] = {
168+ label: getLabelByName (field ),
169+ field ,
170+ comparator ,
171+ search: queries [key ]
172+ };
173+ }
174+ }
175+ return filters
176+ })
177+ </script >
0 commit comments