1+ <template lang="pug">
2+ .row.q-gutter-sm.items-center.q-mt-sm
3+ //- .col.col-md-2
4+ //- q-select(:options="fieldTypes" label="Type de champ" v-model="fieldType" clearable @update:model-value="clearFields(['field', 'comparator'])")
5+ .col.col-md-2
6+ q-select( :options ="fields" label ="Champs" v-model ="field" clearable @update:model-value ="onFieldChange($event)" )
7+ .col.col-md-2
8+ q-select( :options ="comparatorFilteredByType" label ="Comparateurs" v-model ="comparator" clearable @update:model-value ="clearFields([])" : disable= "isFieldDisabled.comparator" )
9+ template( v-slot:selected-item ="scope" )
10+ q-icon( :name ="scope.opt.icon" size ="xs" )
11+ template( v-slot:option ="scope" )
12+ q-item( v-bind ="scope.itemProps" )
13+ q-item-section( avatar )
14+ q-icon( :name ="scope.opt.icon" )
15+ q-item-section
16+ q-item-label
17+ span {{ scope.opt.label }}
18+
19+ .col-12.col-md-2 ( v-show ="!comparator?.multiplefields" )
20+ q-input( v-model ="search" label ="Rechercher" clearable :type ="searchInputType" : disable= "isFieldDisabled.search" : prefix= "comparator?.prefix" : suffix= "comparator?.suffix" )
21+ .col-6.col-md-2 ( v-show ="comparator?.multiplefields" )
22+ q-input( v-model ="searchMin" label ="Min" clearable :type ="searchInputType" : disable= "isFieldDisabled.search" )
23+ .col-6.col-md-2 ( v-show ="comparator?.multiplefields" )
24+ q-input( v-model ="searchMax" label ="Max" clearable :type ="searchInputType" : disable= "isFieldDisabled.search" )
25+ .col-12.col-md-1
26+ q-btn( color ="primary" @click ="addFilter" : disable= "isFieldDisabled.addButton" ) Ajouter
27+ q-space
28+ .col-12.col-md-2
29+ tk-SearchfiltersRightSelect( ref ="rightSelect" )
30+ </template >
31+
32+ <script lang="ts" setup>
33+ import { ref , computed , inject } from ' vue'
34+ import { useRouter , useRoute } from ' nuxt/app'
35+ import { useDayjs } from ' #imports' ;
36+ import type { Filter , Field , Comparator , SearchFilter } from ' ~/types'
37+ const dayjs = useDayjs ()
38+
39+ const fields = inject (' fieldsList' , ref <Field []>([]))
40+
41+ const router = useRouter ()
42+ const route = useRoute ()
43+ const rightSelect = ref (null )
44+ const inclus = ref (true )
45+ const fieldType = ref <string >()
46+
47+ let field = ref <Field >()
48+ let comparator = ref <Comparator >()
49+ const search = ref (' ' )
50+ const searchMin = ref (' ' )
51+ const searchMax = ref (' ' )
52+
53+
54+ const filters = ref <Filter []>([])
55+
56+ const fieldTypes = ref <{
57+ label: string
58+ value: string
59+ }[]>([
60+ { label: ' Texte' , value: ' text' },
61+ { label: ' Nombre' , value: ' number' },
62+ { label: ' Date' , value: ' date' },
63+ ])
64+
65+ const comparatorTypes = ref <Comparator []>([
66+ { label: ' Egal à' , querySign: ' =' , value: ' =' , icon: ' mdi-equal' , type: [' number' ], multiplefields: false , prefix: ' ' , suffix: ' ' },
67+ { label: ' Différent' , querySign: ' !=' , value: ' !=' , icon: ' mdi-exclamation' , type: [' number' ], multiplefields: false , prefix: ' ' , suffix: ' ' },
68+ { label: ' Supérieur à' , querySign: ' >' , value: ' >' , icon: ' mdi-greater-than' , type: [' number' , ' date' ], multiplefields: false , prefix: ' ' , suffix: ' ' },
69+ { label: ' Supérieur ou égal à' , querySign: ' >=' , value: ' >=' , icon: ' mdi-greater-than-or-equal' , type: [' number' , ' date' ], multiplefields: false , prefix: ' ' , suffix: ' ' },
70+ { label: ' Inférieur à' , querySign: ' <' , value: ' <' , icon: ' mdi-less-than' , type: [' number' , ' date' ], multiplefields: false , prefix: ' ' , suffix: ' ' },
71+ { label: ' Inférieur ou égal à' , querySign: ' <=' , value: ' <=' , icon: ' mdi-less-than-or-equal' , type: [' number' , ' date' ], multiplefields: false , prefix: ' ' , suffix: ' ' },
72+ { label: ' entre' , querySign: ' <<' , value: ' between' , icon: ' mdi-arrow-expand-horizontal' , type: [' number' , ' date' ], multiplefields: true , prefix: ' ' , suffix: ' ' },
73+ { label: ' Contiens' , querySign: ' ^' , value: ' ^' , icon: ' mdi-apple-keyboard-control' , type: [' text' ], multiplefields: false , prefix: ' /' , suffix: ' /' },
74+ { label: ' Commence par' , querySign: ' ^' , value: ' /^' , icon: ' mdi-apple-keyboard-control' , type: [' text' ], multiplefields: false , prefix: ' /^' , suffix: ' /' },
75+ { label: ' Fini par' , querySign: ' ^' , value: ' $/' , icon: ' mdi-apple-keyboard-control' , type: [' text' ], multiplefields: false , prefix: ' /' , suffix: ' $/' },
76+ { label: ' Egal à' , querySign: ' @' , value: ' @' , icon: ' mdi-apple-keyboard-control' , type: [], multiplefields: true , prefix: ' ' , suffix: ' ' },
77+
78+ ])
79+
80+ const onFieldChange = (value : Field ) => {
81+ value === null ? fieldType .value = ' ' : fieldType .value = value .type
82+ clearFields ([' comparator' ])
83+ }
84+
85+ const clearFields = (fields : string []) => {
86+ if (fields .includes (' field' )) field = ref ()
87+ if (fields .includes (' comparator' )) comparator = ref ()
88+ search .value = ' '
89+ searchMin .value = ' '
90+ searchMax .value = ' '
91+ }
92+
93+ const addFilter = async () => {
94+ const searchFilter = getSearchFilter .value
95+ if (! searchFilter ) return
96+ if (searchFilter .comparator .multiplefields ) {
97+ for (const { key, value } of parseMultipleFilter (searchFilter )) {
98+ await pushQuery (key , value )
99+ }
100+ } else {
101+ const { key, value } = parseSimpleFilter (searchFilter )
102+ await pushQuery (key , value )
103+ }
104+ }
105+
106+ const parseSimpleFilter = (searchFilter : SearchFilter ) => {
107+ if (searchFilter .field .type === ' date' ) {
108+ if (searchFilter .comparator .querySign === ' <' || searchFilter .comparator .querySign === ' >=' ) searchFilter .search = dayjs (searchFilter .search ).startOf (' day' ).toISOString ()
109+ if (searchFilter .comparator .querySign === ' >' || searchFilter .comparator .querySign === ' <=' ) searchFilter .search = dayjs (searchFilter .search ).endOf (' day' ).toISOString ()
110+ }
111+ return {
112+ key: ` filters[${searchFilter .comparator .querySign }${searchFilter .field .name }] ` ,
113+ value: ` ${searchFilter .comparator .prefix }${searchFilter .search }${searchFilter .comparator .suffix } `
114+ }
115+ }
116+
117+ const parseMultipleFilter = (searchFilter : SearchFilter ) => {
118+ if (searchFilter .field .type === ' date' ) {
119+ searchFilter .searchMin = dayjs (searchFilter .searchMin ).startOf (' day' ).toISOString ()
120+ searchFilter .searchMax = dayjs (searchFilter .searchMax ).endOf (' day' ).toISOString ()
121+ }
122+ const min = {
123+ key: ` filters[>=${searchFilter .field .name }] ` ,
124+ value: ` ${searchFilter .comparator .prefix }${searchFilter .searchMin }${searchFilter .comparator .suffix } `
125+ }
126+ const max = {
127+ key: ` filters[<=${searchFilter .field .name }] ` ,
128+ value: ` ${searchFilter .comparator .prefix }${searchFilter .searchMax }${searchFilter .comparator .suffix } `
129+ }
130+ return [min , max ]
131+ }
132+
133+ const pushQuery = async (key : string , value : string ) => {
134+ const query = {
135+ ... route .query ,
136+ }
137+ query [key ] = value
138+ await router .push ({
139+ query
140+ })
141+ }
142+
143+ const getSearchFilter = computed (() => {
144+ if (field .value === undefined || field .value === null ) return null
145+ if (comparator .value === undefined || comparator .value === null ) return null
146+ return {
147+ field: field ! .value ,
148+ comparator: comparator ! .value ,
149+ search: search .value ,
150+ searchMin: searchMin .value ,
151+ searchMax: searchMax .value
152+ }
153+ })
154+
155+ const searchInputType = computed (() => {
156+ if (fieldType .value === undefined || fieldType .value === null ) return ' text'
157+ return fieldType .value
158+ })
159+
160+ const fieldsFilteredByType = computed (() => {
161+ if (fieldType .value === undefined || fieldType .value === null ) return []
162+ return fields .value .filter ((field ) => {
163+ return field .type === fieldType .value
164+ })
165+ })
166+
167+ const comparatorFilteredByType = computed (() => {
168+ if (fieldType .value === undefined || fieldType .value === null ) return []
169+ return comparatorTypes .value .filter ((comparator ) => {
170+ return comparator .type .includes (fieldType .value ! )
171+ })
172+ })
173+
174+ const isFieldDisabled = computed (() => {
175+ return {
176+ field: false ,
177+ comparator: ! field .value ,
178+ search: ! field .value || ! comparator .value ,
179+ addButton: ! field .value || ! comparator .value || ! search .value ,
180+ }
181+ })
182+
183+ defineExpose ({
184+ comparatorTypes ,
185+ rightSelect ,
186+ })
187+ </script >
0 commit comments