Skip to content

Commit 0964f30

Browse files
committed
infinite scroll browse, search, history
1 parent 0a48089 commit 0964f30

File tree

6 files changed

+78
-5
lines changed

6 files changed

+78
-5
lines changed

frontend/src/components/app/recommendations/HistoryRecommendations.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<!-- eslint-disable max-len -->
3-
<section class="mb-4 sm:mb-16 lg:mb-32">
3+
<section class="sm:mb-16 lg:mb-32">
44
<div v-if="recommendationsBackup.length" v-bind:class="{
55
'flex': true,
66
'w-full': true,
@@ -48,6 +48,8 @@
4848
<div v-if="recommendations.length" ref="recommendationCards" class="grid grid-cols-1 md:grid-cols-2 gap-2">
4949
<RecommendationCard
5050
v-for="(recommendation, index) in recommendations" :key="index"
51+
v-bind:index="index"
52+
v-bind:showCount="showCount"
5153
v-bind:recommendation="recommendation"></RecommendationCard>
5254
</div>
5355
<div class="text-center md:text-left px-4 md:px-0" v-if="!recommendations.length">
@@ -65,7 +67,7 @@ import RecommendationCard from '@/components/app/recommendations/RecommendationC
6567
import MultipleFiltersDropdown from '@/components/shared/MultipleFiltersDropdown.vue';
6668
6769
export default {
68-
props: ['title', 'recommendationsReceived', 'recommendationsAnalysis'],
70+
props: ['title', 'recommendationsReceived', 'recommendationsAnalysis', 'showCount'],
6971
components: {
7072
Sort,
7173
RecommendationCard,
@@ -110,10 +112,12 @@ export default {
110112
const [name, min, max] = range;
111113
this.filters[name].min = min;
112114
this.filters[name].max = max;
115+
this.$emit('reset-show-count');
113116
},
114117
saveFilterMultiple(...multiple) {
115118
const [name, filters] = multiple;
116119
this.filters[name] = filters;
120+
this.$emit('reset-show-count');
117121
},
118122
sort(recommendations, by) {
119123
if (by === 'Closest') {

frontend/src/components/app/recommendations/RecommendationCard.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22
<!-- eslint-disable max-len -->
33
<div
4+
v-if="index < showCount"
45
v-on:click="viewUser(recommendation.id)"
56
class="flex flex-col justify-end shadow-inner recommendation-card rounded-md cursor-pointer"
67
v-bind:style="{
@@ -33,7 +34,7 @@ import imageWoman from '../../../assets/recommendations/avatars/woman1.png';
3334
import imageOther from '../../../assets/recommendations/avatars/other.png';
3435
3536
export default {
36-
props: ['recommendation'],
37+
props: ['recommendation', 'index', 'showCount'],
3738
methods: {
3839
async viewUser(id) {
3940
await this.$router.push(`/users/${id}`);

frontend/src/components/app/recommendations/Recommendations.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<!-- eslint-disable max-len -->
3-
<section class="mb-4 sm:mb-16 lg:mb-32">
3+
<section class="sm:mb-16 lg:mb-32">
44
<h1
55
class="text-5xl my-4 text-center md:text-left leading-none onboarding-sub-container-content-heading">
66
{{recommendations.length}} {{title}}</h1>
@@ -42,6 +42,8 @@
4242
<div ref="recommendationCards" class="grid grid-cols-1 md:grid-cols-2 gap-2">
4343
<RecommendationCard
4444
v-for="(recommendation, index) in recommendations" :key="index"
45+
v-bind:index="index"
46+
v-bind:showCount="showCount"
4547
v-bind:recommendation="recommendation"></RecommendationCard>
4648
</div>
4749
</section>
@@ -55,7 +57,7 @@ import RecommendationCard from '@/components/app/recommendations/RecommendationC
5557
import MultipleFiltersDropdown from '@/components/shared/MultipleFiltersDropdown.vue';
5658
5759
export default {
58-
props: ['title', 'recommendationsReceived', 'recommendationsAnalysis'],
60+
props: ['title', 'recommendationsReceived', 'recommendationsAnalysis', 'showCount'],
5961
components: {
6062
Sort,
6163
RecommendationCard,
@@ -100,10 +102,12 @@ export default {
100102
const [name, min, max] = range;
101103
this.filters[name].min = min;
102104
this.filters[name].max = max;
105+
this.$emit('reset-show-count');
103106
},
104107
saveFilterMultiple(...multiple) {
105108
const [name, filters] = multiple;
106109
this.filters[name] = filters;
110+
this.$emit('reset-show-count');
107111
},
108112
sort(recommendations, by) {
109113
if (by === 'Closest') {

frontend/src/views/app/Browse.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
</div>
88
<Recommendations
99
v-if="recommendationsAnalysisDone"
10+
v-bind:showCount="showCount"
11+
v-on:reset-show-count="resetShowCount()"
1012
v-bind:title="'Potential matches'"
1113
v-bind:recommendationsReceived="recommendations"
1214
v-bind:recommendationsAnalysis="recommendationsAnalysis"></Recommendations>
15+
<div id="invisibleFooter" class="h-4 w-full bg-white"></div>
1316
</section>
1417
</div>
1518
</template>
@@ -43,6 +46,7 @@ export default {
4346
interests: [],
4447
},
4548
recommendationsAnalysisDone: false,
49+
showCount: 10,
4650
}),
4751
methods: {
4852
async fetchUsers() {
@@ -97,11 +101,29 @@ export default {
97101
this.recommendationsAnalysis.popularity.max = null;
98102
this.recommendationsAnalysis.interests = [];
99103
this.recommendationsAnalysisDone = false;
104+
this.showCount = 10;
105+
},
106+
handleIntersect(entries) {
107+
if (entries[0].isIntersecting) {
108+
this.showCount += 10;
109+
}
110+
},
111+
resetShowCount() {
112+
this.showCount = 10;
100113
},
101114
},
102115
async created() {
103116
await this.fetchUsers();
104117
},
118+
mounted() {
119+
const options = {
120+
root: null,
121+
rootMargins: '0px',
122+
threshold: 0.5,
123+
};
124+
const observer = new IntersectionObserver(this.handleIntersect, options);
125+
observer.observe(document.querySelector('#invisibleFooter'));
126+
},
105127
deactivated() {
106128
if (!this.$route.path.startsWith('/users')) {
107129
this.browseAgain();

frontend/src/views/app/History.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818
</div>
1919
<HistoryRecommendations
2020
v-if="recommendationsAnalysisDone"
21+
v-bind:showCount="showCount"
22+
v-on:reset-show-count="resetShowCount()"
2123
v-on:filtered-count="filteredCountSave"
2224
v-bind:title="'Potential matches'"
2325
v-bind:recommendationsReceived="recommendations"
2426
v-bind:recommendationsAnalysis="recommendationsAnalysis"></HistoryRecommendations>
27+
<div id="invisibleFooterHistory" class="h-4 w-full bg-white"></div>
2528
</section>
2629
</div>
2730
</template>
@@ -61,6 +64,7 @@ export default {
6164
filteredCount: null,
6265
historyFetched: false,
6366
visitUser: false,
67+
showCount: 10,
6468
}),
6569
methods: {
6670
async fetchUsers(request) {
@@ -129,6 +133,7 @@ export default {
129133
this.recommendationsAnalysisDone = false;
130134
this.historyFetched = false;
131135
this.visitUser = false;
136+
this.showCount = 10;
132137
},
133138
async updateHistory(...args) {
134139
const [key, value] = args;
@@ -142,6 +147,23 @@ export default {
142147
const [count] = args;
143148
this.filteredCount = count;
144149
},
150+
handleIntersect(entries) {
151+
if (entries[0].isIntersecting) {
152+
this.showCount += 10;
153+
}
154+
},
155+
resetShowCount() {
156+
this.showCount = 10;
157+
},
158+
},
159+
mounted() {
160+
const options = {
161+
root: null,
162+
rootMargins: '0px',
163+
threshold: 0.5,
164+
};
165+
const observer = new IntersectionObserver(this.handleIntersect, options);
166+
observer.observe(document.querySelector('#invisibleFooterHistory'));
145167
},
146168
async beforeRouteEnter(to, from, next) {
147169
next(async (vm) => {

frontend/src/views/app/Search.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
<h1 class="noSelect capitalize">←</h1>
1010
</div>
1111
<Recommendations
12+
v-bind:showCount="showCount"
13+
v-on:reset-show-count="resetShowCount()"
1214
v-bind:title="'Potential matches'"
1315
v-bind:recommendationsReceived="recommendations"
1416
v-bind:recommendationsAnalysis="filters"></Recommendations>
1517
</section>
18+
<div id="invisibleFooterSearch" class="h-4 w-full bg-white"></div>
1619
<section v-on:click="setError(null)"
1720
v-if="!recommendationsAnalysisDone && sliderValuesFetched"
1821
class="flex flex-col my-8 md:my-12">
@@ -110,6 +113,7 @@ export default {
110113
recommendationsAnalysisDone: false,
111114
error: null,
112115
submitted: false,
116+
showCount: 10,
113117
}),
114118
methods: {
115119
saveFilter(...range) {
@@ -195,16 +199,32 @@ export default {
195199
this.filters.distance.max = null;
196200
this.filters.interests = [];
197201
this.recommendationsAnalysisDone = false;
202+
this.showCount = 10;
198203
},
199204
setError(message) {
200205
this.error = message;
201206
},
202207
scrollToTop() {
203208
window.scrollTo(0, 0);
204209
},
210+
handleIntersect(entries) {
211+
if (entries[0].isIntersecting && this.recommendationsAnalysisDone) {
212+
this.showCount += 10;
213+
}
214+
},
215+
resetShowCount() {
216+
this.showCount = 10;
217+
},
205218
},
206219
async mounted() {
207220
await this.fetchUsersOverfiew();
221+
const options = {
222+
root: null,
223+
rootMargins: '0px',
224+
threshold: 0.5,
225+
};
226+
const observer = new IntersectionObserver(this.handleIntersect, options);
227+
observer.observe(document.querySelector('#invisibleFooterSearch'));
208228
},
209229
deactivated() {
210230
if (!this.$route.path.startsWith('/users')) {

0 commit comments

Comments
 (0)