/ src / modules / CategorySelector / CategorySelector.jsx
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