Funcionalidad con tabs
Fue mas complicado de lo que pensaba, pero quedo bien y aprendi un poco mas en como pensar en react ~
This commit is contained in:
1
TODO.md
1
TODO.md
@@ -0,0 +1 @@
|
|||||||
|
Searchbar tendria que hacer callback de la query que se ejecuto, no ejecutarla el mismo
|
||||||
|
|||||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -3618,6 +3618,11 @@
|
|||||||
"shallow-clone": "^0.1.2"
|
"shallow-clone": "^0.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"clsx": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA=="
|
||||||
|
},
|
||||||
"co": {
|
"co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
@@ -10948,6 +10953,15 @@
|
|||||||
"workbox-webpack-plugin": "4.3.1"
|
"workbox-webpack-plugin": "4.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-tabs": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-HpySC29NN1BkzBAnOC+ajfzPbTaVZcSWzMSjk56uAhPC/rBGtli8lTysR4CfPAyEE/hfweIzagOIoJ7nu80yng==",
|
||||||
|
"requires": {
|
||||||
|
"clsx": "^1.1.0",
|
||||||
|
"prop-types": "^15.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-textarea-autosize": {
|
"react-textarea-autosize": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-6.1.0.tgz",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"react-json-view": "^1.19.1",
|
"react-json-view": "^1.19.1",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "3.4.1",
|
"react-scripts": "3.4.1",
|
||||||
|
"react-tabs": "^3.1.1",
|
||||||
"typescript": "^3.7.5"
|
"typescript": "^3.7.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import {searchArtist} from "../services/search_service";
|
|||||||
import SearchBar from "./SearchBar";
|
import SearchBar from "./SearchBar";
|
||||||
import Paginate from "./Paginate";
|
import Paginate from "./Paginate";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
|
import {Tab, TabList, TabPanel, Tabs} from "react-tabs";
|
||||||
|
|
||||||
|
|
||||||
class SearchArtist extends React.Component {
|
class SearchArtist extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
@@ -20,97 +22,143 @@ class SearchArtist extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchList extends React.Component {
|
class SearchArtists extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { artists: null, paginate: null, page: 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount = _ => this.loadArtists(this.props.query, this.state.page);
|
||||||
|
|
||||||
|
componentDidUpdate = (prevProps, prevState) => {
|
||||||
|
if(prevProps.query !== this.props.query || prevState.page !== this.state.page) {
|
||||||
|
this.setState({artists: null, paginate: null})
|
||||||
|
this.loadArtists(this.props.query, this.state.page)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
makeLink = page => `/search/artist?query=${this.state.query}&page=${page}`;
|
||||||
|
|
||||||
|
handlePageChange = page => {
|
||||||
|
this.setState({artists: null, page: page})
|
||||||
|
this.props.onPageChange(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadArtists = (query, page) => {
|
||||||
|
page = page ? page : 1;
|
||||||
|
|
||||||
|
searchArtist(query, page).then((response) => {
|
||||||
|
console.log(response);
|
||||||
|
this.setState({
|
||||||
|
artists: response.artists,
|
||||||
|
paginate: response.paginate
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
let artists = <p>Cargando...</p>;
|
||||||
|
if(this.state.artists) {
|
||||||
|
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) {
|
||||||
|
if(name === 'artist') return 0
|
||||||
|
if(name === 'disc') return 1
|
||||||
|
if(name === 'song') return 2
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexToName(index){
|
||||||
|
if(index === 0) return 'artist'
|
||||||
|
if(index === 1) return 'disc'
|
||||||
|
if(index === 2) return 'song'
|
||||||
|
else return 'artist';
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSelect(index) {
|
||||||
|
if (this.props.onTabChanged) this.props.onTabChanged(this.indexToName(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePageChange = (who) => (index) => {
|
||||||
|
this.props.onPageChange(who, index);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const artists = this.props.artists;
|
return (
|
||||||
return <ul className='entity_list'>
|
<Tabs selectedIndex={this.nameToIndex(this.props.selected)} onSelect={this.handleSelect}>
|
||||||
{artists.map((artist) => <SearchArtist key={artist.id} artist={artist}/>)}
|
<TabList>
|
||||||
</ul>
|
<Tab>Artistas</Tab>
|
||||||
|
<Tab>Discos</Tab>
|
||||||
|
<Tab>Canciones</Tab>
|
||||||
|
</TabList>
|
||||||
|
<TabPanel><SearchArtists query={this.props.query} onPageChange={this.handlePageChange('artist')}/></TabPanel>
|
||||||
|
<TabPanel><p>Discos</p></TabPanel>
|
||||||
|
<TabPanel><p>Canciones</p></TabPanel>
|
||||||
|
</Tabs>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Search extends React.Component {
|
export class Search extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.makeLink = this.makeLink.bind(this);
|
|
||||||
this.handlePageChange = this.handlePageChange.bind(this);
|
|
||||||
this.handleQueryChange = this.handleQueryChange.bind(this);
|
|
||||||
|
|
||||||
const parsed = queryString.parse(this.props.location.search);
|
const parsed = queryString.parse(this.props.location.search);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
artists: null,
|
who: this.props.match.params['who'] ? this.props.match.params['who'] : 'artist',
|
||||||
paginate: null,
|
|
||||||
query: parsed.query,
|
query: parsed.query,
|
||||||
page: !isNaN(+parsed.page) ? +parsed.page : 1,
|
page: !isNaN(+parsed.page) ? +parsed.page : 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
navigateToState = () => {
|
||||||
this.loadArtists(this.state.query, this.state.page);
|
const link = `/search/${this.state.who}?query=${this.state.query}&page=${this.state.page}`;
|
||||||
}
|
this.props.history.push(link);
|
||||||
|
};
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
handleQueryChange = query => {
|
||||||
if(prevState.query !== this.state.query || prevState.page !== this.state.page){
|
this.setState({query: query, page: 1}, this.navigateToState);
|
||||||
this.loadArtists(this.state.query, this.state.page);
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
makeLink(page) {
|
handleTabChange = name => {
|
||||||
return `/search?query=${this.state.query}&page=${page}`
|
this.setState({who: name, page: 1}, this.navigateToState);
|
||||||
}
|
};
|
||||||
|
|
||||||
handlePageChange(page) {
|
handlePageChange = (who, page) => {
|
||||||
this.props.history.push(this.makeLink(page));
|
this.setState({who: who, page: page}, this.navigateToState);
|
||||||
this.setState({page: page});
|
};
|
||||||
}
|
|
||||||
|
|
||||||
handleQueryChange(query) {
|
render = () => (
|
||||||
this.setState({query: query, page: 1});
|
<main>
|
||||||
}
|
<h1>Búsqueda</h1>
|
||||||
|
<SearchBar query={this.state.query} onQueryChanged={this.handleQueryChange} history={this.props.history}/>
|
||||||
render() {
|
<SearchTabs query={this.state.query} onTabChanged={this.handleTabChange} onPageChange={this.handlePageChange} selected={this.state.who} page={this.state.page}/>
|
||||||
let paginate = null;
|
</main>
|
||||||
let artists = null;
|
);
|
||||||
|
|
||||||
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}/>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.artists) {
|
|
||||||
artists = (
|
|
||||||
<Fragment>
|
|
||||||
<SearchList artists={this.state.artists}/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<main>
|
|
||||||
<h1>Busqueda</h1>
|
|
||||||
<SearchBar query={this.state.query} onQueryChanged={this.handleQueryChange} history={this.props.history}/>
|
|
||||||
{artists ? artists : <p>Loading...</p>}
|
|
||||||
{paginate && paginate}
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadArtists(query, page) {
|
|
||||||
if (!page) {
|
|
||||||
page = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
searchArtist(query, page).then((response) => {
|
|
||||||
this.setState({
|
|
||||||
artists: response.artists,
|
|
||||||
paginate: response.paginate,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ import ReactDOM from 'react-dom';
|
|||||||
import {Search} from './components/Search';
|
import {Search} from './components/Search';
|
||||||
import SearchBar from "./components/SearchBar";
|
import SearchBar from "./components/SearchBar";
|
||||||
|
|
||||||
|
import 'react-tabs/style/react-tabs.css'
|
||||||
import './styles/reset.css';
|
import './styles/reset.css';
|
||||||
import './styles/main.css';
|
import './styles/main.css';
|
||||||
|
|
||||||
import {Nav} from "./components/Nav";
|
import {Nav} from "./components/Nav";
|
||||||
|
|
||||||
import {BrowserRouter, Switch, Route} from "react-router-dom";
|
import {BrowserRouter, Switch, Route} from "react-router-dom";
|
||||||
@@ -30,7 +32,7 @@ const App = () => (
|
|||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Nav/>
|
<Nav/>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/search' component={Search}/>
|
<Route path='/search/:who?' component={Search}/>
|
||||||
<Route exact path='/' component={Main}/>
|
<Route exact path='/' component={Main}/>
|
||||||
<Route path='*' component={NoRoute}/>
|
<Route path='*' component={NoRoute}/>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
Reference in New Issue
Block a user