FunctionProject/website/components/FunctionsList/FunctionsList.jsx

152 lines
4.4 KiB
React
Raw Normal View History

2020-08-03 12:04:07 +02:00
import { useState, useEffect, useRef, useCallback } from 'react'
import { useRouter } from 'next/router'
import FunctionCard from '../FunctionCard/FunctionCard'
import Loader from '../Loader'
import api from '../../utils/api'
import useAPI from '../../hooks/useAPI'
import './FunctionsList.css'
2020-08-03 12:04:07 +02:00
let pageFunctions = 1
2020-08-03 14:14:45 +02:00
const FunctionsList = props => {
2020-08-03 12:04:07 +02:00
const { categoryId } = useRouter().query
2020-08-03 12:04:07 +02:00
// State de recherche et de catégories
const [, categories] = useAPI('/categories')
2020-08-03 14:14:45 +02:00
const [inputSearch, setInputSearch] = useState({
search: '',
selectedCategory: categoryId || '0'
})
2020-08-03 12:04:07 +02:00
// State pour afficher les fonctions
2020-08-03 14:14:45 +02:00
const [functionsData, setFunctionsData] = useState({
hasMore: true,
rows: []
})
2020-08-03 12:04:07 +02:00
const [isLoadingFunctions, setLoadingFunctions] = useState(true)
2020-08-03 12:04:07 +02:00
// Récupère la catégorie avec la query categoryId
useEffect(() => {
if (categoryId) {
handleChange({ target: { name: 'selectedCategory', value: categoryId } })
}
}, [categoryId])
2020-08-03 12:04:07 +02:00
// Récupère les fonctions si la catégorie/recherche change
useEffect(() => {
pageFunctions = 1
2020-08-03 14:14:45 +02:00
getFunctionsData().then(data => setFunctionsData(data))
2020-08-03 12:04:07 +02:00
}, [inputSearch])
2020-08-03 12:04:07 +02:00
// Permet la pagination au scroll
const observer = useRef()
2020-08-03 14:14:45 +02:00
const lastFunctionCardRef = useCallback(
node => {
if (isLoadingFunctions) return
if (observer.current) observer.current.disconnect()
observer.current = new window.IntersectionObserver(
entries => {
if (entries[0].isIntersecting && functionsData.hasMore) {
pageFunctions += 1
getFunctionsData().then(data => {
setFunctionsData(oldData => {
return {
hasMore: data.hasMore,
rows: [...oldData.rows, ...data.rows]
}
})
})
}
},
{ threshold: 1 }
)
if (node) observer.current.observe(node)
},
[isLoadingFunctions, functionsData.hasMore]
)
2020-08-03 12:04:07 +02:00
const getFunctionsData = async () => {
setLoadingFunctions(true)
2020-08-03 14:14:45 +02:00
const URL = `${
props.isAdmin ? '/admin/functions' : '/functions'
}?page=${pageFunctions}&limit=10&categoryId=${
inputSearch.selectedCategory
}&search=${inputSearch.search}`
2020-08-03 12:04:07 +02:00
const { data } = await api.get(URL, {
headers: {
2020-08-03 14:14:45 +02:00
...(props.isAdmin &&
props.token != null && { Authorization: props.token })
2020-08-03 12:04:07 +02:00
}
})
setLoadingFunctions(false)
return data
}
2020-08-03 14:14:45 +02:00
const handleChange = event => {
2020-08-03 12:04:07 +02:00
const inputSearchNew = { ...inputSearch }
inputSearchNew[event.target.name] = event.target.value
setInputSearch(inputSearchNew)
}
2020-08-03 12:04:07 +02:00
return (
<div className='container text-center'>
2020-08-03 14:14:45 +02:00
<div className='row justify-content-center'>{props.children}</div>
2020-08-03 12:04:07 +02:00
<div className='Functions__search-container row justify-content-center'>
2020-08-03 14:14:45 +02:00
<select
name='selectedCategory'
value={inputSearch.selectedCategory}
onChange={handleChange}
className='Functions__select Functions__form-control'
>
2020-08-03 12:04:07 +02:00
<option value='0'>Toutes catégories</option>
2020-08-03 14:14:45 +02:00
{categories.map(category => (
<option
key={category.id}
value={category.id}
className='Functions__select-option'
style={{ backgroundColor: category.color }}
>
{category.name}
</option>
2020-08-03 12:04:07 +02:00
))}
</select>
2020-08-03 14:14:45 +02:00
<input
value={inputSearch.search}
onChange={handleChange}
type='search'
className='Functions__form-control Functions__search-input'
name='search'
id='search'
placeholder='🔎 Rechercher...'
/>
2020-08-03 12:04:07 +02:00
</div>
2020-08-03 12:04:07 +02:00
<div className='row justify-content-center'>
{functionsData.rows.map((currentFunction, index) => {
// Si c'est le dernier élément
if (functionsData.rows.length === index + 1) {
2020-08-03 14:14:45 +02:00
return (
<FunctionCard
isAdmin={props.isAdmin}
key={currentFunction.id}
ref={lastFunctionCardRef}
{...currentFunction}
/>
)
2020-08-03 12:04:07 +02:00
}
2020-08-03 14:14:45 +02:00
return (
<FunctionCard
isAdmin={props.isAdmin}
key={currentFunction.id}
{...currentFunction}
/>
)
2020-08-03 12:04:07 +02:00
})}
</div>
{isLoadingFunctions && <Loader />}
</div>
)
}
2020-08-03 12:04:07 +02:00
export default FunctionsList