UNPKG

react-styled-date-time-picker

Version:

```javascript import React, { Component } from 'react'; import DateTimePicker from 'react-styled-date-time-picker'; import { DateTime } from 'luxon';

294 lines (257 loc) 6.73 kB
// @flow /* eslint-disable import/no-unresolved, import/extensions, import/no-extraneous-dependencies, import/no-extraneous-dependencies */ import { Component } from 'react'; import styled, { type StyledComponent } from 'styled-components'; import { type DateTime } from 'luxon'; /** eslint-enable */ import Calendar from './Calendar'; import Time from './Time'; const Container: StyledComponent<{}, {}, HTMLDivElement> = styled.div` display: inline-block; width: 585px; padding: 12px 15px; border-radius: 3px; border: 1px solid #dfe0e4; margin-top: 20px; background: rgba(255, 255, 255, 1); `; const TimeContainer: StyledComponent<{ visible: boolean }, {}, HTMLDivElement> = styled.div` display: ${(props) => (props.visible ? 'flex' : 'none')}; align-items: center; justify-content: space-around; color: #f8f8f8; height: 250px; & div { user-select: none; } `; const Options: StyledComponent<{}, {}, HTMLDivElement> = styled.div` width: 100%; display: inline-block; margin-bottom: 4px; `; const TabButton: StyledComponent<{ active: boolean }, {}, HTMLButtonElement> = styled.button` float: left; width: 50%; color: ${(props) => (props.active ? '#f8f8f8' : '#00A15F')}; background-color: ${(props) => (props.active ? '#00A15F' : 'transparent')}; text-align: center; font-size: 16px; padding: 7px; border: 1px solid #00A15F; border-radius: 3px; cursor: pointer; user-select: none; &:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; } &:last-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } &:focus { outline: none; } `; const Tabs: StyledComponent<{}, {}, HTMLDivElement> = styled.div` margin-bottom: 11px; `; const Label: StyledComponent<{}, {}, HTMLDivElement> = styled.div` margin: 10px auto; margin-top: 0; text-align: center; `; const Button = styled.button` border: 0; outline: 0; cursor: pointer; line-height: 1; display: block; margin-top: 10px; width: 100%; background-color: #00A15F; padding: 12px 0; text-align: center; color: #f8f8f8; font-size: 16px; border-radius: 3px; flex: 0 0 250px; &:before { margin-right: 6px; } `; const messages = { ru: { date: 'Дата', time: 'Время', cancel: 'Отмена', ok: 'Ок', }, en: { date: 'Date', time: 'Time', cancel: 'Cancel', ok: 'OK', }, it: { date: 'Data', time: 'Tempo', cancel: 'Cancella', ok: 'OK', }, es: { date: 'Fecha', time: 'Tiempo', cancel: 'Cancelar', ok: 'OK', }, pt: { date: 'Data', time: 'Hora', cancel: 'Cancelar', ok: 'OK', }, }; type Messages = {| +date: string, +time: string, +cancel: string, +ok: string, |}; const getLabels = (lang: string = 'en'): Messages => messages[lang]; const Actions = styled.div` display: flex; margin: 0 -15px; `; const ButtonContainer = styled.div` display: flex; justify-content: center; flex: 0 0 50%; `; type Props = {| /* Called when user changes on the day of time */ +onChange: (dateFrom: DateTime, dateTo: DateTime) => void, /* Called when user click OK */ +onSelect: (dateFrom: DateTime, dateTo: DateTime) => void, /* Called when user closes the picker */ +onClose: () => void, +dateFrom: DateTime, +dateTo: DateTime, +language: Language, +label: string, +labelStyle?: $Shape<CSSStyleDeclaration>, |}; type State = {| +tab: 0 | 1, +dateFrom: DateTime, +dateTo: DateTime, |}; type DefaultProps = {| +label: string, +labelStyle: $Shape<CSSStyleDeclaration>, +language: string, +onChange: null, |}; class DateTimePicker extends Component<Props, State> { static defaultProps: DefaultProps = { language: 'en', onChange: null, label: '', labelStyle: {}, } constructor(props: Props) { super(props); const { dateFrom, dateTo, language } = props; this.state = { tab: 0, dateFrom: dateFrom.setLocale(language), dateTo: dateTo.setLocale(language), }; } selectDate = (): void => { const { onSelect, onClose } = this.props; const { dateFrom, dateTo } = this.state; onSelect(dateFrom, dateTo); onClose(); } switchTabOne = (): void => this.setState(() => ({ tab: 0 })); switchTabTwo = (): void => this.setState(() => ({ tab: 1 })); handleTimeFrom: ((dateFrom: DateTime) => void) = (dateFrom: DateTime) => { const { onChange, dateTo } = this.props; if (onChange) { onChange(dateFrom, dateTo); } this.setState(() => ({ dateFrom })); } handleTimeTo = (dateTo: DateTime): void => { const { onChange, dateFrom } = this.props; if (onChange) { onChange(dateFrom, dateTo); } this.setState(() => ({ dateTo })); } handleChange = (dateFrom: DateTime, dateTo: DateTime): void => { const { onChange } = this.props; if (onChange) { onChange(dateFrom, dateTo); } this.setState(() => ({ dateFrom, dateTo })); } handleConfirmClick = (dateFrom: DateTime, dateTo: DateTime): void => this.setState(() => ({ dateFrom, dateTo })); render(): React$Node { const { tab, dateFrom, dateTo, } = this.state; const { language, label, labelStyle, onClose, } = this.props; const labels = getLabels(language); return ( <Container> {label && <Label style={labelStyle}>{label}</Label>} <Options> <TabButton type="button" onClick={this.switchTabOne} active={tab === 0} > {labels.date} </TabButton> <TabButton type="button" onClick={this.switchTabTwo} active={tab === 1} > {labels.time} </TabButton> </Options> <Tabs> <Calendar language={language} visible={tab === 0} dateFrom={dateFrom} dateTo={dateTo} onChange={this.handleChange} switchTab={this.switchTabTwo} onSelect={this.handleConfirmClick} cancel={onClose} /> <TimeContainer visible={tab === 1}> <Time value={dateFrom} onChange={this.handleTimeFrom} /> <Time value={dateTo} onChange={this.handleTimeTo} /> </TimeContainer> </Tabs> <Actions> <ButtonContainer> <Button onClick={this.selectDate}>{labels.ok}</Button> </ButtonContainer> <ButtonContainer> <Button onClick={onClose}>{labels.cancel}</Button> </ButtonContainer> </Actions> </Container> ); } } export default DateTimePicker;