import React, {Component} from 'react'; import Select from "react-virtualized-select"; import AlbumList from './AlbumList.js'; import {getQueryString} from './utils.js'; const fetchOpts = { credentials: 'same-origin' } export default class Selector extends Component { selects = [{type: 'artist', title: 'Artists'}, {type: 'year', title: 'Years'}, {type: 'genre', title: 'Genres'}, {type: 'publisher', title: 'Labels'}, {type: 'country', title: 'Countries'}, {type: 'type', title: 'Album types'}, {type: 'status', title: 'Album statuses'}]; constructor(props) { super(props); this.state = { albumList: {key:'', albums: [], error: false, hasMore: false}, filters: {}, filter: '', }; this.filterTimeout = null; } genAlbumListKey() { const {filter, filters} = this.state return `${filter}-${this.selects.map(({type}) => filters[type] ? filters[type].item : '').join('-')}` } loadAlbums = (page) => { const {filter, filters} = this.state const limit = 15; const offset = page * limit; const params = {filter, offset, limit:(limit+1)}; let key = (page === 0 ? this.genAlbumListKey() : this.state.albumList.key) for (const {type} of this.selects) { if (filters[type]) { params[type] = filters[type].item; } } return fetch(`/cat/album?${getQueryString(params)}`, fetchOpts) .then(res => (res.ok ? res.json() : Promise.reject({message:res.statusText}))) .then(data => { const hasMore = (data.length > limit) const albums = page === 0 ? data.slice(0, limit) : this.state.albumList.albums.concat(data.slice(0, limit)) const albumList = {key, albums, hasMore} this.setState({albumList}) return albums; }) .catch(error => { console.log(error) const albumList = {key, error} this.setState({albumList}) }) } componentDidMount() { this.loadAlbums(0) } componentDidUpdate(prevProps, prevState) { const {filters} = this.state; if (filters !== prevState.filters) { this.loadAlbums(0); } } handleFilterChange = (e) => { if (this.filterTimeout) { clearInterval(this.filterTimeout); } const filter = e.target.value; this.filterTimeout = setTimeout(() => { this.loadAlbums(0); }, 500); this.setState({filter}) } handleLoadOptions(cat, q, page) { const pageSize = 100 const params = {filter:q} params.offset = (page - 1) * pageSize; params.limit = pageSize; return fetch(`/cat/${cat}?${getQueryString(params)}`, fetchOpts) .then(res => (res.ok ? res.json() : Promise.reject({message:res.statusText}))) .then(options => ({options})) } handleSelectChange(cat, option) { const filters = Object.assign({}, this.state.filters, {[cat]: option}); this.setState({filters, filter: ''}) } _optionRenderer ({ focusedOption, focusOption, key, labelKey, option, selectValue, style, valueArray }) { const className = ['VirtualizedSelectOption'] if (option === focusedOption) { className.push('VirtualizedSelectFocusedOption') } if (option.disabled) { className.push('VirtualizedSelectDisabledOption') } if (valueArray && valueArray.indexOf(option) >= 0) { className.push('VirtualizedSelectSelectedOption') } if (option.className) { className.push(option.className) } const events = option.disabled ? {} : { onClick: () => selectValue(option), onMouseEnter: () => focusOption(option) } return (