import React from 'react'; import './Calendar.scss'; import { formatJG, gregorianJDN, gregorianMonthDays, jdnGregorian, JulianDay, JulianMonth, monthName, weekdayNames, } from '@common/gregorian'; import {jdnTzolkin, formatTzolkin} from '@common/mayan'; import {jdnLongCount} from '@common/longCount'; import {jdnJulian} from '@common/julian'; import {frDateFormat, frEndJD, frStartJD, jdnFrench} from '@common/french'; import {useMobileTooltipProps} from '@common/ui/MobileTooltip'; import {MonthBasedCalendar} from '@common/ui/MonthBasedCalendar'; type JulianYear = number; type MonthProps = { year: JulianYear; month: JulianMonth; }; type DateProps = MonthProps & { day: JulianDay; }; function WeekdayName({name}: { name: string }): JSX.Element { return
{name}
; } function DayDetail({jdn}: { jdn: number }): JSX.Element { const lc = jdnLongCount(jdn); const mobile = useMobileTooltipProps(); return
JD {jdn}
J.{' '} {formatJG(jdnJulian(jdn))}
TZ{' '} {formatTzolkin(jdnTzolkin(jdn))}
{lc &&
LC{' '} {lc.join('.\u200b')}
} {jdn >= frStartJD && jdn <= frEndJD &&
FR{' '} {frDateFormat(jdnFrench(jdn))}
}
; } function Day({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element { const jdn = gregorianJDN(year, month, day); return
{day}
{weekdayNames[(jdn + 1) % 7]}
; } function Month({year, month, todayJDN}: MonthProps & { todayJDN: number }): JSX.Element { const decadeHeads = weekdayNames.map((name, i) => ); const firstJDN = gregorianJDN(year, month, 1); const firstWeekday = (firstJDN + 1) % 7; const daysTotal = gregorianMonthDays(year, month); return
{decadeHeads}
{ Array.from(Array(6).keys()).flatMap(i => { if (i * 7 - firstWeekday + 1 > daysTotal) return []; return Array.from(Array(7).keys()).map(j => { const day = i * 7 + j - firstWeekday + 1 as JulianDay; if (day < 1 || day > daysTotal) return
; return
; }); }) }
; } export class Calendar extends MonthBasedCalendar { override parseYear(year: string): JulianYear { return +year; } override parseMonth(month: string): JulianMonth { return +month as JulianMonth; } override yearToString(year: JulianYear): string { return year.toString(); } override monthToString(month: JulianMonth): string { return month.toString(); } private goToNormalized(year: number, month: number) { while (month < 1) { --year; month += 12; } while (month > 12) { ++year; month -= 12; } this.goTo(year, month as JulianMonth); } override prevYear = () => { this.goToNormalized(this.props.year - 1, this.props.month); }; override prevMonth = () => { this.goToNormalized(this.props.year, this.props.month - 1); }; override nextYear = () => { this.goToNormalized(this.props.year + 1, this.props.month); }; override nextMonth = () => { this.goToNormalized(this.props.year, this.props.month + 1); }; override isValidYear(year: string): boolean { return /^-?\d+/.test(year); } override jdnLookup(jdn: number): { year: JulianYear; month: JulianMonth } { const [year, month] = jdnGregorian(jdn); return {year, month}; } override monthName(year: JulianYear, month: JulianMonth): string { return `${monthName(month)} ${year}`; } override renderMonthOptions(): JSX.Element[] { return Array.from(Array(12).keys()).map(i => { const month = i + 1 as JulianMonth; return ; }); } override renderBody(): JSX.Element { return } }