/** * Copyright (C) Paul Sarando * Distributed under the Eclipse Public License (http://www.eclipse.org/legal/epl-v10.html). */ import React from "react"; import { RivendellCalendarYear, RivendellDate, RivendellWeekdays, RivendellMonths, RivendellHolidays, RivendellRulesEnum, makeRivendellCalendarDates, } from "../RivendellReckoning"; import { fullYearDate, datesMatch } from "../Utils"; import DateCell, { dateKey } from "./DateCell"; import IntercalaryDay from "./IntercalaryDay"; import WeekDayHeaderCell, { addMonthFiller, addVerticalMonthFiller, } from "./WeekDayHeaderCell"; import "./tolkien-calendars.css"; import { LanguageEnum } from "./controls/LanguagePicker"; import { MonthLayoutEnum, VerticalLayoutFiller, } from "./controls/MonthViewLayout"; interface RivendellCalendarProps { caption?: string | boolean; className?: string; language?: LanguageEnum; monthView?: number; monthViewLayout?: MonthLayoutEnum; startDay?: number; yearView?: boolean; date?: Date; startDate?: Date; calendarRules?: RivendellRulesEnum; calendar?: RivendellCalendarYear; } interface RivendellDateProps { date: RivendellDate; today: Date; language: LanguageEnum; } interface RivendellYearProps { dates: RivendellDate[]; today: Date; language: LanguageEnum; } interface RivendellMonthProps extends RivendellYearProps { monthView: number; } const RivendellDateCell = ({ date, today, language }: RivendellDateProps) => { switch (date.day) { case "Yestarë": case "Enderë": case "Reformed Enderë": case "Mettarë": const holiday = RivendellHolidays[date.day]; return ( ); default: const month = RivendellMonths[date.month]; const weekday = RivendellWeekdays[date.weekDay]; const className = date.className === undefined ? month.className : date.className; return ( ); } }; const RivendellMonth = ({ monthView, dates, today, language, }: RivendellMonthProps) => { const weeks: React.JSX.Element[] = []; let week: React.JSX.Element[] = []; let i = 0, date = dates[i], endere = 1; for (; i < dates.length && date.month < monthView; i++, date = dates[i]) { // seek ahead to current month view } addMonthFiller(week, date.weekDay); for (; i < dates.length && monthView === date.month; i++, date = dates[i]) { week.push( ); if (date.weekDay === 5) { weeks.push({week}); week = []; } } if (monthView === 2) { date = dates[i]; for (; date.day === "Enderë"; i++, date = dates[i]) { week.push( ); if (date.weekDay === 5) { weeks.push({week}); week = []; } } } if (week.length > 0) { weeks.push({week}); } return weeks; }; const RivendellMonthVertical = ({ monthView, dates, today, language, }: RivendellMonthProps) => { const weeks = RivendellWeekdays.map(function (weekday) { const weekdayName = weekday[language]; return [ , ]; }); let i = 0, date = dates[i], endere = 1; for (; i < dates.length && date.month < monthView; i++, date = dates[i]) { // seek ahead to current month view } addVerticalMonthFiller(weeks, date.weekDay); for (; i < dates.length && monthView === date.month; i++, date = dates[i]) { weeks[date.weekDay].push( ); } if (monthView === 2) { date = dates[i]; for (; date.day === "Enderë"; i++, date = dates[i]) { weeks[date.weekDay].push( ); } } return weeks.map(function (week, i) { return {week}; }); }; const RivendellYear = ({ dates, today, language }: RivendellYearProps) => { const weeks: React.JSX.Element[] = []; let week: React.JSX.Element[] = [], endere = 1; addMonthFiller(week, dates[0].weekDay); for (let i = 0, date = dates[i]; i < dates.length; i++, date = dates[i]) { week.push( ); if (date.weekDay === 5) { weeks.push({week}); week = []; } } if (week.length > 0) { weeks.push({week}); } return weeks; }; const RivendellCalendar = (props: RivendellCalendarProps) => { const { caption, className, language = LanguageEnum.QUENYA, monthViewLayout = MonthLayoutEnum.HORIZONTAL, startDay = 22, yearView = false, } = props; const nextDate = props.date || new Date(); const [today, setToday] = React.useState(nextDate); const nextStartDate = props.startDate || fullYearDate(1, 2, startDay); const [startDate, setStartDate] = React.useState(nextStartDate); const nextRules = props.calendarRules || RivendellRulesEnum.TRADITIONAL; const [calendarRules, setCalendarRules] = React.useState(nextRules); const [calendar, setCalendar] = React.useState( () => props.calendar || makeRivendellCalendarDates(today, startDate, calendarRules) ); const updateToday = !datesMatch(today, nextDate); if (updateToday) { setToday(nextDate); } const updateStartDate = !datesMatch(startDate, nextStartDate); if (updateStartDate) { setStartDate(nextStartDate); } const updateRules = calendarRules !== nextRules; if (updateRules) { setCalendarRules(nextRules); } const updateCalendar = props.calendar && props.calendar !== calendar; if (updateCalendar || updateToday || updateStartDate || updateRules) { setCalendar( props.calendar || makeRivendellCalendarDates( nextDate, nextStartDate, nextRules ) ); } const { dates, todayRivendell } = calendar; const monthView = props.monthView === undefined ? todayRivendell.month : props.monthView; return ( {caption && ( )} {monthViewLayout === MonthLayoutEnum.VERTICAL && !yearView ? ( ) : ( {RivendellWeekdays.map(function (weekday) { let weekdayName = weekday[language]; return ( ); })} )} {yearView ? ( ) : monthViewLayout === MonthLayoutEnum.VERTICAL ? ( ) : ( )}
{caption === true ? "Rivendell Reckoning" : caption}
); }; RivendellCalendar.TRADITIONAL_RULES = RivendellRulesEnum.TRADITIONAL; RivendellCalendar.REFORMED_RULES = RivendellRulesEnum.REFORMED; RivendellCalendar.LANGUAGE_ENGLISH = LanguageEnum.ENGLISH; RivendellCalendar.LANGUAGE_QUENYA = LanguageEnum.QUENYA; RivendellCalendar.LANGUAGE_SINDARIN = LanguageEnum.SINDARIN; RivendellCalendar.MONTH_VIEW_VERTICAL = MonthLayoutEnum.VERTICAL; RivendellCalendar.MONTH_VIEW_HORIZONTAL = MonthLayoutEnum.HORIZONTAL; export default RivendellCalendar;