Grégoire Delattre 4b26080193
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Update redux state management
Use immer with native javascript objects instead of immutablejs.
2020-04-07 18:22:26 +02:00

178 lines
4.1 KiB
JavaScript

import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import fuzzy from "fuzzy";
import InfiniteScroll from "react-infinite-scroll-component";
import ListFilter from "./filter";
import ExplorerOptions from "./explorerOptions";
import Poster from "./poster";
import { KeyboardNavigation } from "./keyboard";
import Loader from "../loader/loader";
const ListPosters = ({
data,
exploreFetchOptions,
exploreOptions,
loading,
onClick,
onDoubleClick,
onKeyEnter,
params,
placeHolder,
selectedImdbId,
type,
}) => {
const [list, setList] = useState([]);
const [filteredList, setFilteredList] = useState([]);
const [filter, setFilter] = useState("");
useEffect(() => {
let l = [];
data.forEach((e) => {
l.push({
imdbId: e.imdb_id,
posterUrl: e.poster_url,
title: e.title,
});
});
setList(l);
}, [data]);
useEffect(() => {
if (filter !== "" && filter.length >= 3) {
setFilteredList(list.filter((e) => fuzzy.test(filter, e.title)));
} else {
setFilteredList(list);
}
}, [filter, list]);
if (loading) {
return <Loader />;
}
// Chose when to display filter / explore options
let displayFilter = true;
if (
(params &&
params.category &&
params.category !== "" &&
params.source &&
params.source !== "") ||
list.length === 0
) {
displayFilter = false;
}
let displayExplorerOptions = false;
if (list.length !== 0) {
displayExplorerOptions = !displayFilter;
}
return (
<div className="col-4 col-md-8 px-1">
{displayFilter && (
<ListFilter updateFilter={setFilter} placeHolder={placeHolder} />
)}
<ExplorerOptions
type={type}
display={displayExplorerOptions}
params={params}
fetch={exploreFetchOptions}
options={exploreOptions}
/>
<Posters
list={filteredList}
loading={loading}
selectedImdbId={selectedImdbId}
selectPoster={onClick}
onDoubleClick={onDoubleClick}
onKeyEnter={onKeyEnter}
/>
</div>
);
};
ListPosters.propTypes = {
data: PropTypes.object,
onClick: PropTypes.func,
onDoubleClick: PropTypes.func,
onKeyEnter: PropTypes.func,
selectedImdbId: PropTypes.string,
loading: PropTypes.bool.isRequired,
params: PropTypes.object.isRequired,
exploreOptions: PropTypes.object,
type: PropTypes.string.isRequired,
placeHolder: PropTypes.string.isRequired,
exploreFetchOptions: PropTypes.func,
};
export default ListPosters;
const Posters = ({
list,
onKeyEnter,
selectedImdbId,
selectPoster,
onDoubleClick,
}) => {
const addMoreCount = 20;
const [size, setSize] = useState(0);
const updateSize = (newSize, maxSize) => {
setSize(Math.min(newSize, maxSize));
};
useEffect(() => {
updateSize(size + addMoreCount, list.length);
}, [list]); // eslint-disable-line react-hooks/exhaustive-deps
const loadMore = () => {
updateSize(size + addMoreCount, list.length);
};
if (list.length === 0) {
return (
<div className="jumbotron">
<h2>No result</h2>
</div>
);
}
return (
<KeyboardNavigation
onKeyEnter={onKeyEnter}
selectPoster={selectPoster}
list={list}
selected={selectedImdbId}
>
<InfiniteScroll
className="poster-list d-flex flex-column flex-sm-row flex-sm-wrap justify-content-around"
dataLength={size}
next={loadMore}
hasMore={size !== list.length}
loader={<Loader />}
>
{list.slice(0, size).map((el, index) => {
const imdbId = el.imdbId;
return (
<Poster
url={el.posterUrl}
key={index}
selected={imdbId === selectedImdbId}
onClick={() => selectPoster(imdbId)}
onDoubleClick={() => onDoubleClick(imdbId)}
/>
);
}, this)}
</InfiniteScroll>
</KeyboardNavigation>
);
};
Posters.propTypes = {
list: PropTypes.array.isRequired,
selectedImdbId: PropTypes.string,
onDoubleClick: PropTypes.func,
onKeyEnter: PropTypes.func,
selectPoster: PropTypes.func,
};