import React, { useState } from 'react'; import { debounce } from 'lodash'; import { Input, Col, Row, Select, Pagination } from 'antd'; import { Track } from './tracks/Track'; import { ManagedTrack } from './tracks/ManagedTrack'; import { useAppState } from '../hooks/useAppState'; import { useErrors } from '../hooks/useErrors'; import { fetchTacks, countTracks, fetchGenres } from '../api/calls'; import { useAbortableEffect } from '../hooks/useAbortableEffect'; import { requireEmployee } from '../util/constants'; import './TracksPage.css'; const { Search } = Input; const { Option } = Select; const DEBOUNCE_TIMER = 500; const DEBOUNCE_OPTIONS = { leading: true, trailing: false, }; const renderGenres = (genres) => genres.map(({ ID, name }) => ( )); const TracksContainer = () => { const { setLoading, user } = useAppState(); const { handleError } = useErrors(); const [state, setState] = useState({ tracks: [], genres: [], pagination: { currentPage: 1, totalItems: 0, pageSize: 20, }, searchOptions: { substr: '', genreIds: [], }, }); useAbortableEffect((status) => { setLoading(true); const countTracksReq = countTracks(); const getTracksRequest = fetchTacks(); const getGenresReq = fetchGenres(); Promise.all([countTracksReq, getTracksRequest, getGenresReq]) .then( ([ { data: totalItems }, { data: { value: tracks }, }, { data: { value: genres }, }, ]) => { if (!status.aborted) { setState({ ...state, tracks, genres, pagination: { ...state.pagination, totalItems }, }); } } ) .catch(handleError) .finally(() => setLoading(false)); }, []); const onSearch = debounce( () => { setLoading(true); const options = { $top: state.pagination.pageSize, substr: state.searchOptions.substr.replace(`'`, `''`), genreIds: state.searchOptions.genreIds, }; Promise.all([ fetchTacks(options), countTracks({ substr: options.substr, genreIds: options.genreIds, }), ]) .then(([{ data: { value: tracks } }, { data: totalItems }]) => setState({ ...state, tracks, pagination: { ...state.pagination, totalItems }, }) ) .catch(handleError) .finally(() => setLoading(false)); }, DEBOUNCE_TIMER, DEBOUNCE_OPTIONS ); const onSelectChange = (genres) => { setState({ ...state, searchOptions: { ...state.searchOptions, genreIds: genres.map((value) => parseInt(value, 10)), }, }); }; const onSearchChange = (event) => { setState({ ...state, searchOptions: { ...state.searchOptions, substr: event.target.value }, }); }; const onChangePage = (pageNumber) => { document.querySelector('section.ant-layout').scrollTo({ top: 0, left: 0, behavior: 'smooth' }); setLoading(true); const options = { $top: state.pagination.pageSize, substr: state.searchOptions.substr, genreIds: state.searchOptions.genreIds, $skip: (pageNumber - 1) * state.pagination.pageSize, }; fetchTacks(options) .then((response) => setState({ ...state, tracks: response.data.value, pagination: { ...state.pagination, currentPage: pageNumber }, }) ) .catch(handleError) .finally(() => setLoading(false)); }; const deleteTrack = (ID) => { setState({ ...state, tracks: state.tracks.filter(({ ID: curID }) => curID !== ID), }); }; const renderTracks = (tracks) => { const isEmployee = requireEmployee(user); const TrackComponent = isEmployee ? ManagedTrack : Track; return tracks.map((track) => { const isAlreadyOrdered = !isEmployee && track.alreadyOrdered; const onDeleteTrack = isEmployee && ((ID) => deleteTrack(ID)); return (