diff --git a/src/chronology/ui/DateConverterForm.sass b/src/chronology/ui/DateConverterForm.sass new file mode 100644 index 000000000..bb2d2a28d --- /dev/null +++ b/src/chronology/ui/DateConverterForm.sass @@ -0,0 +1,28 @@ +.date_converter + padding-top: 50px + padding-bottom: 20px + +.section-row + align-items: stretch + border-bottom: 1px grey solid + padding-top: 10px + + .even + .section-title + + .odd + .section-title + +.section-row:last-child + border-bottom: none + +.section-title + writing-mode: vertical-rl + transform: rotate(180deg) + text-align: center + font-family: Arial, Helvetica, sans-serif + font-size: 80% + letter-spacing: 1px + +.section-fields + padding-left: 15px diff --git a/src/chronology/ui/DateConverterForm.tsx b/src/chronology/ui/DateConverterForm.tsx index 970770afe..5210391d2 100644 --- a/src/chronology/ui/DateConverterForm.tsx +++ b/src/chronology/ui/DateConverterForm.tsx @@ -1,103 +1,200 @@ import React, { useState } from 'react' +import { + Form, + FormGroup, + FormControl, + Row, + Col, + FormCheck, + FormLabel, + Popover, +} from 'react-bootstrap' +import DateConverter from 'chronology/domain/DateConverter' +import HelpTrigger from 'common/HelpTrigger' +import { sections, Field } from 'chronology/ui/DateConverterFormFieldData' +import './DateConverterForm.sass' +import { Markdown } from 'common/Markdown' -const fields = [ - { name: 'year', type: 'number', placeholder: 'Year', required: true }, - { name: 'bcYear', type: 'number', placeholder: 'BC Year' }, - { name: 'month', type: 'number', placeholder: 'Month', required: true }, - { name: 'day', type: 'number', placeholder: 'Day', required: true }, - { name: 'weekDay', type: 'number', placeholder: 'Week Day', required: true }, - { name: 'cjdn', type: 'number', placeholder: 'CJDN', required: true }, - { - name: 'lunationNabonassar', - type: 'number', - placeholder: 'Lunation Nabonassar', - required: true, - }, - { - name: 'seBabylonianYear', - type: 'number', - placeholder: 'SE Babylonian Year', - required: true, - }, - { - name: 'seMacedonianYear', - type: 'number', - placeholder: 'SE Macedonian Year', - }, - { name: 'seArsacidYear', type: 'number', placeholder: 'SE Arsacid Year' }, - { - name: 'mesopotamianMonth', - type: 'number', - placeholder: 'Mesopotamian Month', - required: true, - }, - { name: 'mesopotamianDay', type: 'number', placeholder: 'Mesopotamian Day' }, - { - name: 'mesopotamianMonthLength', - type: 'number', - placeholder: 'Mesopotamian Month Length', - }, - { name: 'ruler', type: 'text', placeholder: 'Ruler' }, - { name: 'regnalYear', type: 'number', placeholder: 'Regnal Year' }, -] +const description = `The project uses a date converter that is based on the converter developed by [Robert H. van Gent](https://webspace.science.uu.nl/~gent0113/babylon/babycal_converter.htm). +The form below presents a dedicated interface designed for users who need to convert dates between different ancient calendar systems. Users can choose from three different input scenarios for conversion: + +- **Modern Date**: For conversion related to contemporary dates. +- **Seleucid (Babylonian) Date**: For dates in the Seleucid or Babylonian calendar. +- **Nabonassar Date**: For dates in the Nabonassar calendar system. + +Each section of the form is dynamically updating based on the selected scenario. Fields that are relevant to the chosen scenario are highlighted for user convenience.` function DateForm(): JSX.Element { - const initialFormData = fields.reduce((acc, field) => { - acc[field.name] = '' - return acc - }, {}) + const dateConverter = new DateConverter() + const [formData, setFormData] = useState(dateConverter.calendar) + const [scenario, setScenario] = useState('setToModernDate') - /* ToDo: - Implement. - 1. Switch between scenarios. - 2. When a scenario is selected, only the inputs that are relevant should remain active. + const handleChange = (event) => { + const { name, value } = event.target + const _formData = { ...formData, [name]: value } + const { + year, + month, + day, + ruler, + regnalYear, + seBabylonianYear, + mesopotamianMonth, + mesopotamianDay, + } = _formData + const setSeBabylonianDateArgs = [ + seBabylonianYear, + mesopotamianMonth, + mesopotamianDay, + ] + const setMesopotamianDateArgs = [ + ruler, + regnalYear, + mesopotamianMonth, + mesopotamianDay, + ] + if (scenario === 'setToModernDate') { + dateConverter.setToModernDate( + year as number, + month as number, + day as number + ) + } else if ( + scenario === 'setSeBabylonianDate' && + !setSeBabylonianDateArgs.includes(undefined) + ) { + dateConverter.setSeBabylonianDate( + seBabylonianYear as number, + mesopotamianMonth as number, + mesopotamianDay as number + ) + } else if ( + scenario === 'setMesopotamianDate' && + !setMesopotamianDateArgs.includes(undefined) + ) { + dateConverter.setMesopotamianDate( + ruler as string, + regnalYear as number, + mesopotamianMonth as number, + mesopotamianDay as number + ) + } + setFormData({ ...dateConverter.calendar }) + } - Scenarios: - - * setToModernDate(year: number, month: number, day: number) - - * setSeBabylonianDate( - seBabylonianYear: number, - mesopotamianMonth: number, - mesopotamianDay: number - ) - - * setMesopotamianDate( - ruler: string, - regnalYear: number, - mesopotamianMonth: number, - mesopotamianDay: number - ) + const handleScenarioChange = (_scenario) => { + setScenario(_scenario) + } - */ + const fieldIsActive = (fieldName) => { + switch (scenario) { + case 'setToModernDate': + return ['year', 'month', 'day'].includes(fieldName) + case 'setSeBabylonianDate': + return [ + 'seBabylonianYear', + 'mesopotamianMonth', + 'mesopotamianDay', + ].includes(fieldName) + case 'setMesopotamianDate': + return [ + 'ruler', + 'regnalYear', + 'mesopotamianMonth', + 'mesopotamianDay', + ].includes(fieldName) + default: + return false + } + } + const activeStyle = { backgroundColor: '#f9ffcf' } - const [formData, setFormData] = useState(initialFormData) + function getField(field: Field, index: number): JSX.Element { + return ( + + + {field.placeholder}{' '} + + {field.help} + + } + /> + + + + ) + } + + function getSection( + title: string, + fields: Field[], + index: number + ): JSX.Element { + return ( + + +
{title}
+ + + + {fields.map((field, fieldIndex) => getField(field, fieldIndex))} + + +
+ ) + } - const handleChange = (e) => { - const { name, value } = e.target - setFormData((prevState) => ({ ...prevState, [name]: value })) + const scenarioLabels = { + setToModernDate: 'Modern date', + setSeBabylonianDate: 'Seleucid (Babylonian) date', + setMesopotamianDate: 'Nabonassar date', } - const handleSubmit = (e) => { - e.preventDefault() - console.log(formData) + function getControls(): JSX.Element { + return ( + + ) } return ( -
- {fields.map((field) => ( - - ))} - -
+ <> + + + +
+ {sections.map(({ title, fields }, index) => + getSection(title, fields, index) + )} +
+ + {getControls()} +
+ ) } diff --git a/src/chronology/ui/DateConverterFormFieldData.ts b/src/chronology/ui/DateConverterFormFieldData.ts new file mode 100644 index 000000000..193f06d00 --- /dev/null +++ b/src/chronology/ui/DateConverterFormFieldData.ts @@ -0,0 +1,133 @@ +const generalInformationFields = [ + { + name: 'year', + type: 'number', + placeholder: 'Year', + required: true, + help: + 'The modern (Gregorian) CE year. BCE years are displayed in negative numbers, e.g. -310 for 311 BCE.', + }, + { + name: 'bcYear', + type: 'number', + placeholder: 'BCE Year', + help: 'The modern (Gregorian) BCE year, if before CE.', + }, + { + name: 'month', + type: 'number', + placeholder: 'Month', + required: true, + help: 'The modern (Gregorian) month as a number from 1 to 12.', + }, + { + name: 'day', + type: 'number', + placeholder: 'Day', + required: true, + help: 'The modern (Gregorian) day of the month as a number from 1 to 31.', + }, + { + name: 'weekDay', + type: 'number', + placeholder: 'Week Day', + required: true, + help: + 'The modern (Gregorian) day of the week as a number from 1 (Monday) to 7 (Sunday).', + }, +] + +const specializedDateInformationFields = [ + { + name: 'cjdn', + type: 'number', + placeholder: 'CJDN', + required: true, + help: + 'Chronological Julian Day Number, a continuous count of days since the beginning of the Julian Period (November 24, 4714 BCE in the proleptic Gregorian calendar).', + }, + { + name: 'lunationNabonassar', + type: 'number', + placeholder: 'Lunation Nabonassar', + help: + 'Lunation following the Nabonassar (Nabû-nāṣir, 747-734 BCE) Era. Begins on Wednesday, February 26, 747 BCE.', + required: true, + }, +] + +const seleucidEraInformationFields = [ + { + name: 'seBabylonianYear', + type: 'number', + placeholder: 'SE Babylonian Year', + required: true, + help: 'Seleucid Era Babylonian year, counting from the year 312 BCE.', + }, + { + name: 'seMacedonianYear', + type: 'number', + placeholder: 'SE Macedonian Year', + help: 'Seleucid Era Macedonian year, counting from the year 312 BCE.', + }, + { + name: 'seArsacidYear', + type: 'number', + placeholder: 'SE Arsacid Year', + help: 'Year count during the Arsacid (Parthian) Dynasty, 247 BCE - 224 CE.', + }, +] + +const mesopotamianDateInformationFields = [ + { + name: 'ruler', + type: 'text', + placeholder: 'Ruler', + help: 'Name of the ruler or king reigning at the time.', + }, + { + name: 'regnalYear', + type: 'number', + placeholder: 'Regnal Year', + help: + 'Regnal year, or the year of the ruler’s reign, as a number starting from 1.', + }, + { + name: 'mesopotamianMonth', + type: 'number', + placeholder: 'Mesopotamian Month', + required: true, + help: + 'Mesopotamian month as a number from 1 to 12 or 13 (depending on the year).', + }, + { + name: 'mesopotamianDay', + type: 'number', + placeholder: 'Mesopotamian Day', + help: 'Mesopotamian day of the month as a number from 1 to 30.', + }, + { + name: 'mesopotamianMonthLength', + type: 'number', + placeholder: 'Mesopotamian Month Length', + help: 'Length of the Mesopotamian month, either 29 or 30 days.', + }, +] + +export const sections = [ + { title: 'Modern', fields: generalInformationFields }, + { title: 'Mesopotamian', fields: mesopotamianDateInformationFields }, + { title: 'Seleucid', fields: seleucidEraInformationFields }, + { + title: 'Specialized', + fields: specializedDateInformationFields, + }, +] + +export type Field = { + name: string + type: string + placeholder: string + required?: boolean + help: string +}