import React from 'react'; import { withRouter, Link } from 'react-router-dom' import Flatpickr from "react-flatpickr"; import {shiftDays, shiftMonths, formatDay, formatDayShort, formatMonthYYYY, formatISO, isToday} from './date' class DatePicker extends React.Component { constructor(props) { super(props) this.handleKeyup = this.handleKeyup.bind(this) this.handleClick = this.handleClick.bind(this) this.state = {mode: 'closed'} } componentDidMount() { document.addEventListener('keyup', this.handleKeyup); document.addEventListener('mousedown', this.handleClick, false); } componentWillUnmount() { document.removeEventListener("keyup", this.handleKeyup); document.removeEventListener('mousedown', this.handleClick, false); } queryWithPeriod(period, dates) { const query = new URLSearchParams(window.location.search) query.set('period', period) query.delete('date'); query.delete('from'); query.delete('to') if (dates) { for (const key of Object.keys(dates)) { query.set(key, dates[key]) } } else { query.delete('date') } return query.toString() } handleKeyup(e) { const {query, history} = this.props if (e.key === 'ArrowLeft') { if (query.period === 'day') { const prevDate = formatISO(shiftDays(query.date, -1)) history.push({search: this.queryWithPeriod('day', {date: prevDate})}) } else if (query.period === 'month') { const prevMonth = formatISO(shiftMonths(query.date, -1)) history.push({search: this.queryWithPeriod('month', {date: prevMonth})}) } } else if (e.key === 'ArrowRight') { if (query.period === 'day') { const nextDate = formatISO(shiftDays(query.date, 1)) history.push({search: this.queryWithPeriod('day', {date: nextDate})}) } else if (query.period === 'month') { const nextMonth = formatISO(shiftMonths(query.date, 1)) history.push({search: this.queryWithPeriod('month', {date: nextMonth})}) } } } handleClick(e) { if (this.dropDownNode && this.dropDownNode.contains(e.target)) return; this.setState({mode: 'closed'}) } timeFrameText() { const {query, site} = this.props if (query.period === 'day') { if (isToday(site, query.date)) { return 'Today' } else { return formatDay(query.date) } } else if (query.period === '7d') { return 'Last 7 days' } else if (query.period === '30d') { return 'Last 30 days' } else if (query.period === '60d') { return 'Last 60 days' } else if (query.period === 'month') { return formatMonthYYYY(query.date) } else if (query.period === '6mo') { return 'Last 6 months' } else if (query.period === '12mo') { return 'Last 12 months' } else if (query.period === 'custom') { return `${formatDayShort(query.from)} - ${formatDayShort(query.to)}` } } renderArrow(period, prevDate, nextDate) { return (
) } renderArrows() { const {query} = this.props if (query.period === 'month') { const prevDate = formatISO(shiftMonths(query.date, -1)) const nextDate = formatISO(shiftMonths(query.date, 1)) return this.renderArrow('month', prevDate, nextDate) } else if (query.period === 'day') { const prevDate = formatISO(shiftDays(query.date, -1)) const nextDate = formatISO(shiftDays(query.date, 1)) return this.renderArrow('day', prevDate, nextDate) } } open() { this.setState({mode: 'open'}) } renderDropDown() { return (
this.dropDownNode = node}>
{this.timeFrameText()}
{this.renderDropDownContent()}
) } close() { this.setState({mode: 'closed'}) } renderLink(period, text) { const {query, site} = this.props let boldClass; if (query.period === 'day' && period === 'day') { boldClass = isToday(site, query.date) ? 'font-bold' : '' } else { boldClass = query.period === period ? 'font-bold' : '' } return ( {text} ) } renderDropDownContent() { if (this.state.mode === 'open') { return (
{ this.renderLink('day', 'Today') }
{ this.renderLink('7d', 'Last 7 days') } { this.renderLink('30d', 'Last 30 days') } { this.renderLink('60d', 'Last 60 days') }
{ this.renderLink('6mo', 'Last 6 months') } { this.renderLink('12mo', 'Last 12 months') }
this.setState({mode: 'calendar'}, this.openCalendar.bind(this))} className="block px-4 py-2 text-sm leading-tight hover:bg-gray-100 hover:text-gray-900 cursor-pointer">Custom range
) } else if (this.state.mode === 'calendar') { return this.calendar = calendar} className="invisible" onChange={this.setCustomDate.bind(this)} /> } } setCustomDate(dates) { if (dates.length === 2) { const [from, to] = dates this.props.history.push({search: this.queryWithPeriod('custom', {from: formatISO(from), to: formatISO(to)})}) } } openCalendar() { this.calendar && this.calendar.flatpickr.open() } render() { return (
{ this.renderArrows() } { this.renderDropDown() }
) } } export default withRouter(DatePicker)