import React, { useState } from "react"; import { debounce } from "lodash"; import { Input, Col, Row, Select, Pagination } from "antd"; import { Track } from "./Track"; import "./TracksPage.css"; import { useAppState } from "../../hooks/useAppState"; import { useErrors } from "../../hooks/useErrors"; import { fetchTacks, countTracks, fetchGenres } from "../../api/calls"; import { useAbortableEffect } from "../../hooks/useAbortableEffect"; let counter = 0; 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, invoicedItems } = 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(); console.log("calling requests", counter++); 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, 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, invoicedItems) => tracks.map( ({ ID, name, composer, genre, unitPrice, alreadyOrdered, album }) => ( curID === ID)} onDeleteTrack={(ID) => deleteTrack(ID)} /> ) ); const trackElements = renderTracks(state.tracks, invoicedItems); const genreElements = renderGenres(state.genres); return ( <>
{trackElements}
); }; export { TracksContainer };