instantjob-recruiter-client
Version:
a set of tools for creating an instantjob recruiter react client
252 lines (232 loc) • 8.28 kB
JSX
import React, {Component} from 'react'
import styled from 'styled-components'
import {connect} from 'react-redux'
import {browserHistory} from 'react-router'
import {
MdFlag, MdGroup, MdComment, MdArrowDropDown, MdMenu, MdTrendingUp, MdSettings, MdPowerSettingsNew,
} from 'react-icons/lib/md'
import ProfileImage from 'components/profile_image'
import InstantJob from 'components/instant_job'
import Hover from 'components/utils/hover'
import ViewportListener from 'components/viewport_listener'
import Chat from 'scenes/chat'
import store from 'common/store'
import auto_bind from 'common/auto_bind'
import {color, link} from 'common/styles'
import {action_logout} from 'common/authentication'
import {array_from_hash, array_contains} from 'common/utilities'
import {store_viewport} from 'actions/display'
const font_title = 20
const font_text = 12
class NavbarStatic extends Component {
constructor(props) {
super(props)
this.state = {
previously_extended: false,
}
auto_bind(this)
}
render() {
return (
<div style={{display: 'flex', flexDirection: 'column'}}>
<ViewportListener on_change={(viewport, scrollbar_size) => store.dispatch(store_viewport(viewport, scrollbar_size))}/>
<div style={styles.nav_bar}>
<div style={{display: 'flex', alignItems: 'center', height: 50}}>
<div style={styles.brand(true)}>
<InstantJob />
</div>
</div>
<CollapsibleLinks {...this.props} />
</div>
<div style={{display: 'flex', flexDirection: 'row', alignItems: 'stretch', position: 'absolute', top: 50, right: 0, left: 0, bottom: 0}}>
<div style={{zIndex: 0, overflow: 'auto', backgroundColor: 'white', flexGrow: 10000000, flexShrink: 1, display: 'flex', flexDirection: 'column', alignItems: 'stretch', justifyContent: 'flex-start'}}>
{this.props.children}
</div>
{array_contains(['xs', 'sm'], this.props.viewport) ? null : (
<Chat side_module />
)}
</div>
</div>
)
}
}
class CollapsibleLinks extends Component {
render() {
let tabs
switch (this.props.viewport) {
case 'xs':
case 'sm':
tabs = [
{path: "/", icon: MdTrendingUp, label: "Activité", is_active: (path) => (path.match(/^\/statistics\/?/) || path == '/')},
{path: "/deals", icon: MdFlag, label: "Missions", is_active: (path) => path.match(/^\/deals\/?/)},
{path: "/users", icon: MdGroup, label: "Répertoire", is_active: (path) => path.match(/^\/users\/?/)},
{path: "/messages", icon: MdComment, label: "Messagerie", is_active: (path) => path.match(/^\/messages\/?/)},
{path: "/settings", icon: MdSettings, label: "Paramètres", is_active: (path) => path.match(/^\/settings\/?/)},
]
return (
<Hover>
{(hover) => (
<div style={{display: 'flex', alignItems: 'center'}}>
<div style={{right: 0, marginLeft: 'auto', paddingRight: 15, color: color('white'), fontSize: 30}}>
<MdMenu/>
</div>
{hover ? (
<div style={styles.extended_menu}>
<div style={{display: 'flex', flexDirection: 'column'}}>
{tabs.map((tab) => <Tab key={tab.label} path={tab.path} icon={tab.icon} label={tab.label} active={tab.is_active(this.props.location.pathname)} extended/>)}
<div className="link" style={{...styles.profile, paddingTop: 8}} onClick={() => browserHistory.push('/settings')}>
<ProfileImage {...this.props.profile} hide_status />
<div style={{...styles.profile_infos, marginLeft: 8}}>
<div>{this.props.profile.first_name}</div>
<div style={{display: 'flex', fontSize: font_text}}>{this.props.profile.agency.name}</div>
</div>
<MdArrowDropDown style={{...styles.icons, fontSize: 22, marginLeft: 10}}/>
</div>
</div>
<div style={{fontSize: 20, color: 'white', right: 20, bottom: 15, position: 'absolute'}} dangerouslySetInnerHTML={{__html: this.props.logout_link}}></div>
</div>
) : null}
</div>
)}
</Hover>
)
case 'md':
case 'lg':
case 'xl':
tabs = [
{path: "/", icon: MdTrendingUp, label: "Activité", is_active: (path) => (path.match(/^\/statistics\/?/) || path == '/')},
{path: "/deals", icon: MdFlag, label: "Missions", is_active: (path) => path.match(/^\/deals\/?/)},
{path: "/users", icon: MdGroup, label: "Répertoire", is_active: (path) => path.match(/^\/users\/?/)},
{path: "/settings", icon: MdSettings, label: "Paramètres", is_active: (path) => path.match(/^\/settings\/?/)},
]
return (
<div style={{flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between'}}>
<div style={styles.tab_list}>
{tabs.map(({is_active, ...tab}, index) => <Tab {...tab} key={tab.label} index={index} active={is_active(this.props.location.pathname)}/>)}
</div>
<div style={styles.profile_container}>
<div style={styles.profile}>
<ProfileImage {...this.props.profile} large hide_status />
<div style={styles.profile_infos}>
<div>{this.props.profile.first_name}</div>
<div style={{display: 'flex', fontSize: font_text}}>{this.props.profile.agency.name}</div>
</div>
</div>
<Logout onClick={action_logout}>
<MdPowerSettingsNew />
</Logout>
</div>
</div>
)
default:
return <div></div>
}
}
}
const Tab = ({icon: Icon, extended, active, index, path, label}) => {
const tab_style = extended ? styles.extended_tab(active, index) : styles.tab(active, index)
return (
<TabContainer style={tab_style} onClick={() => browserHistory.push(path)}>
<Icon/>
<div style={{paddingLeft:10}}>
{label}
</div>
</TabContainer>
)
}
const TabContainer = styled.div`
${link}
`
const Navbar = connect(
(state) => {
return {
profile: state.profile,
viewport: state.display.viewport,
}
}
)(NavbarStatic)
const styles = {
nav_bar: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'stretch',
paddingLeft: 8,
backgroundColor: color('primary'),
height: 50,
zIndex: 2,
position: 'relative',
},
tab_list: {
display: 'flex',
flexDirection: 'row',
alignItems: 'flex-start',
},
tab(activated, index) {
return {
display: 'flex',
flexDirection: 'row',
marginLeft: index ? 40 : 20,
fontSize: font_title,
color: activated ? color('white') : color('black', 'normal', 0.5),
alignItems: 'center',
}
},
extended_tab(activated, index) {
return {
...this.tab(activated, index),
marginLeft: 8,
paddingTop: 8,
}
},
extended_menu: {
display: 'flex',
flexDirection:'row',
alignItems: 'flex-end',
paddingBottom: 15,
position: 'absolute',
left: 0,
top: 50,
right: 0,
flex: 1,
backgroundColor: color('primary'),
},
brand(activated) {
return {
display: 'flex',
color: activated ? color('white') : color('black', 'normal', 0.5),
marginRight: 8,
fontSize: 24,
}
},
profile_container: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
color: color('white'),
marginRight: 15,
},
profile: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
color: color('white'),
},
profile_infos: {
display: 'flex',
flexDirection: 'column',
fontSize: font_title,
marginLeft: 20,
},
icons: {
fontSize: 30,
marginLeft: 20,
},
}
const Logout = styled.div`
${link}
font-size: 25px;
color: white;
margin-left: 20px;
`
export default Navbar