diff --git a/common/src/dateJump/GregorianJumper.tsx b/common/src/dateJump/GregorianJumper.tsx new file mode 100644 index 0000000..252589e --- /dev/null +++ b/common/src/dateJump/GregorianJumper.tsx @@ -0,0 +1,43 @@ +import {DateJumperProps} from './base'; +import React from 'react'; +import {gregorianJDN, jdnGregorian} from '../gregorian'; + +export default function GregorianJumper({minJDN, maxJDN, todayJDN, onJump}: DateJumperProps): JSX.Element { + const {todayYear, todayMonth, todayDay, startYear, endYear} = React.useMemo(() => { + const [todayYear, todayMonth, todayDay] = jdnGregorian(todayJDN); + const [startYear] = jdnGregorian(minJDN); + const [endYear] = jdnGregorian(maxJDN); + return {todayYear, todayMonth, todayDay, startYear, endYear}; + }, [minJDN, maxJDN, todayJDN]); + + const [year, setYear] = React.useState(todayYear.toString()); + const [month, setMonth] = React.useState(todayMonth.toString()); + const [day, setDay] = React.useState(todayDay.toString()); + + const validYear = /^-?\d+$/.test(year) && startYear <= +year && +year <= endYear; + const validMonth = /^\d+$/.test(month) && 1 <= +month && +month <= 12; + const validDay = /^\d+$/.test(day) && 1 <= +day && +day <= 31; + + function goToGregorian(event: React.FormEvent) { + event.preventDefault(); + + if (!validYear || !validMonth || !validDay) + return; + + onJump(gregorianJDN(+year, +month, +day)); + } + + return
; +} diff --git a/common/src/dateJump/base.ts b/common/src/dateJump/base.ts new file mode 100644 index 0000000..958516f --- /dev/null +++ b/common/src/dateJump/base.ts @@ -0,0 +1,6 @@ +export type DateJumperProps = { + minJDN: number; + maxJDN: number; + todayJDN: number; + onJump: (jdn: number) => void; +}; \ No newline at end of file diff --git a/common/src/dateJump/index.ts b/common/src/dateJump/index.ts new file mode 100644 index 0000000..feb9e73 --- /dev/null +++ b/common/src/dateJump/index.ts @@ -0,0 +1,3 @@ +import GregorianJumper from './GregorianJumper'; + +export {GregorianJumper}; diff --git a/common/src/french/index.ts b/common/src/french/index.ts index 3061f5d..023dd3b 100644 --- a/common/src/french/index.ts +++ b/common/src/french/index.ts @@ -1,6 +1,5 @@ import data from './cal.json'; import ruralName from './rural-days.json'; -import {jdnGregorian} from '../gregorian'; // Month 13 is for the complementary days export type FrenchMonth = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13; @@ -145,9 +144,6 @@ export function dateRuralName(month: FrenchMonth, day: FrenchDay): { name: strin return {name, title}; } -export const startGregorian = jdnGregorian(frStartJD); -export const endGregorian = jdnGregorian(frEndJD); - export function frDateFormat({year, month, day}: { year: number, month: FrenchMonth, day: FrenchDay }): string { return `${dateName(month, day)} ${year}`; } diff --git a/frcal/src/App.tsx b/frcal/src/App.tsx index f863885..e833e7c 100644 --- a/frcal/src/App.tsx +++ b/frcal/src/App.tsx @@ -1,16 +1,9 @@ -import React, {FormEvent} from 'react'; +import React from 'react'; import {Calendar} from './Calendar'; -import { - endGregorian, - frEndJD, - FrenchMonth, - frSupportedYear, - jdnFrench, - startGregorian, - frStartJD, -} from '@common/french'; -import {dateJDN, gregorianJDN} from '@common/gregorian'; +import {FrenchMonth, frEndJD, frStartJD, frSupportedYear, jdnFrench} from '@common/french'; +import {dateJDN} from '@common/gregorian'; import {TimeOfDay} from './TimeOfDay'; +import {GregorianJumper} from '@common/dateJump'; type YearMonth = { year: number; @@ -31,9 +24,6 @@ function parseURL(): YearMonth | null { type AppState = YearMonth & { todayJDN: number, - goYear: string, - goMonth: string, - goDay: string, }; class App extends React.Component<{}, AppState> { @@ -41,16 +31,12 @@ class App extends React.Component<{}, AppState> { constructor(props: {}) { super(props); - const today = new Date(); - const todayJDN = dateJDN(today); + const todayJDN = dateJDN(new Date()); const {year, month} = jdnFrench(todayJDN); this.state = { ...(parseURL() || {year, month}), todayJDN, - goYear: today.getFullYear().toString(), - goMonth: (today.getMonth() + 1).toString(), - goDay: today.getDate().toString(), }; this.updateStateFromURL = this.updateStateFromURL.bind(this); } @@ -75,38 +61,10 @@ class App extends React.Component<{}, AppState> { } } - changeField(field: keyof AppState, event: any) { - this.setState({[field]: event.target.value}); - } - - validYear() { - return /^-?\d+$/.test(this.state.goYear) && startGregorian[0] <= +this.state.goYear && - +this.state.goYear <= endGregorian[0]; - } - - validMonth() { - return /^\d+$/.test(this.state.goMonth) && 1 <= +this.state.goMonth && +this.state.goMonth <= 12; - } - - validDay() { - return /^\d+$/.test(this.state.goDay) && 1 <= +this.state.goDay && +this.state.goDay <= 31; - } - - goToGregorian(event: FormEvent) { - event.preventDefault(); - - if (!this.validYear() || !this.validMonth() || !this.validDay()) - return; - - const jdn = gregorianJDN(+this.state.goYear, +this.state.goMonth, +this.state.goDay); - const {year, month} = jdnFrench(Math.min(Math.max(frStartJD, jdn), frEndJD)); - this.setState({year, month}); - } - setState(state: any, callback?: () => void) { super.setState(state, () => { this.updateURL(); - callback && callback(); + callback?.(); }); } @@ -114,6 +72,11 @@ class App extends React.Component<{}, AppState> { this.setState({todayJDN}); }; + goToJDN = (jdn: number) => { + const {year, month} = jdnFrench(Math.min(Math.max(frStartJD, jdn), frEndJD)); + this.setState({year, month}); + }; + render() { return <>