Usando componentes funcionales

This commit is contained in:
Daniel Cortes
2020-06-05 18:13:22 -04:00
parent 9f30c5c340
commit 7ede6effcc

View File

@@ -1,4 +1,4 @@
import React, {Fragment} from "react"; import React, {Fragment, useEffect, useState} from "react";
import queryString from "query-string"; import queryString from "query-string";
import {searchArtist, searchDisc, searchSong} from "../services/search_service"; import {searchArtist, searchDisc, searchSong} from "../services/search_service";
@@ -9,33 +9,24 @@ import {Tab, TabList, TabPanel, Tabs} from "react-tabs";
import {ReactComponent as DiscSVG} from "../svg/disc.svg"; import {ReactComponent as DiscSVG} from "../svg/disc.svg";
class CoverArt extends React.Component { const CoverArt = (props) => {
constructor(props) { const [loading, setLoading] = useState(true);
super(props);
this.state = {
loading: true
}
}
handleLoad = () => { const handleLoad = () => setLoading(false)
this.setState({loading: false})
};
render() { if (props.cover_art) {
if (this.props.cover_art) { if (loading) {
if (this.state.loading) { return (
return ( <Fragment>
<Fragment> <img src={props.cover_art.image} className={'coverart loading'} alt={props.alt} onLoad={handleLoad}/>
<img src={this.props.cover_art.image} className={'coverart loading'} alt={this.props.alt} onLoad={this.handleLoad}/> <DiscSVG className='coverart'/>
<DiscSVG className='coverart'/> </Fragment>
</Fragment> )
)
} else {
return <img src={this.props.cover_art.image} className={'coverart'} alt={this.props.alt}/>
}
} else { } else {
return <DiscSVG className='coverart'/> return <img src={props.cover_art.image} className={'coverart'} alt={props.alt}/>
} }
} else {
return <DiscSVG className='coverart'/>
} }
} }
@@ -48,336 +39,281 @@ const SearchPlaceholder = (props) => {
) )
} }
class SearchSong extends React.Component { const SearchSong = (props) => {
render() { const song = props.song;
const song = this.props.song; return (
return ( <li className='song'>
<li className='song'> <Link to={`/song/${song.id}`}>
<Link to={`/song/${song.id}`}> <div className='description'>
<div className='description'> <span>{song.title}</span>
<span>{song.title}</span> <span className='small'>{song.artist[0].name}</span>
<span className='small'>{song.artist[0].name}</span> </div>
</div> </Link>
</Link> </li>
</li> )
)
}
} }
class SearchSongs extends React.Component { const SearchSongs = (props) => {
constructor(props) { const [songs, setSongs] = useState(null);
super(props); const [paginate, setPaginate] = useState(null);
this.state = {songs: null, paginate: null, page: this.props.page ? this.props.page : 1} const [page, setPage] = useState(props.page ? props.page : 1);
useEffect(() => {
setSongs(null);
setPaginate(null);
loadSongs(props.query, page)
}, [props.query, page]);
const makeLink = page => `/search/song?query=${props.query}&page=${page}`;
const handlePageChange = page => {
setSongs(null);
setPage(page);
props.onPageChange(page);
} }
componentDidMount = _ => this.loadSongs(this.props.query, this.state.page); const loadSongs = (query, page) => {
componentDidUpdate = (prevProps, prevState) => {
if (prevProps.query !== this.props.query || prevState.page !== this.state.page) {
this.loadSongs(this.props.query, this.state.page)
if (prevState.page !== this.state.page) {
this.setState({songs: null})
} else {
this.setState({songs: null, paginate: null})
}
}
};
makeLink = page => `/search/song?query=${this.props.query}&page=${page}`;
handlePageChange = page => {
this.setState({songs: null, page: page})
this.props.onPageChange(page);
}
loadSongs = (query, page) => {
page = page ? page : 1; page = page ? page : 1;
searchSong(query, page).then((response) => { searchSong(query, page).then((response) => {
this.setState({ setSongs(response.recordings);
songs: response.recordings, setPaginate(response.paginate);
paginate: response.paginate
})
}) })
}; };
render = () => { let songsComponent = <SearchPlaceholder className='song'/>;
let songs = <SearchPlaceholder className='song'/>; if (songs) {
if (this.state.songs) { songsComponent = songs.map((song) => <SearchSong key={song.id} song={song}/>);
songs = this.state.songs.map((song) => <SearchSong key={song.id} song={song}/>); }
}
let paginate; let paginateComponent;
if (this.state.paginate) { if (paginate) {
const total = this.state.paginate.total; const total = paginate.total;
const currentPage = this.state.paginate.current_page; const currentPage = paginate.current_page;
const pageLimit = this.state.paginate.per_page; const pageLimit = paginate.per_page;
paginate = <Paginate totalRecords={total} pageLimit={pageLimit} currentPage={currentPage} pageNeighbours={2} onPageChanged={this.handlePageChange} makeLink={this.makeLink}/> paginateComponent = <Paginate totalRecords={total} pageLimit={pageLimit} currentPage={currentPage} pageNeighbours={2} onPageChanged={handlePageChange} makeLink={makeLink}/>
} }
return ( return (
<Fragment> <Fragment>
<ul className='entity_list'> <ul className='entity_list'>
{songs} {songsComponent}
</ul> </ul>
{paginate} {paginateComponent}
</Fragment> </Fragment>
) )
};
} }
class SearchDisc extends React.Component { const SearchDisc = (props) => {
getReleaseYear = (release) => { const disc = props.disc;
const releaseDate = new Date(release); return (
return ( <li className='disc'>
<span className='release-date'>{releaseDate.getFullYear()}</span> <Link to={`/disc/${disc.id}`}>
) <CoverArt cover_art={disc.cover_art} alt={`Cover del disco: ${disc.title}`}/>
} <div className='description'>
<span>{disc.title}</span>
render() { <span className='small'>{disc.artist[0].name}</span>
const disc = this.props.disc; </div>
return ( </Link>
<li className='disc'> </li>
<Link to={`/disc/${disc.id}`}> )
<CoverArt cover_art={disc.cover_art} alt={`Cover del disco: ${disc.title}`}/>
<div className='description'>
<span>{disc.title}</span>
<span className='small'>{disc.artist[0].name}</span>
</div>
</Link>
</li>
)
}
} }
class SearchDiscs extends React.Component { const SearchDiscs = (props) => {
constructor(props) { const [discs, setDiscs] = useState(null);
super(props); const [paginate, setPaginate] = useState(null);
this.state = {discs: null, paginate: null, page: this.props.page ? this.props.page : 1} const [page, setPage] = useState(null);
useEffect(_ => {
setDiscs(null)
setPaginate(null)
loadDiscs(props.query, page)
}, [props.query, page])
const makeLink = page => `/search/disc?query=${props.query}&page=${page}`;
const handlePageChange = page => {
setDiscs(null);
setPage(page);
props.onPageChange(page);
} }
componentDidMount = _ => this.loadDiscs(this.props.query, this.state.page); const loadDiscs = (query, page) => {
componentDidUpdate = (prevProps, prevState) => {
if (prevProps.query !== this.props.query || prevState.page !== this.state.page) {
this.loadDiscs(this.props.query, this.state.page)
if (prevState.page !== this.state.page) {
this.setState({discs: null})
} else {
this.setState({discs: null, paginate: null})
}
}
};
makeLink = page => `/search/disc?query=${this.props.query}&page=${page}`;
handlePageChange = page => {
this.setState({discs: null, page: page})
this.props.onPageChange(page);
}
loadDiscs = (query, page) => {
page = page ? page : 1; page = page ? page : 1;
searchDisc(query, page).then((response) => { searchDisc(query, page).then((response) => {
this.setState({ setDiscs(response.discs);
discs: response.discs, setPaginate(response.paginate);
paginate: response.paginate
})
}) })
}; };
render = () => { let discsComponent = <SearchPlaceholder className='disc'/>;
let discs = <SearchPlaceholder className='disc'/>; if (discs) {
if (this.state.discs) { discsComponent = discs.map((disc) => <SearchDisc key={disc.id} disc={disc}/>);
discs = this.state.discs.map((disc) => <SearchDisc key={disc.id} disc={disc}/>); }
}
let paginate; let paginateComponent;
if (this.state.paginate) { if (paginate) {
const total = this.state.paginate.total; const total = paginate.total;
const currentPage = this.state.paginate.current_page; const currentPage = paginate.current_page;
const pageLimit = this.state.paginate.per_page; const pageLimit = paginate.per_page;
paginate = <Paginate totalRecords={total} pageLimit={pageLimit} currentPage={currentPage} pageNeighbours={2} onPageChanged={this.handlePageChange} makeLink={this.makeLink}/> paginateComponent = <Paginate totalRecords={total} pageLimit={pageLimit} currentPage={currentPage} pageNeighbours={2} onPageChanged={handlePageChange} makeLink={makeLink}/>
} }
return ( return (
<Fragment> <Fragment>
<ul className='entity_list'> <ul className='entity_list'>
{discs} {discsComponent}
</ul> </ul>
{paginate} {paginateComponent}
</Fragment> </Fragment>
) )
};
} }
class SearchArtist extends React.Component { const SearchArtist = (props) => {
render() { const artist = props.artist;
const artist = this.props.artist; return (
return ( <li className='artist'>
<li className='artist'> <Link to={`/artist/${artist.id}`}>
<Link to={`/artist/${artist.id}`}> <span className='description'>
<span className='description'> <span>{artist.name}</span>
<span>{artist.name}</span> <span className='small'>{[artist.type, artist.country].filter(Boolean).join(' - ')}</span>
<span className='small'>{[artist.type, artist.country].filter(Boolean).join(' - ')}</span> </span>
</span> </Link>
</Link> </li>
</li> )
)
}
} }
class SearchArtists extends React.Component { const SearchArtists = (props) => {
constructor(props) { const [artists, setArtist] = useState(null);
super(props); const [paginate, setPaginate] = useState(null);
this.state = {artists: null, paginate: null, page: this.props.page ? this.props.page : 1} const [page, setPage] = useState(props.page ? props.page : 1);
useEffect(_ => {
setArtist(null)
setPaginate(null)
loadArtists(props.query, page)
}, [props.query, page])
const makeLink = page => `/search/artist?query=${props.query}&page=${page}`;
const handlePageChange = page => {
setArtist(null);
setPage(page);
props.onPageChange(page);
} }
componentDidMount = _ => this.loadArtists(this.props.query, this.state.page); const loadArtists = (query, page) => {
componentDidUpdate = (prevProps, prevState) => {
if (prevProps.query !== this.props.query || prevState.page !== this.state.page) {
this.loadArtists(this.props.query, this.state.page)
if (prevState.page !== this.state.page) {
this.setState({artists: null})
} else {
this.setState({artists: null, paginate: null})
}
}
};
makeLink = page => `/search/artist?query=${this.props.query}&page=${page}`;
handlePageChange = page => {
this.setState({artists: null, page: page})
this.props.onPageChange(page);
}
loadArtists = (query, page) => {
page = page ? page : 1; page = page ? page : 1;
searchArtist(query, page).then((response) => { searchArtist(query, page).then((response) => {
this.setState({ setArtist(response.artists);
artists: response.artists, setPaginate(response.paginate);
paginate: response.paginate
})
}) })
}; };
render = () => { let artistsContent = <SearchPlaceholder className='artist'/>;
let artists = <SearchPlaceholder className='artist'/>; if (artists) {
if (this.state.artists) { artistsContent = artists.map((artist) => <SearchArtist key={artist.id} artist={artist}/>);
artists = this.state.artists.map((artist) => <SearchArtist key={artist.id} artist={artist}/>);
}
let paginate;
if (this.state.paginate) {
const total = this.state.paginate.total;
const currentPage = this.state.paginate.current_page;
const pageLimit = this.state.paginate.per_page;
paginate = <Paginate totalRecords={total} pageLimit={pageLimit} currentPage={currentPage} pageNeighbours={2} onPageChanged={this.handlePageChange} makeLink={this.makeLink}/>
}
return (
<Fragment>
<ul className='entity_list'>
{artists}
</ul>
{paginate}
</Fragment>
)
};
}
class SearchTabs extends React.Component {
constructor(props) {
super(props);
this.handleSelect = this.handleSelect.bind(this);
} }
nameToIndex(name) { let paginateContent;
if (paginate) {
const total = paginate.total;
const currentPage = paginate.current_page;
const pageLimit = paginate.per_page;
paginateContent = <Paginate totalRecords={total} pageLimit={pageLimit} currentPage={currentPage} pageNeighbours={2} onPageChanged={handlePageChange} makeLink={makeLink}/>
}
return (
<Fragment>
<ul className='entity_list'>
{artistsContent}
</ul>
{paginateContent}
</Fragment>
)
}
const SearchTabs = (props) => {
const nameToIndex = (name) => {
if (name === 'artist') return 0 if (name === 'artist') return 0
if (name === 'disc') return 1 if (name === 'disc') return 1
if (name === 'song') return 2 if (name === 'song') return 2
else return 0; else return 0;
} }
indexToName(index) { const indexToName = (index) => {
if (index === 0) return 'artist' if (index === 0) return 'artist'
if (index === 1) return 'disc' if (index === 1) return 'disc'
if (index === 2) return 'song' if (index === 2) return 'song'
else return 'artist'; else return 'artist';
} }
handleSelect(index) { const handleSelect = (index) => {
if (this.props.onTabChanged) this.props.onTabChanged(this.indexToName(index)) props.onTabChanged(indexToName(index))
} }
handlePageChange = (who) => (index) => { const handlePageChange = (who) => (index) => props.onPageChange(who, index);
this.props.onPageChange(who, index);
}
render() { return (
return ( <Tabs selectedIndex={nameToIndex(props.selected)} onSelect={handleSelect}>
<Tabs selectedIndex={this.nameToIndex(this.props.selected)} onSelect={this.handleSelect}> <TabList className='tabs'>
<TabList className='tabs'> <Tab className='tab' selectedClassName='selected'>Artistas</Tab>
<Tab className='tab' selectedClassName='selected'>Artistas</Tab> <Tab className='tab' selectedClassName='selected'>Discos</Tab>
<Tab className='tab' selectedClassName='selected'>Discos</Tab> <Tab className='tab' selectedClassName='selected'>Canciones</Tab>
<Tab className='tab' selectedClassName='selected'>Canciones</Tab> </TabList>
</TabList> <TabPanel><SearchArtists query={props.query} page={props.page} onPageChange={handlePageChange('artist')}/></TabPanel>
<TabPanel><SearchArtists query={this.props.query} page={this.props.page} onPageChange={this.handlePageChange('artist')}/></TabPanel> <TabPanel><SearchDiscs query={props.query} page={props.page} onPageChange={handlePageChange('disc')}/></TabPanel>
<TabPanel><SearchDiscs query={this.props.query} page={this.props.page} onPageChange={this.handlePageChange('disc')}/></TabPanel> <TabPanel><SearchSongs query={props.query} page={props.page} onPageChange={handlePageChange('song')}/></TabPanel>
<TabPanel><SearchSongs query={this.props.query} page={this.props.page} onPageChange={this.handlePageChange('song')}/></TabPanel> </Tabs>
</Tabs> )
)
}
} }
export class Search extends React.Component { export const Search = (props) => {
constructor(props) { const parsedParams = queryString.parse(props.location.search);
super(props); const [who, setWho] = useState(props.match.params['who'] ? props.match.params['who'] : 'artist')
const parsed = queryString.parse(this.props.location.search); const [query, setQuery] = useState(parsedParams.query)
this.state = { const [page, setPage] = useState(!isNaN(+parsedParams.page) ? +parsedParams.page : 1)
who: this.props.match.params['who'] ? this.props.match.params['who'] : 'artist',
query: parsed.query,
page: !isNaN(+parsed.page) ? +parsed.page : 1,
};
console.log(this.state); const navigateTo = (who, query, page) => props.history.push(`/search/${who}?query=${query}&page=${page}`);
}
navigateToState = () => { const handleQueryChange = query => {
const link = `/search/${this.state.who}?query=${this.state.query}&page=${this.state.page}`; setQuery(query);
this.props.history.push(link); setPage(1);
navigateTo(who, query, 1)
}; };
handleQueryChange = query => { const handleTabChange = who => {
this.setState({query: query, page: 1}, this.navigateToState); setWho(who);
setPage(1)
navigateTo(who, query, 1)
}; };
handleTabChange = name => { const handlePageChange = (who, page) => {
this.setState({who: name, page: 1}, this.navigateToState); setWho(who);
}; setPage(page);
navigateTo(who, query, page);
handlePageChange = (who, page) => {
this.setState({who: who, page: page}, this.navigateToState);
window.scroll({left: 0, top: 0, behavior: 'smooth'}); window.scroll({left: 0, top: 0, behavior: 'smooth'});
}; };
render = () => ( const content = _ => {
if (query) {
return <SearchTabs query={query} onTabChanged={handleTabChange} onPageChange={handlePageChange} selected={who} page={page}/>
} else {
return null;
}
}
return (
<Fragment> <Fragment>
<h1>Búsqueda</h1> <h1>Búsqueda</h1>
<SearchBar query={this.state.query} onQueryChanged={this.handleQueryChange} history={this.props.history}/> <SearchBar query={query} onQueryChanged={handleQueryChange} history={props.history}/>
{this.state.query && {content()}
<SearchTabs query={this.state.query} onTabChanged={this.handleTabChange} onPageChange={this.handlePageChange} selected={this.state.who} page={this.state.page}/>
}
</Fragment> </Fragment>
); );
} }