/ src / modules / Dapps / Dapps.jsx
Dapps.jsx
 1  import React from 'react'
 2  import PropTypes from 'prop-types'
 3  import { debounce } from 'debounce'
 4  import DappList from '../../common/components/DappList'
 5  import CategoryHeader from '../CategoryHeader'
 6  import styles from './Dapps.module.scss'
 7  import { headerElements, getYPosition } from './Dapps.utils'
 8  import { DappState } from '../../common/data/dapp'
 9  
10  class Dapps extends React.Component {
11    static scanHeaderPositions() {
12      const headerPositions = headerElements().map(element => ({
13        id: element.id,
14        position: getYPosition(element),
15      }))
16      return headerPositions
17    }
18  
19    constructor(props) {
20      super(props)
21      this.state = {
22        currentCategoryIndex: 0,
23      }
24    }
25  
26    componentDidMount() {
27      this.boundScroll = debounce(this.handleScroll.bind(this), 150)
28      window.addEventListener('scroll', this.boundScroll)
29    }
30  
31    componentWillUnmount() {
32      window.removeEventListener('scroll', this.boundScroll)
33    }
34  
35    getCategories() {
36      const { dappState } = this.props
37      return [...dappState.categoryMap.keys()]
38    }
39  
40    handleScroll() {
41      const currentHeader = document.getElementById(this.currentCategory())
42      const headerPositions = Dapps.scanHeaderPositions()
43      const categories = this.getCategories()
44  
45      const newHeader = [...headerPositions]
46        .reverse()
47        .find(header => header.position < window.scrollY)
48  
49      if (!newHeader) {
50        return this.setState({ currentCategoryIndex: 0 })
51      }
52  
53      if (newHeader.id === currentHeader.id) {
54        return false
55      }
56  
57      const newIndex = categories.indexOf(newHeader.id)
58  
59      return this.setState({ currentCategoryIndex: newIndex })
60    }
61  
62    currentCategory() {
63      const { currentCategoryIndex } = this.state
64      const categories = this.getCategories()
65      return categories[currentCategoryIndex]
66    }
67  
68    isCurrentCategory(category) {
69      return category === this.currentCategory()
70    }
71  
72    render() {
73      const { dappState } = this.props
74      const categories = this.getCategories()
75  
76      return (
77        <div className={styles.list}>
78          {categories.map(category => (
79            <div key={category}>
80              <div id={category} className="category-header">
81                <CategoryHeader
82                  text={category}
83                  active={this.isCurrentCategory(category)}
84                />
85              </div>
86              <DappList dapps={dappState.getDappsByCategory(category)} />
87            </div>
88          ))}
89        </div>
90      )
91    }
92  }
93  
94  Dapps.propTypes = {
95    dappState: PropTypes.instanceOf(DappState).isRequired,
96  }
97  
98  export default Dapps