import React from 'react';
import './Calendar.scss';
import {
dateName,
Day,
decadeNames,
endYear,
frIsLeap,
frJDN,
jdnFrench,
jdnGregorian,
jdnLongCount,
Month,
monthName,
startYear
} from './dates';
type MonthProps = {
year: number;
month: Month;
};
type DateProps = MonthProps & {
day: Day;
};
function DecadeName({name}: { name: string }): JSX.Element {
return
{name}
;
}
function DayDetail({jdn}: { jdn: number }): JSX.Element {
return
{jdnGregorian(jdn).toDateString()}
{jdnLongCount(jdn)}
;
}
function NormalDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
const jdn = frJDN(year, month, day);
return
{day}
{decadeNames[(day - 1) % 10]}
;
}
function NormalMonth({year, month, todayJDN}: MonthProps & { todayJDN: number }): JSX.Element {
const decadeHeads = decadeNames.map(name => );
return
{decadeHeads}
{
Array.from(Array(3).keys()).map(i =>
{
Array.from(Array(10).keys()).map(j => <>
{j === 4 && }
>)
})
}
;
}
function ComplementaryDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
const jdn = frJDN(year, month, day);
return ;
}
function ComplementaryDays({year, todayJDN}: { year: number, todayJDN: number }): JSX.Element {
return {
Array.from(Array(frIsLeap(year) ? 6 : 5).keys()).map(i => <>
{i % 2 === 1 && }
>)
} ;
}
export type CalendarProps = MonthProps & {
todayJDN: number;
onSwitch?: (year: number, month: Month) => void,
};
type CalendarState = {
selecting: boolean,
yearStr: string,
};
export class Calendar extends React.Component {
selection: React.RefObject;
constructor(props: CalendarProps) {
super(props);
this.state = {
selecting: false,
yearStr: this.props.year.toString(),
};
this.selection = React.createRef();
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentDidMount() {
document.addEventListener('click', this.handleClickOutside, true);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, true);
}
private goToNormalized(year: number, month: number) {
if (month < 1) {
--year;
month += 13;
}
if (month > 13) {
++year;
month -= 13;
}
if (year < startYear) {
year = startYear;
month = 1;
} else if (year > endYear) {
year = endYear;
month = 13;
}
this.props.onSwitch && this.props.onSwitch(year, month as Month);
}
prevYear() {
this.goToNormalized(this.props.year - 1, this.props.month);
}
prevMonth() {
this.goToNormalized(this.props.year, this.props.month - 1);
}
nextYear() {
this.goToNormalized(this.props.year + 1, this.props.month);
}
nextMonth() {
this.goToNormalized(this.props.year, this.props.month + 1);
}
startSelection() {
this.setState({selecting: true});
}
handleClickOutside(event: any) {
if (this.state.selecting && this.selection.current && !this.selection.current.contains(event.target))
this.setState({selecting: false});
}
handleKeyUp(event: any) {
if (event.key === 'Escape')
this.setState({selecting: false});
}
monthChange(event: any) {
this.goToNormalized(this.props.year, event.target.value as Month);
}
yearChange(event: any) {
console.log(/^-?\d+/.test(event.target.value));
if (/^-?\d+/.test(event.target.value)) {
this.goToNormalized(+event.target.value, this.props.month);
}
this.setState({yearStr: event.target.value});
}
componentDidUpdate(prevProps: CalendarProps) {
if (prevProps.year !== this.props.year) {
const yearStr = this.props.year.toString();
if (this.state.yearStr !== yearStr) {
this.setState({
yearStr: yearStr,
});
}
}
}
goToToday() {
const {year, month} = jdnFrench(this.props.todayJDN);
this.goToNormalized(year, month);
this.setState({selecting: false});
}
render(): JSX.Element {
return
{!this.state.selecting &&
{this.props.month < 13 && monthName(this.props.month)} {this.props.year}
}
{this.state.selecting &&
}
{this.props.month < 13 &&
}
{this.props.month === 13 && }
;
}
}