|
| 1 | +<template> |
| 2 | + <!-- eslint-disable max-len --> |
| 3 | + <section class="mb-4 sm:mb-16 lg:mb-32"> |
| 4 | + <div class="flex items-center justify-center md:justify-start w-full mb-4"> |
| 5 | + <h1 |
| 6 | + class="text-3xl sm:text-5xl my-4 inline-block text-center leading-none onboarding-sub-container-content-heading"> |
| 7 | + {{recommendations.length}}</h1> |
| 8 | + <DropdownDisplayChoiceHistory |
| 9 | + v-on:save-single-choice="saveSingleChoice" |
| 10 | + class="inline-block ml-4" |
| 11 | + v-bind:name="'history'" |
| 12 | + v-bind:starting-option="'People I viewed'" |
| 13 | + v-bind:options="['People I view', 'People I like', 'Who views me', 'Who likes me', 'Whom I block']"></DropdownDisplayChoiceHistory> |
| 14 | + </div> |
| 15 | + <div class="flex w-full items-stretch sm:items-center justify-center md:justify-start mb-12 relative"> |
| 16 | + <Sort |
| 17 | + v-bind:position="'left'" |
| 18 | + v-bind:startingOption="'Closest'" |
| 19 | + v-bind:options="['Closest', 'Furthest', 'Youngest', |
| 20 | + 'Oldest', 'Most popular', 'Least popular', 'Most common interests', 'Least common interests']" |
| 21 | + v-on:save-sort="saveSort"></Sort> |
| 22 | + <FilterSliderDropdown |
| 23 | + v-bind:min="recommendationsAnalysis.age.min" |
| 24 | + v-bind:max="recommendationsAnalysis.age.max" |
| 25 | + v-bind:name="'age'" |
| 26 | + v-on:save-filter="saveFilter"></FilterSliderDropdown> |
| 27 | + <FilterSliderDropdown |
| 28 | + v-bind:min="recommendationsAnalysis.distance.min" |
| 29 | + v-bind:max="recommendationsAnalysis.distance.max" |
| 30 | + v-bind:unit="'km'" |
| 31 | + v-bind:name="'distance'" |
| 32 | + v-on:save-filter="saveFilter"></FilterSliderDropdown> |
| 33 | + <FilterSliderDropdown |
| 34 | + v-bind:min="recommendationsAnalysis.popularity.min" |
| 35 | + v-bind:max="recommendationsAnalysis.popularity.max" |
| 36 | + v-bind:unit="'pts'" |
| 37 | + v-bind:name="'popularity'" |
| 38 | + v-on:save-filter="saveFilter"></FilterSliderDropdown> |
| 39 | + <MultipleFiltersDropdown |
| 40 | + v-bind:position="'right'" |
| 41 | + v-bind:options="recommendationsAnalysis.interests" |
| 42 | + v-bind:name="'interests'" |
| 43 | + v-on:save-filter-multiple="saveFilterMultiple"></MultipleFiltersDropdown> |
| 44 | + </div> |
| 45 | + <div ref="recommendationCards" class="grid grid-cols-1 md:grid-cols-2 gap-2"> |
| 46 | + <RecommendationCard |
| 47 | + v-for="(recommendation, index) in recommendations" :key="index" |
| 48 | + v-bind:recommendation="recommendation"></RecommendationCard> |
| 49 | + </div> |
| 50 | + </section> |
| 51 | +</template> |
| 52 | + |
| 53 | +<script> |
| 54 | +/* eslint-disable */ |
| 55 | +import Sort from '@/components/shared/Sort.vue'; |
| 56 | +import FilterSliderDropdown from '@/components/shared/FilterSliderDropdown.vue'; |
| 57 | +import RecommendationCard from '@/components/app/recommendations/RecommendationCard.vue'; |
| 58 | +import MultipleFiltersDropdown from '@/components/shared/MultipleFiltersDropdown.vue'; |
| 59 | +import DropdownDisplayChoiceHistory from '@/components/shared/DropdownDisplayChoiceHistory.vue'; |
| 60 | +
|
| 61 | +export default { |
| 62 | + props: ['title', 'recommendationsReceived', 'recommendationsAnalysis'], |
| 63 | + components: { |
| 64 | + Sort, |
| 65 | + RecommendationCard, |
| 66 | + FilterSliderDropdown, |
| 67 | + MultipleFiltersDropdown, |
| 68 | + DropdownDisplayChoiceHistory, |
| 69 | + }, |
| 70 | + data: () => ({ |
| 71 | + recommendations: [], |
| 72 | + recommendationsBackup: [], |
| 73 | + sorting: 'Closest', |
| 74 | + filters: { |
| 75 | + age: { |
| 76 | + min: null, |
| 77 | + max: null, |
| 78 | + }, |
| 79 | + distance: { |
| 80 | + min: null, |
| 81 | + max: null, |
| 82 | + }, |
| 83 | + popularity: { |
| 84 | + min: null, |
| 85 | + max: null, |
| 86 | + }, |
| 87 | + interests: [], |
| 88 | + }, |
| 89 | + }), |
| 90 | + methods: { |
| 91 | + saveSort(...args) { |
| 92 | + const [by] = args; |
| 93 | + this.sorting = by; |
| 94 | + }, |
| 95 | + saveFilter(...range) { |
| 96 | + const [name, min, max] = range; |
| 97 | + this.filters[name].min = min; |
| 98 | + this.filters[name].max = max; |
| 99 | + }, |
| 100 | + saveFilterMultiple(...multiple) { |
| 101 | + const [name, filters] = multiple; |
| 102 | + this.filters[name] = filters; |
| 103 | + }, |
| 104 | + sort(recommendations, by) { |
| 105 | + if (by === 'Closest') { |
| 106 | + recommendations.sort((a, b) => a.distance - b.distance); |
| 107 | + } else if (by === 'Furthest') { |
| 108 | + recommendations.sort((a, b) => b.distance - a.distance); |
| 109 | + } else if (by === 'Youngest') { |
| 110 | + recommendations.sort((a, b) => a.age - b.age); |
| 111 | + } else if (by === 'Oldest') { |
| 112 | + recommendations.sort((a, b) => b.age - a.age); |
| 113 | + } else if (by === 'Most popular') { |
| 114 | + recommendations.sort((a, b) => b.heat_score - a.heat_score); |
| 115 | + } else if (by === 'Least popular') { |
| 116 | + recommendations.sort((a, b) => a.heat_score - b.heat_score); |
| 117 | + } else if (by === 'Most common interests') { |
| 118 | + recommendations.sort((a, b) => b.common_tags.length - a.common_tags.length); |
| 119 | + } else if (by === 'Least common interests') { |
| 120 | + recommendations.sort((a, b) => a.common_tags.length - b.common_tags.length); |
| 121 | + } |
| 122 | + }, |
| 123 | + filter(recommendations) { |
| 124 | + let i = recommendations.length; |
| 125 | + while (i--) { |
| 126 | + if (!this.meetsFilters(recommendations[i])) { |
| 127 | + recommendations.splice(i, 1); |
| 128 | + } |
| 129 | + } |
| 130 | + return recommendations; |
| 131 | + }, |
| 132 | + meetsFilters(recommendation) { |
| 133 | + return this.meetsAge(recommendation) |
| 134 | + && this.meetsPopularity(recommendation) |
| 135 | + && this.meetsDistance(recommendation) |
| 136 | + && this.meetsInterests(recommendation); |
| 137 | + }, |
| 138 | + meetsAge(recommendation) { |
| 139 | + return recommendation.age >= this.filters.age.min |
| 140 | + && recommendation.age <= this.filters.age.max; |
| 141 | + }, |
| 142 | + meetsPopularity(recommendation) { |
| 143 | + return recommendation.heat_score >= this.filters.popularity.min |
| 144 | + && recommendation.heat_score <= this.filters.popularity.max; |
| 145 | + }, |
| 146 | + meetsDistance(recommendation) { |
| 147 | + return recommendation.distance >= this.filters.distance.min |
| 148 | + && recommendation.distance <= this.filters.distance.max; |
| 149 | + }, |
| 150 | + meetsInterests(recommendation) { |
| 151 | + const recommendationInterests = recommendation.interests; |
| 152 | + const filterInterests = this.filters.interests; |
| 153 | + for (let i = 0; i < filterInterests.length; i += 1) { |
| 154 | + if (recommendationInterests.indexOf(filterInterests[i]) === -1) { |
| 155 | + return false; |
| 156 | + } |
| 157 | + } |
| 158 | + return true; |
| 159 | + }, |
| 160 | + filterOutBlockedUsers(recommendations) { |
| 161 | + let i = recommendations.length; |
| 162 | + const { blocks } = this.$store.getters.getLoggedInUser; |
| 163 | + let blockedIds = []; |
| 164 | + for (let j = 0; j < blocks.length; j += 1) { |
| 165 | + blockedIds.push(blocks[j].blocked_id); |
| 166 | + } |
| 167 | + while (i--) { |
| 168 | + if (blockedIds.indexOf(recommendations[i].id) !== -1) { |
| 169 | + recommendations.splice(i, 1); |
| 170 | + } |
| 171 | + } |
| 172 | + return recommendations; |
| 173 | + }, |
| 174 | + saveSingleChoice() { |
| 175 | + console.log('bingo'); |
| 176 | + }, |
| 177 | + }, |
| 178 | + watch: { |
| 179 | + sorting: { |
| 180 | + handler() { |
| 181 | + this.sort(this.recommendations, this.sorting); |
| 182 | + }, |
| 183 | + }, |
| 184 | + filters: { |
| 185 | + handler() { |
| 186 | + let base = this.recommendationsBackup.slice(); |
| 187 | + base = this.filter(base); |
| 188 | + this.sort(base, this.sorting); |
| 189 | + this.recommendations = base; |
| 190 | + }, |
| 191 | + deep: true, |
| 192 | + } |
| 193 | + }, |
| 194 | + beforeMount() { |
| 195 | + this.recommendations = this.filterOutBlockedUsers(this.recommendationsReceived); |
| 196 | + this.recommendationsBackup = this.recommendations; |
| 197 | + this.filters.age.min = this.recommendationsAnalysis.age.min; |
| 198 | + this.filters.age.max = this.recommendationsAnalysis.age.max; |
| 199 | + this.filters.distance.min = this.recommendationsAnalysis.distance.min; |
| 200 | + this.filters.distance.max = this.recommendationsAnalysis.distance.max; |
| 201 | + this.filters.popularity.min = this.recommendationsAnalysis.popularity.min; |
| 202 | + this.filters.popularity.max = this.recommendationsAnalysis.popularity.max; |
| 203 | + } |
| 204 | +}; |
| 205 | +</script> |
0 commit comments