/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ require('./listPage.less'); const React = require('react'); const createClass = require('create-react-class'); const _ = require('lodash'); const moment = require('moment'); const BrewItem = require('./brewItem/brewItem.jsx'); const USERPAGE_KEY_PREFIX = 'HOMEBREWERY-LISTPAGE'; const DEFAULT_SORT_TYPE = 'alpha'; const DEFAULT_SORT_DIR = 'asc'; const ListPage = createClass({ displayName : 'ListPage', getDefaultProps : function() { return { brewCollection : [ { title : '', class : '', brews : [] } ], navItems : <>, reportError : null }; }, getInitialState : function() { // HIDE ALL GROUPS UNTIL LOADED const brewCollection = this.props.brewCollection.map((brewGroup)=>{ brewGroup.visible = false; return brewGroup; }); return { filterString : this.props.query?.filter || '', filterTags : [], sortType : this.props.query?.sort || null, sortDir : this.props.query?.dir || null, query : this.props.query, brewCollection : brewCollection }; }, componentDidMount : function() { // SAVE TO LOCAL STORAGE WHEN LEAVING PAGE window.onbeforeunload = this.saveToLocalStorage; // LOAD FROM LOCAL STORAGE if(typeof window !== 'undefined') { const newSortType = (this.state.sortType ?? (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-SORTTYPE`) || DEFAULT_SORT_TYPE)); const newSortDir = (this.state.sortDir ?? (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-SORTDIR`) || DEFAULT_SORT_DIR)); this.updateUrl(this.state.filterString, newSortType, newSortDir); const brewCollection = this.props.brewCollection.map((brewGroup)=>{ brewGroup.visible = (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-VISIBILITY-${brewGroup.class}`) ?? 'true')=='true'; return brewGroup; }); this.setState({ brewCollection : brewCollection, sortType : newSortType, sortDir : newSortDir }); }; }, componentWillUnmount : function() { window.onbeforeunload = function(){}; }, saveToLocalStorage : function() { this.state.brewCollection.map((brewGroup)=>{ localStorage.setItem(`${USERPAGE_KEY_PREFIX}-VISIBILITY-${brewGroup.class}`, `${brewGroup.visible}`); }); localStorage.setItem(`${USERPAGE_KEY_PREFIX}-SORTTYPE`, this.state.sortType); localStorage.setItem(`${USERPAGE_KEY_PREFIX}-SORTDIR`, this.state.sortDir); }, renderBrews : function(brews){ if(!brews || !brews.length) return
No Brews.
; return _.map(brews, (brew, idx)=>{ return { this.updateUrl(this.state.filterString, this.state.sortType, this.state.sortDir, tag); }}/>; }); }, sortBrewOrder : function(brew){ if(!brew.title){brew.title = 'No Title';} const mapping = { 'alpha' : _.deburr(brew.title.trim().toLowerCase()), 'created' : moment(brew.createdAt).format(), 'updated' : moment(brew.updatedAt).format(), 'views' : brew.views, 'latest' : moment(brew.lastViewed).format() }; return mapping[this.state.sortType]; }, handleSortOptionChange : function(event){ this.updateUrl(this.state.filterString, event.target.value, this.state.sortDir); this.setState({ sortType : event.target.value }); }, handleSortDirChange : function(event){ const newDir = this.state.sortDir == 'asc' ? 'desc' : 'asc'; this.updateUrl(this.state.filterString, this.state.sortType, newDir); this.setState({ sortDir : newDir }); }, renderSortOption : function(sortTitle, sortValue){ return
{this.state.sortType == sortValue && }
; }, handleFilterTextChange : function(e){ this.setState({ filterString : e.target.value, }); this.updateUrl(e.target.value, this.state.sortType, this.state.sortDir); return; }, updateUrl : function(filterTerm, sortType, sortDir, filterTag=''){ const url = new URL(window.location.href); const urlParams = new URLSearchParams(url.search); urlParams.set('sort', sortType); urlParams.set('dir', sortDir); let filterTags = urlParams.getAll('tag'); if(filterTag != '') { if(filterTags.findIndex((tag)=>{return tag.toLowerCase()==filterTag.toLowerCase();}) == -1){ filterTags.push(filterTag); } else { filterTags = filterTags.filter((tag)=>{ return tag.toLowerCase() != filterTag.toLowerCase(); }); } } urlParams.delete('tag'); // Add tags to URL in the order they were clicked filterTags.forEach((tag)=>{ urlParams.append('tag', tag); }); // Sort tags before updating state filterTags.sort((a, b)=>{ return a.indexOf(':') - b.indexOf(':') != 0 ? a.indexOf(':') - b.indexOf(':') : a.toLowerCase().localeCompare(b.toLowerCase()); }); this.setState({ filterTags }); if(!filterTerm) urlParams.delete('filter'); else urlParams.set('filter', filterTerm); url.search = urlParams; window.history.replaceState(null, null, url); }, renderFilterOption : function(){ return
; }, renderTagsOptions : function(){ if(this.state.filterTags?.length == 0) return; return
{_.map(this.state.filterTags, (tag, idx)=>{ const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); return { this.updateUrl(this.state.filterString, this.state.sortType, this.state.sortDir, tag); }}>{matches[2]}; })}
; }, renderSortOptions : function(){ return
Sort by :
{this.renderSortOption('Title', 'alpha')} {this.renderSortOption('Created Date', 'created')} {this.renderSortOption('Updated Date', 'updated')} {this.renderSortOption('Views', 'views')} {/* {this.renderSortOption('Latest', 'latest')} */} {this.renderFilterOption()}
; }, getSortedBrews : function(brews){ const testString = _.deburr(this.state.filterString).toLowerCase(); brews = _.filter(brews, (brew)=>{ // Filter by user entered text const brewStrings = _.deburr([ brew.title, brew.description, brew.tags].join('\n') .toLowerCase()); const filterTextTest = brewStrings.includes(testString); // Filter by user selected tags let filterTagTest = true; if(this.state.filterTags.length > 0){ filterTagTest = Array.isArray(brew.tags) && this.state.filterTags?.every((tag)=>{ return brew.tags.findIndex((brewTag)=>{ return brewTag.toLowerCase() == tag.toLowerCase(); }) >= 0; }); } return filterTextTest && filterTagTest; }); return _.orderBy(brews, (brew)=>{ return this.sortBrewOrder(brew); }, this.state.sortDir); }, toggleBrewCollectionState : function(brewGroupClass) { this.setState((prevState)=>({ brewCollection : prevState.brewCollection.map( (brewGroup)=>brewGroup.class === brewGroupClass ? { ...brewGroup, visible: !brewGroup.visible } : brewGroup ) })); }, renderBrewCollection : function(brewCollection){ if(brewCollection == []) return

No Brews

; return _.map(brewCollection, (brewGroup, idx)=>{ return

{this.toggleBrewCollectionState(brewGroup.class);}}>{brewGroup.title || 'No Title'}

{brewGroup.visible ? this.renderBrews(this.getSortedBrews(brewGroup.brews)) : <>}
; }); }, render : function(){ return
{/**/} {this.props.navItems} {this.renderSortOptions()} {this.renderTagsOptions()}
{this.renderBrewCollection(this.state.brewCollection)}
; } }); module.exports = ListPage;