From c4b2f567725fb32bf1755e34a6f06c219d9befca Mon Sep 17 00:00:00 2001 From: Quantum Date: Mon, 14 Feb 2022 01:48:09 -0500 Subject: [PATCH] Add ability to navigate to date --- src/App.tsx | 69 +++++++++++++++++++++++++++++++++++++++++++++----- src/dates.ts | 3 +++ src/index.scss | 25 ++++++++++++++++++ 3 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 7cd666d..401fb8e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, {FormEvent} from 'react'; import {Calendar} from './Calendar'; -import {frSupportedYear, gregorianJDN, jdnFrench, Month} from './dates'; +import {endGregorian, frSupportedYear, gregorianJDN, jdnFrench, Month, startGregorian} from './dates'; type YearMonth = { year: number; @@ -21,6 +21,9 @@ function parseURL(): YearMonth | null { type AppState = YearMonth & { todayJDN: number, + goYear: string, + goMonth: string, + goDay: string, }; class App extends React.Component<{}, AppState> { @@ -35,6 +38,9 @@ class App extends React.Component<{}, AppState> { this.state = { ...(parseURL() || {year, month}), todayJDN, + goYear: today.getFullYear().toString(), + goMonth: (today.getMonth() + 1).toString(), + goDay: today.getDate().toString(), }; this.updateURL(); this.updateStateFromURL = this.updateStateFromURL.bind(this); @@ -60,6 +66,36 @@ class App extends React.Component<{}, AppState> { } } + changeField(field: keyof AppState, event: any) { + const change: Partial = {}; + change[field] = event.target.value; + this.setState(change); + } + + validYear() { + return /^-?\d+$/.test(this.state.goYear) && startGregorian.getFullYear() <= +this.state.goYear && + +this.state.goYear <= endGregorian.getFullYear(); + } + + 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(jdn); + this.setState({year, month}); + } + setState(state: any, callback?: () => void) { super.setState(state, () => { this.updateURL(); @@ -68,11 +104,30 @@ class App extends React.Component<{}, AppState> { } render() { - return { - this.setState({year, month}) - }}/>; + return <> + { + this.setState({year, month}); + }}/> + +
+

Go to a date

+
+ Gregorian Date + + + + +
+
+ ; } } diff --git a/src/dates.ts b/src/dates.ts index ea42eea..0916dde 100644 --- a/src/dates.ts +++ b/src/dates.ts @@ -107,6 +107,9 @@ export function jdnGregorian(jdn: number): Date { return new Date(year, month - 1, day); } +export const startGregorian = jdnGregorian(startJD); +export const endGregorian = jdnGregorian(frJDN(endYear, 13, frIsLeap(endYear) ? 6: 5)); + export function jdnFrench(jdn: number): FrenchDate { let lo = 0; let hi = leaps.length; diff --git a/src/index.scss b/src/index.scss index 25c4464..41a3552 100644 --- a/src/index.scss +++ b/src/index.scss @@ -6,6 +6,7 @@ @import 'bootstrap/scss/transitions'; @import 'bootstrap/scss/type'; @import 'bootstrap/scss/card'; +@import 'bootstrap/scss/forms'; @import './consts'; body { @@ -34,6 +35,30 @@ nav.navbar { } } +@include media-breakpoint-down(sm) { + .hide-small { + display: none; + } +} + +.navigate { + max-width: $calendar-width; + margin-top: $spacer; + @include make-container(); + + .go-year { + max-width: 7em; + } + + .go-month, .go-day { + max-width: 5em; + } + + .go-button { + max-width: 3em; + } +} + .main { max-width: $calendar-width; margin-top: $spacer;