From d35778f5e2c62920c0a673315bb2576161b18408 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Thu, 23 Dec 2021 15:58:53 +0530 Subject: [PATCH] fix pagination errors --- jam-ui/src/components/page/JKPeople.js | 37 +- jam-ui/src/components/page/JKPeopleFilter.js | 194 +++++---- .../src/components/page/JKPeopleFilter_bk.js | 372 ++++++++++++++++++ jam-ui/src/components/page/JKPeopleList.js | 9 +- web/app/controllers/api_search_controller.rb | 3 +- 5 files changed, 508 insertions(+), 107 deletions(-) create mode 100644 jam-ui/src/components/page/JKPeopleFilter_bk.js diff --git a/jam-ui/src/components/page/JKPeople.js b/jam-ui/src/components/page/JKPeople.js index 321e2e506..96ebe7192 100644 --- a/jam-ui/src/components/page/JKPeople.js +++ b/jam-ui/src/components/page/JKPeople.js @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; -import { Alert, Card, CardBody, Col, Row, Button, Form } from 'reactstrap'; +import { Alert, Col, Row } from 'reactstrap'; import Loader from '../common/Loader'; import { isIterableArray } from '../../helpers/utils'; import { useSelector } from 'react-redux'; @@ -20,28 +20,6 @@ const JKPeople = ({ className, onPageChange }) => { const { greaterThan } = useResponsive(); - // const loadPeople = React.useCallback(() => { - // if (totalPages !== 0 && page > totalPages) { - // setPage(totalPages + 1); - // return; - // } - // try { - // onPageChange(page) - // } catch (error) { - // console.log('Error fetching people', error); - // } - // }, [page, totalPages, dispatch]); - - // useEffect(() => { - // loadPeople(); - - // }, [page]); - - // useEffect(() => { - // if (loadingStatus === 'succeeded' && peopleListRef.current && page !== 1) { - // } - // }, [loadingStatus]); - useEffect(() => { try { console.log("DEBUG======", page, hasNext); @@ -66,19 +44,6 @@ const JKPeople = ({ className, onPageChange }) => { } }; - // const handleScroll = () => { - // if (window.innerHeight + window.scrollY >= document.body.offsetHeight) { - // goNextPage(); - // } - // }; - - // useEffect(() => { - // window.addEventListener('scroll', handleScroll, { passive: true }); - // return () => { - // window.removeEventListener('scroll', handleScroll); - // }; - // }, []); - return (
{loadingStatus === 'loading' && people.length === 0 ? ( diff --git a/jam-ui/src/components/page/JKPeopleFilter.js b/jam-ui/src/components/page/JKPeopleFilter.js index f7ae0a425..c492a0c40 100644 --- a/jam-ui/src/components/page/JKPeopleFilter.js +++ b/jam-ui/src/components/page/JKPeopleFilter.js @@ -1,25 +1,38 @@ import React, { useState, useEffect, useRef } from 'react'; -import { Button, Card, CardBody, Form, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { Alert, Col, Row, Button, Card, CardBody, Form, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import FalconCardHeader from '../common/FalconCardHeader'; +import Loader from '../common/Loader'; +import { isIterableArray } from '../../helpers/utils'; +import { useResponsive } from '@farfetch/react-context-responsive'; import { useTranslation } from 'react-i18next'; import Select from 'react-select'; import JKTooltip from '../common/JKTooltip'; +import JKPeopleList from './JKPeopleList'; +import JKPeopleSwiper from './JKPeopleSwiper'; import { getGenres, getInstruments } from '../../helpers/rest'; import { useForm, Controller, useFormState } from 'react-hook-form'; import { useDispatch, useSelector } from 'react-redux'; import { fetchPeople, resetState, loadPrefetched, preFetchPeople } from '../../store/features/peopleSlice'; -import JKPeople from './JKPeople'; function JKPeopleFilter() { const { t } = useTranslation(); - const [ show, setShow ] = useState(false); + const [show, setShow] = useState(false); const [resetFilter, setResetFilter] = useState(false); const [instruments, setInstruments] = useState([]); const [genres, setGenres] = useState([]); const dispatch = useDispatch(); - const pageToRequest = useRef(1) + const currentPage = useRef(1); + const nextPage = useRef(1); + const [hasNextPage, setHasNextPage] = useState(true) + + const { greaterThan } = useResponsive(); + + const peopleListRef = useRef(); + + const people = useSelector(state => state.people.people); const totalPages = useSelector(state => state.people.totalPages); + const loadingStatus = useSelector(state => state.people.status); const { register, handleSubmit, setValue, control } = useForm({ defaultValues: { @@ -40,6 +53,22 @@ function JKPeopleFilter() { const toggle = () => setShow(!show); + const lastActiveOpts = [ + { value: '', label: 'Any Range' }, + { value: '1', label: 'Within Last 1 Days' }, + { value: '7', label: 'Within Last 7 Days' }, + { value: '30', label: 'Within Last 30 Days' }, + { value: '90', label: 'Within Last 90 Days' } + ]; + + const joinedOpts = [ + { value: '', label: 'Any Range' }, + { value: '1', label: 'Within Last 1 Days' }, + { value: '7', label: 'Within Last 7 Days' }, + { value: '30', label: 'Within Last 30 Days' }, + { value: '90', label: 'Within Last 90 Days' } + ]; + const fetchInstruments = async () => { await getInstruments() .then(response => { @@ -82,50 +111,37 @@ function JKPeopleFilter() { }); }; - useEffect(() => { - if (resetFilter) { - clearFilterOpts(); - setResetFilter(false); - dispatch(resetState()); - pageToRequest.current = 1 - handleSubmit(onSubmit)() - } - }, [resetFilter]); - + const goNextPage = () => { + submitPageQuery(currentPage.current) + }; const clearFilterOpts = () => { - setValue('latency_good', true) - setValue('latency_fair', true) - setValue('latency_high', false) - setValue('proficiency_beginner', true) - setValue('proficiency_intermediate', true) - setValue('proficiency_expert', true) - setValue('instruments', null) - setValue('genres', null) - setValue('joined_within_days', -1) - setValue('active_within_days', -1) - } + setValue('latency_good', true); + setValue('latency_fair', true); + setValue('latency_high', false); + setValue('proficiency_beginner', true); + setValue('proficiency_intermediate', true); + setValue('proficiency_expert', true); + setValue('instruments', null); + setValue('genres', null); + setValue('joined_within_days', -1); + setValue('active_within_days', -1); + }; - useEffect(() => { - fetchGenres(); - fetchInstruments(); - }, []); + const submitPageQuery = () => { + handleSubmit(onSubmit)(); + }; const submitForm = event => { event.preventDefault(); - pageToRequest.current = 1 + currentPage.current = 1; + nextPage.current = 1; dispatch(resetState()); - handleSubmit(onSubmit)(pageToRequest.current); + handleSubmit(onSubmit)(nextPage.current); setShow(false); }; - const submitPageQuery = (page, hasNextPage) => { - handleSubmit(onSubmit)(page, hasNextPage) - } - - const onSubmit = (data, page, hasNextPage = true) => { - let _page = pageToRequest.current > page ? pageToRequest.current : page - + const onSubmit = (data) => { let genres = []; let joined_within_days = ''; let active_within_days = ''; @@ -133,48 +149,55 @@ function JKPeopleFilter() { if (data.genres) { genres = data.genres.map(genre => genre.value); } - if(data.joined_within_days){ + if (data.joined_within_days) { joined_within_days = data.joined_within_days.value; } - if(data.active_within_days){ + if (data.active_within_days) { active_within_days = data.active_within_days.value; } const params = { ...data, genres, joined_within_days, active_within_days }; try { - dispatch(loadPrefetched()) - if(totalPages && _page > totalPages){ - return - } - dispatch(fetchPeople({ data: params, page: _page })); - pageToRequest.current++ - if(hasNextPage){ - dispatch(preFetchPeople({ data: params, page: _page + 1 })) - pageToRequest.current = pageToRequest.current + 2 - } + dispatch(loadPrefetched()); + currentPage.current = nextPage.current + + dispatch(fetchPeople({ data: params, page: currentPage.current })); + + nextPage.current = currentPage.current + 1 + + if (hasNextPage) { + dispatch(preFetchPeople({ data: params, page: nextPage.current })); + nextPage.current = nextPage.current + 1; + } } catch (error) { console.log('error fetching people', error); } - }; - const lastActiveOpts = [ - { value: '', label: 'Any Range' }, - { value: '1', label: 'Within Last 1 Days' }, - { value: '7', label: 'Within Last 7 Days' }, - { value: '30', label: 'Within Last 30 Days' }, - { value: '90', label: 'Within Last 90 Days' } - ]; + useEffect(() => { + fetchGenres(); + fetchInstruments(); + submitPageQuery(currentPage.current) + }, []); - const joinedOpts = [ - { value: '', label: 'Any Range' }, - { value: '1', label: 'Within Last 1 Days' }, - { value: '7', label: 'Within Last 7 Days' }, - { value: '30', label: 'Within Last 30 Days' }, - { value: '90', label: 'Within Last 90 Days' } - ]; + useEffect(() => { + if(totalPages > 0){ + setHasNextPage(currentPage.current < totalPages) + } + }, [totalPages, currentPage.current]); + + useEffect(() => { + if (resetFilter) { + clearFilterOpts(); + dispatch(resetState()); + currentPage.current = 1; + nextPage.current = 1; + handleSubmit(onSubmit)(); + setResetFilter(false); + } + }, [resetFilter]); return ( @@ -193,7 +216,7 @@ function JKPeopleFilter() { color="secondary" className="fs--1" data-testid="btnResetSearch" - onClick={() => setResetFilter(true) } + onClick={() => setResetFilter(true)} > {t('reset_filters', { ns: 'people' })} @@ -359,8 +382,43 @@ function JKPeopleFilter() { - - + +
+ {loadingStatus === 'loading' && people.length === 0 ? ( + + ) : isIterableArray(people) ? ( + //Start Find Friends table hidden on small screens + <> + {greaterThan.xs ? ( + +
+ +
+
+ ) : ( + + + + )} + + ) : ( + + + + No Records! + + + + )} +
); diff --git a/jam-ui/src/components/page/JKPeopleFilter_bk.js b/jam-ui/src/components/page/JKPeopleFilter_bk.js new file mode 100644 index 000000000..882ce618b --- /dev/null +++ b/jam-ui/src/components/page/JKPeopleFilter_bk.js @@ -0,0 +1,372 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { Button, Card, CardBody, Form, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import FalconCardHeader from '../common/FalconCardHeader'; +import { useTranslation } from 'react-i18next'; +import Select from 'react-select'; +import JKTooltip from '../common/JKTooltip'; + +import { getGenres, getInstruments } from '../../helpers/rest'; +import { useForm, Controller, useFormState } from 'react-hook-form'; +import { useDispatch, useSelector } from 'react-redux'; +import { fetchPeople, resetState, loadPrefetched, preFetchPeople } from '../../store/features/peopleSlice'; +import JKPeople from './JKPeople'; + +function JKPeopleFilter() { + const { t } = useTranslation(); + const [ show, setShow ] = useState(false); + const [resetFilter, setResetFilter] = useState(false); + const [instruments, setInstruments] = useState([]); + const [genres, setGenres] = useState([]); + const dispatch = useDispatch(); + const pageToRequest = useRef(1) + const totalPages = useSelector(state => state.people.totalPages); + + const { register, handleSubmit, setValue, control } = useForm({ + defaultValues: { + latency_good: true, + latency_fair: true, + latency_high: false, + proficiency_beginner: true, + proficiency_intermediate: true, + proficiency_expert: true, + instruments: [], + genres: [], + joined_within_days: '-1', + active_within_days: '-1' + } + }); + + const { isDirty } = useFormState({ control }); + + const toggle = () => setShow(!show); + + const fetchInstruments = async () => { + await getInstruments() + .then(response => { + if (response.ok) { + return response.json(); + } + }) + .then(data => { + setInstruments( + data.map(instrument => { + return { + value: instrument.id, + label: instrument.description + }; + }) + ); + }) + .catch(error => console.log(error)); + }; + + const fetchGenres = async () => { + await getGenres() + .then(response => { + if (response.ok) { + return response.json(); + } + }) + .then(data => { + setGenres( + data.map(genre => { + return { + value: genre.id, + label: genre.description + }; + }) + ); + }) + .catch(error => { + console.log(error); + }); + }; + + useEffect(() => { + if (resetFilter) { + clearFilterOpts(); + setResetFilter(false); + dispatch(resetState()); + pageToRequest.current = 1 + handleSubmit(onSubmit)() + } + }, [resetFilter]); + + + const clearFilterOpts = () => { + setValue('latency_good', true) + setValue('latency_fair', true) + setValue('latency_high', false) + setValue('proficiency_beginner', true) + setValue('proficiency_intermediate', true) + setValue('proficiency_expert', true) + setValue('instruments', null) + setValue('genres', null) + setValue('joined_within_days', -1) + setValue('active_within_days', -1) + } + + useEffect(() => { + fetchGenres(); + fetchInstruments(); + }, []); + + const submitForm = event => { + event.preventDefault(); + pageToRequest.current = 1 + dispatch(resetState()); + handleSubmit(onSubmit)(pageToRequest.current); + setShow(false); + }; + + const submitPageQuery = (page, hasNextPage) => { + handleSubmit(onSubmit)(page, hasNextPage) + } + + const onSubmit = (data, page, hasNextPage = true) => { + let _page = pageToRequest.current > page ? pageToRequest.current : page + + let genres = []; + let joined_within_days = ''; + let active_within_days = ''; + + if (data.genres) { + genres = data.genres.map(genre => genre.value); + } + if(data.joined_within_days){ + joined_within_days = data.joined_within_days.value; + } + if(data.active_within_days){ + active_within_days = data.active_within_days.value; + } + + const params = { ...data, genres, joined_within_days, active_within_days }; + + console.log("---DEBUG--- _page", _page); + console.log("---DEBUG--- totalPages", totalPages); + + try { + dispatch(loadPrefetched()) + if(totalPages && _page > totalPages){ + return + } + dispatch(fetchPeople({ data: params, page: _page })); + pageToRequest.current++ + if(hasNextPage){ + dispatch(preFetchPeople({ data: params, page: _page + 1 })) + pageToRequest.current = pageToRequest.current + 2 + } + + } catch (error) { + console.log('error fetching people', error); + } + + }; + + const lastActiveOpts = [ + { value: '', label: 'Any Range' }, + { value: '1', label: 'Within Last 1 Days' }, + { value: '7', label: 'Within Last 7 Days' }, + { value: '30', label: 'Within Last 30 Days' }, + { value: '90', label: 'Within Last 90 Days' } + ]; + + const joinedOpts = [ + { value: '', label: 'Any Range' }, + { value: '1', label: 'Within Last 1 Days' }, + { value: '7', label: 'Within Last 7 Days' }, + { value: '30', label: 'Within Last 30 Days' }, + { value: '90', label: 'Within Last 90 Days' } + ]; + + return ( + + +
+ + +
+
+ + + Update Search + +
+
+
+ {/* first column */} +
+
+
+ +
+ setValue('latency_good', e.target.checked)} + /> + +
+
+ setValue('latency_fair', e.target.checked)} + /> + +
+
+ setValue('latency_high', e.target.checked)} + /> + +
+
+ +
+ +
+ setValue('proficiency_beginner', e.target.checked)} + /> + +
+
+ setValue('proficiency_intermediate', e.target.checked)} + /> + +
+
+ setValue('proficiency_expert', e.target.checked)} + /> + +
+
+
+
+ + {/* second column */} +
+ +
+ ( + + )} + /> +
+ +
+ } + /> +
+
+
+
+
+
+ + {' '} + + +
+ + +
+
+ ); +} + +export default JKPeopleFilter; diff --git a/jam-ui/src/components/page/JKPeopleList.js b/jam-ui/src/components/page/JKPeopleList.js index 724a825fb..0199b42af 100644 --- a/jam-ui/src/components/page/JKPeopleList.js +++ b/jam-ui/src/components/page/JKPeopleList.js @@ -4,7 +4,7 @@ import JKPerson from './JKPerson'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; -const JKPeopleList = ({ people, goNextPage, hasNext }) => { +const JKPeopleList = ({ people, goNextPage, hasNext, isLoading }) => { const { t } = useTranslation(); return ( <> @@ -26,7 +26,12 @@ const JKPeopleList = ({ people, goNextPage, hasNext }) => { ))} - {hasNext && } + + {hasNext && ( + + )} ); }; diff --git a/web/app/controllers/api_search_controller.rb b/web/app/controllers/api_search_controller.rb index edde43efb..b6f82a589 100644 --- a/web/app/controllers/api_search_controller.rb +++ b/web/app/controllers/api_search_controller.rb @@ -157,7 +157,8 @@ class ApiSearchController < ApiController filter_params.merge!(active_within_days: params[:active_within_days]) unless params[:active_within_days].blank? sobj = MusicianSearch.user_search_filter(current_user) - @search = sobj.search_results_page(filter_params, [params[:page].to_i, 1].max, user_ids) + #@search = sobj.search_results_page(filter_params, [params[:page].to_i, 1].max, user_ids) + @search = sobj.search_results_page(filter_params, [params[:page].to_i, 1].max) respond_with @search, responder: ApiResponder, status: 201, template: 'api_search/index'