Skip to content

Instantly share code, notes, and snippets.

@steida
Created October 8, 2018 17:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steida/414fd78fb8cb1b387c7544539fcfee0a to your computer and use it in GitHub Desktop.
Save steida/414fd78fb8cb1b387c7544539fcfee0a to your computer and use it in GitHub Desktop.
Get nearest day week date defined by week in month
/* @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