Created
October 8, 2018 17:41
-
-
Save steida/414fd78fb8cb1b387c7544539fcfee0a to your computer and use it in GitHub Desktop.
Get nearest day week date defined by week in month
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* @flow */ | |
import React from 'react'; | |
import { DayOfWeek, LocalDate, TemporalAdjusters } from 'js-joda'; | |
import { FormattedDate } from 'react-intl'; | |
import { ValidationError } from '../../common/lib/validation'; | |
import { connect } from 'react-redux'; | |
import { fields } from '../../common/lib/redux-fields'; | |
import { orderCourse } from '../../common/courses/actions'; | |
import { | |
Block, | |
Button, | |
ButtonOutline, | |
Input, | |
Space, | |
Text, | |
View, | |
} from '../app/components'; | |
// // TODO: Handle holidays somehow. Probably specific dates handled manually. | |
// // en.wikipedia.org/wiki/Public_holidays_in_the_Czech_Republic | |
// const csPublicHolidays = [ | |
// [1, 1], | |
// // Good Friday | |
// // Easter Monday | |
// [1, 5], | |
// [8, 5], | |
// [5, 7], | |
// [6, 7], | |
// [28, 9], | |
// [28, 10], | |
// [17, 11], | |
// [24, 12], | |
// [25, 12], | |
// [26, 12], | |
// ]; | |
const getWeekDayInMonth = (now, week, day) => now | |
.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)) | |
.plusWeeks(week - 1) | |
.plusDays(day - 1); | |
const getNearestCourseDate = (now, week, day) => { | |
const currentMonthDate = getWeekDayInMonth(now, week, day); | |
if (now.isBefore(currentMonthDate)) { | |
return currentMonthDate; | |
} | |
// Return next month course date. | |
return getWeekDayInMonth(now.plusMonths(1), week, day); | |
}; | |
const styles = { | |
orderForm: { | |
maxWidth: '21em', | |
}, | |
quantity: { | |
width: '8em', | |
}, | |
}; | |
type Props = { | |
didMount: bool, | |
fields: Object, | |
course: string, | |
week: number, // Week in month. | |
day: number, // Day in week. | |
orderCourse: Function, | |
orderError: Error, | |
}; | |
// Recommended date pattern: | |
// - Second week in a month is for beginners. | |
// - Third week, they can continue with native, then Este universal. Perfect. | |
let Order = ({ | |
didMount, | |
fields, | |
course, | |
week, | |
day, | |
orderCourse, | |
orderError, | |
}: Props) => { | |
const now = LocalDate.now(); | |
const date = getNearestCourseDate(now, week, day); | |
const onOrderClick = () => { | |
const { email, quantity } = fields.$values(); | |
orderCourse(course, date, email, quantity, () => { | |
alert('Počítám s vámi, detaily zašlu emailem.'); // eslint-disable-line no-alert | |
fields.$reset(); | |
}); | |
}; | |
return ( | |
<View> | |
<Block> | |
<Text> | |
Nejbližší termín:{' '} | |
<b> | |
<FormattedDate | |
day="numeric" | |
month="long" | |
value={date} | |
weekday={didMount ? 'long' : 'short'} | |
/> | |
{' '} | |
v Praze | |
</b> | |
</Text> | |
</Block> | |
{!fields.edit.value ? | |
<View> | |
<ButtonOutline onClick={() => fields.$setValue('edit', true)}> | |
Objednat | |
</ButtonOutline> | |
</View> | |
: | |
<View style={styles.orderForm}> | |
<Input | |
{...fields.email} | |
autoFocus | |
aria-invalid={ValidationError.isInvalid(orderError, 'email')} | |
label="Email" | |
maxLength={100} | |
type="text" | |
/> | |
<Input | |
{...fields.quantity} | |
// aria-invalid={ValidationError.isInvalid(error, 'name')} | |
label="Počet účastníků" | |
style={styles.quantity} | |
type="number" | |
/> | |
<Button onClick={onOrderClick}> | |
Objednat | |
</Button> | |
<Space x={1} /> | |
<ButtonOutline onClick={() => fields.$setValue('edit', false)}> | |
Zpět | |
</ButtonOutline> | |
</View> | |
} | |
</View> | |
); | |
}; | |
Order = fields(Order, { | |
path: props => [props.course], | |
fields: [ | |
'edit', | |
'email', | |
'quantity', | |
], | |
getInitialState: () => ({ | |
edit: false, | |
email: '', | |
quantity: '1', | |
showResponse: false, | |
}), | |
}); | |
// This is workaround. Node.js for some reason does not support 'long' weekday, | |
// so we have to render long weekday after the componentDidMount. | |
class OrderContainer extends React.Component { | |
state = { | |
didMount: false, | |
}; | |
componentDidMount() { | |
this.setState({ didMount: true }); // eslint-disable-line react/no-did-mount-set-state | |
} | |
render() { | |
return <Order {...this.props} didMount={this.state.didMount} />; | |
} | |
} | |
export default connect(state => ({ | |
orderError: state.courses.orderError, | |
}), { orderCourse })(OrderContainer); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment