UNPKG

instantjob-recruiter-client

Version:

a set of tools for creating an instantjob recruiter react client

221 lines (206 loc) 6.55 kB
import React, {Component} from 'react' import {connect} from 'react-redux' import classNames from 'classnames/bind' import Calendar from 'components/generic_calendar' import Tabbar from 'components/tabbar' import Button from 'components/utils/button' import TimePickers, { chunks_count_in_hour, chunk_length_in_minutes, chunks_count_in_day, get_periods, get_start_end, get_days_chunks, day_id, } from 'components/input_calendar/time_pickers' import moment from 'common/moment' import { for_all, array_from_hash, range, array_from_set, group_consecutive, set_from_array, exist, empty_set, map_hash, create_hash, } from 'common/utilities' import {color} from 'common/constants' import auto_bind from 'common/auto_bind' import store from 'common/store' import {dismiss_popover} from 'actions/display' import {remove_item, create_item, toggle_item_id} from 'reducers/base' import {tolerant_equal} from 'selectors/base' const cx = classNames.bind(require('styles/mission_period_picker.scss')) class MissionPeriodPicker extends Component { constructor(props) { super(props) auto_bind(this) this.update_initial_days(props.initial_events) let mode = "all" let identical_days = (day1, day2) => tolerant_equal(array_from_set(day1).sort(), array_from_set(day2).sort()) if (empty_set(this.initial_days) || group_consecutive(array_from_hash(this.initial_days), identical_days).length == 1) { mode = "day" } this.state = { active_days: map_hash(this.initial_days, () => true), day_active: set_from_array(range(chunks_count_in_day).filter( (chunk) => exist(array_from_hash(this.initial_days), (day) => day[chunk]) )), chunks: this.initial_days, mode, } this.all_time_pickers = {} } on_day_click(date) { this.setState(toggle_item_id(this.state, "active_days", day_id(date))) } on_create_period(start, end, paint) { let day_ids = [], current = moment(start) while (current.isBefore(end)) { day_ids.push(day_id(current)) current.add(1, 'day') } this.setState({active_days: { ...this.state.active_days, ...map_hash(set_from_array(day_ids), () => paint) }}) } flip(date, chunks, paint) { let chunks_range = create_hash(chunks, () => paint) switch (this.state.mode) { case "day": this.setState(({day_active}) => ({ day_active: { ...day_active, ...chunks_range, }, })) break case "all": let id = day_id(date) this.setState(({chunks, day_active}) => ({ chunks: { ...chunks, [id]: { ...(chunks[id] || day_active), ...chunks_range, }, }, })) break } } update_initial_days(events) { this.initial_days = get_days_chunks(events) } get_day_events() { return array_from_set(this.state.active_days).map((day) => ({ start: moment(day), end: moment(day).endOf('day'), full_days: true, })) } get_events() { let days = array_from_set(this.state.active_days) let events = [] let add_events = (day, active_chunks) => { get_periods(active_chunks).forEach(({start, end}) => { events.push({ ...get_start_end(day, start, end), full_days: false, }) }) } switch (this.state.mode) { case 'day': days.forEach((day) => add_events(day, this.state.day_active)) break case 'all': days.forEach((day) => add_events( day, this.state.chunks[day] || this.state.day_active, )) break } if (events.length == 0) { events = days.map((day) => ({ start: moment(day), end: moment(day).endOf('day'), full_days: true, })) } return events } on_save() { this.props.on_save(this.get_events()) } render_time_picker() { let common_props = { drag_color: color('primary', 'light'), flip: this.flip, } switch (this.state.mode) { case "day": return ( <TimePickers day_label={false} days={[{date: moment(), chunks: this.state.day_active}]} {...common_props} /> ) case "all": return ( <TimePickers days={array_from_set(this.state.active_days).map((day) => moment(day)).sort((a, b) => a.isAfter(b) ? 1 : (a.isSame(b) ? 0 : -1)).map((day) => ({ date: day, chunks: this.state.chunks[day_id(day)] || this.state.day_active, }))} {...common_props} /> ) } } set_mode(mode) { this.setState({mode}) } render() { return ( <div style={{display: 'flex', alignItems: 'stretch'}}> <div className={cx('mission-period-picker')}> <div className={cx('mission-period-picker__calendar')}> <Calendar hide_navigation events={{[color('primary')]: this.get_day_events()}} on_click={this.on_day_click} drag_color={color('primary')} on_drag_and_drop={this.on_create_period} /> </div> <div className={cx('mission-period-picker__time')}> <Tabbar tabs={[ { label: "Horaires uniques pour toute la mission", onClick: () => this.set_mode("day"), is_active: () => this.state.mode == "day", }, { label: "Jour par jour", onClick: () => this.set_mode("all"), is_active: () => this.state.mode == "all", }, ]} /> <div className={cx('mission-period-picker__time-pickers')}> {this.render_time_picker()} </div> <div className={cx('mission-period-picker__time-button')}> <Button onClick={this.on_save}> Enregistrer les dates de la mission </Button> </div> </div> </div> </div> ) } } MissionPeriodPicker.defaultProps = { initial_events: [], update_events: () => {}, } export default connect( (state, {mission_id}) => ({ initial_events: array_from_hash(state.missions.events) .filter(({calenderable_id, deleted_at}) => calenderable_id == mission_id && !deleted_at) }), )(MissionPeriodPicker)