88 :items-per-page =" itemsPerPage"
99 :footer-props =" footerProps"
1010 >
11+ <template v-slot :top >
12+ <v-card-actions class =" px-2 py-2" >
13+ <v-menu
14+ :close-on-content-click =" false"
15+ min-width =" 500"
16+ max-width =" 500"
17+ offset-y
18+ >
19+ <template v-slot :activator =" { on , attrs } " >
20+ <v-btn
21+ icon
22+ v-bind =" attrs"
23+ v-on =" on"
24+ class =" pa-0 ma-0"
25+ >
26+ <v-icon >mdi-filter-variant-plus</v-icon >
27+ </v-btn >
28+ </template >
29+
30+ <v-card >
31+ <v-card-text >
32+ <v-autocomplete
33+ v-model =" selectedCategories"
34+ :items =" categories"
35+ label =" Categorías"
36+ chips
37+ deletable-chips
38+ clearable
39+ multiple
40+ small-chips
41+ prepend-icon =" mdi-tag"
42+ ></v-autocomplete >
43+ <v-autocomplete
44+ v-model =" selectedStates"
45+ :items =" states"
46+ label =" Estados"
47+ chips
48+ deletable-chips
49+ clearable
50+ multiple
51+ small-chips
52+ prepend-icon =" mdi-state-machine"
53+ ></v-autocomplete >
54+ </v-card-text >
55+ </v-card >
56+ </v-menu >
57+ <span class =" mx-4" >
58+ <v-chip small class =" mr-2 my-1" :color =" activeFilter ? 'primary lighten-3' : ''" @click =" clickActiveFilter" >
59+ <v-icon small left v-if =" activeFilter" >mdi-check</v-icon >
60+ <v-icon small left v-else >mdi-minus</v-icon >
61+ Activos
62+ </v-chip >
63+ <v-chip small class =" mr-2 my-1" :color =" blockedFilter ? 'primary lighten-3' : ''" @click =" clickBlockedFilter" >
64+ <v-icon small left v-if =" blockedFilter" >mdi-check</v-icon >
65+ <v-icon small left v-else >mdi-minus</v-icon >
66+ Bloqueados
67+ </v-chip >
68+ <v-chip small class =" mr-2 my-1" color =" amber lighten-3" v-for =" category in selectedCategories" :key =" category" >
69+ <v-icon small left >mdi-check</v-icon >
70+ {{ category }}
71+ </v-chip >
72+ <v-chip small class =" mr-2 my-1" color =" pink lighten-3" v-for =" state in states.filter(s => selectedStates.includes(s.value)).map(f => f.text)" :key =" state" >
73+ <v-icon small left >mdi-check</v-icon >
74+ {{ state }}
75+ </v-chip >
76+ </span >
77+ <v-spacer ></v-spacer >
78+ <v-radio-group v-model =" operator" row dense hide-details class =" pa-0 ma-0" >
79+ <v-radio label =" OR" value =" or" class =" pa-0 my-0 mx-2" ></v-radio >
80+ <v-radio label =" AND" value =" and" class =" pa-0 ma-0 mx-2" ></v-radio >
81+ </v-radio-group >
82+ </v-card-actions >
83+ <v-divider ></v-divider >
84+ </template >
85+
86+ <template v-slot :item .blocked =" { item } " >
87+ <div >
88+ <v-tooltip bottom v-if =" item.isBlocked" >
89+ <template v-slot :activator =" { on , attrs } " >
90+ <v-icon color =" red" dark v-bind =" attrs" v-on =" on" >mdi-cancel</v-icon >
91+ </template >
92+ <span >Usuario bloqueado</span >
93+ </v-tooltip >
94+ <v-tooltip bottom v-else >
95+ <template v-slot :activator =" { on , attrs } " >
96+ <v-icon color =" green" dark v-bind =" attrs" v-on =" on" >mdi-check-circle-outline</v-icon >
97+ </template >
98+ <span >Activo</span >
99+ </v-tooltip >
100+ </div >
101+ </template >
102+
11103 <template v-slot :item .owner =" { item } " >
12104 <a href =" #" @click.prevent =" goToUserDetails(item.owner.dbId)" >{{ item.owner.email }}</a >
13105 </template >
37129</template >
38130
39131<script >
40- import { ALL_PROJECTS_QUERY } from ' @/graphql/graphql'
132+ import { ALL_PROJECTS_QUERY , CATEGORIES_QUERY } from ' @/graphql/graphql'
41133
42134const DEFAULT_ROWS_PER_PAGE = 10
43135const PROJECT_SORT_ENUM = {
@@ -64,14 +156,36 @@ export default {
64156 options: {},
65157 headers: [
66158 { text: ' ID' , align: ' start' , sortable: true , value: ' dbId' },
159+ { text: ' Activo' , sortable: true , value: ' blocked' },
67160 { text: ' Nombre' , sortable: true , value: ' name' },
68161 { text: ' Categoría' , sortable: true , value: ' category.name' },
69162 { text: ' Estado' , sortable: true , value: ' currentState' },
70163 { text: ' Recaudado' , sortable: false , value: ' amountCollected' },
71164 { text: ' Objetivo' , sortable: true , value: ' goal' },
72165 { text: ' Emprendedor' , sortable: true , value: ' owner' },
73166 { text: ' Detalles' , align: ' end' , sortable: false , value: ' actions' }
74- ]
167+ ],
168+ blockedFilter: false ,
169+ activeFilter: false ,
170+ selectedCategories: [],
171+ selectedStates: [],
172+ states: [{
173+ text: ' Created' ,
174+ value: ' CREATED'
175+ }, {
176+ text: ' Funding' ,
177+ value: ' FUNDING'
178+ }, {
179+ text: ' In Progress' ,
180+ value: ' IN_PROGRESS'
181+ }, {
182+ text: ' Complete' ,
183+ value: ' COMPLETE'
184+ }, {
185+ text: ' Canceled' ,
186+ value: ' CANCELED'
187+ }],
188+ operator: ' or'
75189 }
76190 },
77191
@@ -80,6 +194,10 @@ export default {
80194 return this .allProjects ? .edges ? .map ((e ) => e .node ) || []
81195 },
82196
197+ categories () {
198+ return this .allCategories ? .edges ? .map ((e ) => e .node ? .name ) || []
199+ },
200+
83201 totalCount () {
84202 return this .allProjects ? .totalCount || this .projects ? .length || 0
85203 },
@@ -108,6 +226,16 @@ export default {
108226 ' disable-items-per-page' : this .loading ,
109227 ' disable-pagination' : this .loading
110228 }
229+ },
230+
231+ filters () {
232+ return {
233+ [this .operator ]: [
234+ { [this .operator ]: [{ isBlocked: (this .blockedFilter === this .activeFilter ) ? undefined : this .blockedFilter || ! this .activeFilter }] },
235+ { [this .operator ]: [{ categoryNameIn: (this .selectedCategories .length ) ? this .selectedCategories : undefined }] },
236+ { [this .operator ]: [{ currentStateIn: (this .selectedStates .length ) ? this .selectedStates : undefined }] }
237+ ]
238+ }
111239 }
112240 },
113241
@@ -118,39 +246,59 @@ export default {
118246
119247 goToProjectDetails (id ) {
120248 this .$router .push ({ name: ' ProjectDetail' , params: { id: id } })
249+ },
250+
251+ clickActiveFilter () {
252+ this .blockedFilter = false
253+ this .activeFilter = ! this .activeFilter
254+ },
255+
256+ clickBlockedFilter () {
257+ this .activeFilter = false
258+ this .blockedFilter = ! this .blockedFilter
259+ },
260+
261+ paginate (val , oldVal ) {
262+ const isPreviousPage = val? .page < oldVal? .page
263+ const isNextPage = val? .page > oldVal? .page
264+
265+ let first = this .options .itemsPerPage
266+ let last
267+ let endCursor
268+ let startCursor
269+
270+ if (isNextPage) {
271+ endCursor = this .endCursor
272+ }
273+
274+ if (isPreviousPage) {
275+ first = undefined
276+ last = this .options .itemsPerPage
277+ startCursor = [this .startCursor ]
278+ }
279+
280+ this .$apollo .queries .allProjects .refetch ({
281+ first: first,
282+ last: last,
283+ endCursor: endCursor,
284+ startCursor: startCursor,
285+ sort: this .sorting ,
286+ filters: this .filters
287+ })
121288 }
122289 },
123290
124291 watch: {
125292 options: {
126293 handler (val , oldVal ) {
127- const isPreviousPage = val? .page < oldVal? .page
128- const isNextPage = val? .page > oldVal? .page
129-
130- let first = this .options .itemsPerPage
131- let last
132- let endCursor
133- let startCursor
134-
135- if (isNextPage) {
136- endCursor = this .endCursor
137- }
138-
139- if (isPreviousPage) {
140- first = undefined
141- last = this .options .itemsPerPage
142- startCursor = [this .startCursor ]
143- }
144-
145- this .$apollo .queries .allProjects .refetch ({
146- first: first,
147- last: last,
148- endCursor: endCursor,
149- startCursor: startCursor,
150- sort: this .sorting
151- })
294+ this .paginate (val, oldVal)
152295 },
153296 deep: true
297+ },
298+ filters: {
299+ handler (val , oldVal ) {
300+ this .paginate (val, oldVal)
301+ }
154302 }
155303 },
156304
@@ -162,7 +310,16 @@ export default {
162310 first: this .itemsPerPage
163311 }
164312 }
313+ },
314+ allCategories: {
315+ query: CATEGORIES_QUERY
165316 }
166317 }
167318}
168319< / script>
320+
321+ < style>
322+ .v - radio > .v - label {
323+ font- size: small ! important;
324+ }
325+ < / style>
0 commit comments