CategorySelector.jsx
1 import React from 'react' 2 import PropTypes from 'prop-types' 3 import CategoryIcon from '../../common/components/CategoryIcon' 4 import ViewAll from '../../common/components/ViewAll' 5 import categories from '../../common/utils/categories' 6 import humanise from '../../common/utils/humanise' 7 import dropdownArrows from '../../common/assets/images/dropdown-arrows.svg' 8 import styles from './CategorySelector.module.scss' 9 10 class CategorySelector extends React.Component { 11 constructor(props) { 12 super(props) 13 this.state = { open: false } 14 this.toggle = this.toggle.bind(this) 15 this.updateCategory = this.updateCategory.bind(this) 16 this.container = React.createRef() 17 this.onClickSubmit = this.onClickSubmit.bind(this) 18 this.onClickHighestRanked = this.onClickHighestRanked.bind(this) 19 this.onClickRecentlyAdded = this.onClickRecentlyAdded.bind(this) 20 } 21 22 componentDidMount() { 23 this.closeOnBackgroundClick = this.closeOnBackgroundClick.bind(this) 24 document.addEventListener('click', this.closeOnBackgroundClick) 25 } 26 27 componentWillUnmount() { 28 document.removeEventListener('click', this.closeOnBackgroundClick) 29 } 30 31 onClickSubmit(e) { 32 const { onClickSubmit, onClickCloseDesktopMenu } = this.props 33 onClickCloseDesktopMenu() 34 onClickSubmit() 35 e.stopPropagation() 36 } 37 38 closeOnBackgroundClick(event) { 39 if (this.container.current.contains(event.target)) { 40 return 41 } 42 43 this.setState({ open: false }) 44 } 45 46 onClickHighestRanked(e) { 47 const { onClickCloseDesktopMenu } = this.props 48 onClickCloseDesktopMenu() 49 e.stopPropagation() 50 window.location.hash = 'highest-ranked' 51 } 52 53 onClickRecentlyAdded(e) { 54 const { onClickCloseDesktopMenu } = this.props 55 onClickCloseDesktopMenu() 56 e.stopPropagation() 57 window.location.hash = 'recently-added' 58 } 59 60 updateCategory(event) { 61 const { select } = this.props 62 select(event.target.value) 63 this.setState({ open: false }) 64 } 65 66 toggle() { 67 const { open } = this.state 68 this.setState({ open: !open }) 69 } 70 71 render() { 72 const { 73 category, 74 alwaysOpen, 75 className, 76 showLists, 77 showSubmitDApp, 78 } = this.props 79 let { open } = this.state 80 if (alwaysOpen === true) open = true 81 82 return ( 83 <div ref={this.container} className={className}> 84 <div 85 style={open ? { visible: 'block' } : { display: 'none' }} 86 className={styles.open} 87 > 88 <div className={styles.openHeader}> 89 <h2>Categories</h2> 90 <ViewAll size="small" /> 91 </div> 92 {categories.map(c => ( 93 <button 94 className={ 95 c.key === category 96 ? [styles.openButton, styles.selected].join(' ') 97 : styles.openButton 98 } 99 key={c.key} 100 type="button" 101 value={c.key} 102 onClick={this.updateCategory} 103 > 104 <CategoryIcon category={c.key} /> 105 {c.value} 106 </button> 107 ))} 108 109 {showLists && ( 110 <> 111 <div className={`${styles.openHeader} ${styles.spacing}`}> 112 <h2>Lists</h2> 113 </div> 114 <button 115 className={styles.openButton} 116 type="button" 117 onClick={this.onClickHighestRanked} 118 > 119 <svg 120 width="18" 121 height="17" 122 viewBox="0 0 18 17" 123 fill="none" 124 xmlns="http://www.w3.org/2000/svg" 125 > 126 <path 127 d="M8.07764 0.702201C8.42034 -0.116037 9.57966 -0.116039 9.92236 0.7022L11.555 4.60017C11.6992 4.9444 12.023 5.1797 12.395 5.21045L16.6066 5.55862C17.4907 5.6317 17.849 6.73427 17.1767 7.31306L13.974 10.0703C13.6912 10.3138 13.5675 10.6945 13.6532 11.0578L14.6235 15.1709C14.8272 16.0343 13.8893 16.7157 13.1311 16.2552L9.51914 14.0613C9.20016 13.8676 8.79984 13.8676 8.48087 14.0613L4.86889 16.2552C4.11068 16.7157 3.17278 16.0343 3.37647 15.1709L4.34682 11.0578C4.43251 10.6945 4.30881 10.3138 4.02598 10.0703L0.823298 7.31306C0.15101 6.73427 0.509255 5.6317 1.39335 5.55862L5.60504 5.21045C5.97698 5.1797 6.30084 4.9444 6.44502 4.60017L8.07764 0.702201Z" 128 fill="black" 129 /> 130 </svg> 131 {'Highest rated'} 132 </button> 133 <button 134 className={styles.openButton} 135 type="button" 136 onClick={this.onClickRecentlyAdded} 137 > 138 <svg 139 width="18" 140 height="18" 141 viewBox="0 0 18 18" 142 fill="none" 143 xmlns="http://www.w3.org/2000/svg" 144 > 145 <path 146 fillRule="evenodd" 147 clipRule="evenodd" 148 d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18ZM9.75 3.375C9.75 2.75368 9.24632 2.25 8.625 2.25C8.00368 2.25 7.5 2.75368 7.5 3.375V8.00368C7.5 8.69987 7.77656 9.36755 8.26884 9.85983L11.2045 12.7955C11.6438 13.2348 12.3562 13.2348 12.7955 12.7955C13.2348 12.3562 13.2348 11.6438 12.7955 11.2045L9.85983 8.26884C9.78951 8.19852 9.75 8.10314 9.75 8.00368V3.375Z" 149 fill="black" 150 /> 151 </svg> 152 {'Recently added'} 153 </button> 154 </> 155 )} 156 157 {showSubmitDApp && ( 158 <button 159 className={`${styles.openButton} ${styles.submitDapp}`} 160 type="button" 161 onClick={this.onClickSubmit} 162 > 163 <svg 164 width="20" 165 height="20" 166 viewBox="0 0 20 20" 167 fill="none" 168 xmlns="http://www.w3.org/2000/svg" 169 > 170 <path 171 fillRule="evenodd" 172 clipRule="evenodd" 173 d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20ZM10 4C10.5523 4 11 4.44772 11 5V8.5C11 8.77614 11.2239 9 11.5 9H15C15.5523 9 16 9.44772 16 10C16 10.5523 15.5523 11 15 11H11.5C11.2239 11 11 11.2239 11 11.5V15C11 15.5523 10.5523 16 10 16C9.44771 16 9 15.5523 9 15V11.5C9 11.2239 8.77614 11 8.5 11H5C4.44771 11 4 10.5523 4 10C4 9.44772 4.44772 9 5 9H8.5C8.77614 9 9 8.77614 9 8.5V5C9 4.44771 9.44772 4 10 4Z" 174 fill="black" 175 /> 176 </svg> 177 {'Submit a ÐApp'} 178 </button> 179 )} 180 </div> 181 182 <button 183 style={open ? { visibility: 'hidden' } : { visibility: 'visible' }} 184 className={[styles.closed, styles[category]].join(' ')} 185 type="button" 186 onClick={this.toggle} 187 > 188 <div className={styles.closedText}> 189 {category && <CategoryIcon category={category} />} 190 {category ? humanise(category) : 'Choose category'} 191 </div> 192 <img src={dropdownArrows} alt="Toggle category selector" /> 193 </button> 194 </div> 195 ) 196 } 197 } 198 199 CategorySelector.propTypes = { 200 category: PropTypes.string, 201 select: PropTypes.func.isRequired, 202 alwaysOpen: PropTypes.bool, 203 className: PropTypes.string, 204 showLists: PropTypes.bool, 205 showSubmitDApp: PropTypes.bool, 206 onClickSubmit: PropTypes.func, 207 onClickCloseDesktopMenu: PropTypes.func, 208 } 209 210 CategorySelector.defaultProps = { 211 category: null, 212 className: '', 213 alwaysOpen: false, 214 showLists: false, 215 showSubmitDApp: false, 216 onClickSubmit: null, 217 onClickCloseDesktopMenu: null, 218 } 219 220 export default CategorySelector