cruk-pattern-library-api
Version:
CRUK Pattern Library API
158 lines (142 loc) • 4.74 kB
JSX
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import Search from './search';
export default class MegaMenu extends Component {
constructor(props) {
super(props);
this.state = {
menuData: [],
enableSubmit: false
};
this.handleNav = this.handleNav.bind(this);
this.handleMenuItem = this.handleMenuItem.bind(this);
this.handleChange = this.handleChange.bind(this);
this.changeCallback = this.changeCallback.bind(this);
}
componentDidMount() {
if(this.props.loadData) {
this.setState({ menuData: this.props.loadData });
} else {
axios.get(this.props.url)
.then(res => {
const menuData = res.data;
this.setState({ menuData });
});
}
};
changeCallback = (e) => {
if (e.target.value !== '' ) {
this.setState({ enableSubmit: true });
}
};
handleMenuItem = (href, title) => {
const regex = /(twitter\.com|facebook\.com|addthis\.com|ebay)/;
const found = href.match(regex);
return (
<a
role='menuitem'
href={href}
className={!found || 'external'}
target={!found || '_blank'}
>
{title}
</a>
);
};
handleChange(e) {
document.querySelectorAll('.cr-menu__btn').forEach( el => el.checked = false );
document.getElementById(e.target.id).checked = true;
}
// @TODO: Refactor and extract checkbox to separate reusable component
handleNav = (data) => {
const menuItems= Object.keys(data)
.filter(obj => data[obj]['#title'] !== undefined )
.sort((a, b) => data[a]['#original_link'].weight - data[b]['#original_link'].weight)
.map(obj => {
const level1 = data[obj];
const menuBar = (
<div className="cr-menu__block">
<span />
{this.handleMenuItem(level1['#href'], level1['#title'])}
</div>
);
const menu = Object.keys(level1['#below'])
.filter(obj2 => level1['#below'][obj2]['#title'] !== undefined )
.sort((a, b) => level1['#below'][a]['#original_link'].weight - level1['#below'][b]['#original_link'].weight)
.map(
obj2 => {
const level2 = level1['#below'][obj2];
const menuItem = Object.keys(level2['#below'])
.filter(obj3 => level2['#below'][obj3]['#title'] !== undefined )
.sort((a, b) => level2['#below'][a]['#original_link'].weight - level2['#below'][b]['#original_link'].weight)
.map(
obj3 => {
const level3 = level2['#below'][obj3];
return (
<li key={level3['#title']}>
{this.handleMenuItem(level3['#href'], level3['#title'])}
</li>
);
}
);
return (
<li key={level2['#title']}>
{this.handleMenuItem(level2['#href'], level2['#title'])}
<ul>
{menuItem}
</ul>
</li>
);
}
);
return (
<li key={level1['#title']}>
{menuBar}
<ul role="menu">
{menu}
</ul>
</li>
);
});
return (
<nav className="cr-menu__nav">
<ul role="menubar" tabIndex="0">
{menuItems}
</ul>
</nav>
);
};
render() {
return (
<div className="cr-menu__wrapper">
<hr className="cr-menu__divider" />
<div className="cr-menu__inner">
<div className="cr-menu">
<input type="checkbox" id="cr-menu__btn--menu" className="cr-menu__btn" onClick={this.handleChange} />
<label htmlFor="cr-menu__btn--menu" className="cr-menu__label">Menu</label>
<input type="checkbox" id="cr-menu__btn--search" className="cr-menu__btn" onClick={this.handleChange}/>
<label htmlFor="cr-menu__btn--search" className="cr-menu__label">Search</label>
<div className="cr-menu__main-menu">
{this.handleNav(this.state.menuData)}
</div>
<div className="cr-menu__search">
<Search
label='Search'
submitCallback={this.state.enableSubmit}
changeCallback={this.changeCallback}
/>
</div>
</div>
</div>
</div>
);
}
}
MegaMenu.defaultProps = {
url: 'https://www.cancerresearchuk.org/cruk-navigation/menu-mdd/json',
};
MegaMenu.propTypes = {
loadData: PropTypes.array,
url: PropTypes.string,
};