/** @jsxRuntime classic */ /** @jsx jsx */ import React, { useState, useEffect, Fragment } from 'react'; import { useTheme } from '@emotion/react'; import { StyledCalendar } from '../style'; import cx from 'classnames'; import { BnBack, BnForward } from '../../../icons'; import dayjs, { Dayjs } from 'dayjs'; import { DateProps, WeekDay } from './Date'; import { jsx, css } from '@emotion/react'; import { SelectOptions } from '../../Options'; import { IOption } from '../../Select'; type TStep = 'year' | 'month' | 'day'; const yearsCss = css` width: 250px; height: 300px; overflow-y: scroll; div { text-align: center; } `; export const DateOfBirth = ({ defaultValue, disabledDates, mode = 'date', value, onChange, }: DateProps) => { const getValueFormat = () => { if (mode === 'date') { return 'DD / MM / YYYY'; } else if (mode === 'datetime') { return 'DD / MM / YYYY HH:mm'; } else { return 'HH:mm'; } }; const colors = useTheme(); const currentDate = dayjs(); const [selectedMonth, setSelectedMonth] = useState<{ month: number; year: number; }>({ month: defaultValue ? dayjs(defaultValue).month() : dayjs().month(), year: defaultValue ? dayjs(defaultValue).year() : dayjs().year(), }); const [weeksAndDays, setWeeksAndDays] = useState([]); const [hoverPlaceholder, setHoverPlaceholder] = useState( undefined ); const [selectedDay, setSelectedDay] = useState( defaultValue ? dayjs(defaultValue) : dayjs() ); const [inputValue, setInputValue] = useState( value ? dayjs(value).format(getValueFormat()) : undefined ); const [isOptionsOpen, setIsOptionsOpen] = useState(false); const [step, setStep] = useState('year'); const [years, setYears] = useState([]); const [months, setMonths] = useState([]); const [selectedYear, setSelectedYear] = useState(); useEffect(() => { const potentialYears = []; const potentialMonths = []; for ( let i = Number(dayjs().format('YYYY')); i > Number(dayjs().format('YYYY')) - 100; i-- ) { potentialYears.push({ label: String(i), value: i, }); } for (let j = 1; j < 13; j++) { potentialMonths.push({ label: String(j), value: j, }); } setMonths(potentialMonths); setYears(potentialYears); }, []); const weekDays = [ dayjs().day(1).format('dd').slice(0, 1), dayjs().day(2).format('dd').slice(0, 1), dayjs().day(3).format('dd').slice(0, 1), dayjs().day(4).format('dd').slice(0, 1), dayjs().day(5).format('dd').slice(0, 1), dayjs().day(6).format('dd').slice(0, 1), dayjs().day(0).format('dd').slice(0, 1), ]; const getWeekday = (date: string) => { return dayjs(date).day(); }; const createCalendar = () => { let currentMonthDays = [ ...Array( dayjs( `${selectedMonth.year}-${selectedMonth.month + 1}-01` ).daysInMonth() ), ].map((_, index) => { return { date: dayjs( `${selectedMonth.year}-${selectedMonth.month + 1}-${index + 1}` ).format('YYYY-MM-DD'), dayOfMonth: index + 1, isCurrentMonth: true, isDisabled: disabledDates && disabledDates( dayjs( `${selectedMonth.year}-${selectedMonth.month + 1}-${index + 1}` ) ), }; }); const currentMonthFirstDay = getWeekday(currentMonthDays[0].date); const previousMonth = dayjs( `${selectedMonth.year}-${selectedMonth.month + 1}-01` ).subtract(1, 'month'); const daysOfPreviousMonth = currentMonthFirstDay ? currentMonthFirstDay - 1 : 6; const lastMondayOfPreviousMonth = dayjs(currentMonthDays[0].date) .subtract(daysOfPreviousMonth, 'day') .date(); let previousMonthDays = [...Array(daysOfPreviousMonth)].map((_, index) => { return { date: dayjs( `${previousMonth.year()}-${previousMonth.month() + 1}-${ lastMondayOfPreviousMonth + index }` ).format('YYYY-MM-DD'), dayOfMonth: lastMondayOfPreviousMonth + index, isCurrentMonth: false, isDisabled: disabledDates && disabledDates( dayjs( `${previousMonth.year()}-${previousMonth.month() + 1}-${ lastMondayOfPreviousMonth + index }` ) ), }; }); const currentMonthLastDay = getWeekday( `${selectedMonth.year}-${selectedMonth.month + 1}-${ currentMonthDays.length }` ); const nextMonth = dayjs( `${selectedMonth.year}-${selectedMonth.month + 1}-01` ).add(1, 'month'); const daysOfNextMonth = currentMonthLastDay ? 7 - currentMonthLastDay : currentMonthLastDay; let nextMonthDays = [...Array(daysOfNextMonth)].map((_, index) => { return { date: dayjs( `${nextMonth.year()}-${nextMonth.month() + 1}-${index + 1}` ).format('YYYY-MM-DD'), dayOfMonth: index + 1, isCurrentMonth: false, isDisabled: disabledDates && disabledDates( dayjs(`${nextMonth.year()}-${nextMonth.month() + 1}-${index + 1}`) ), }; }); let days = [...previousMonthDays, ...currentMonthDays, ...nextMonthDays]; return days; }; const goBack = () => { setSelectedMonth({ month: dayjs( dayjs() .month(selectedMonth.month) .year(selectedMonth.year) .subtract(1, 'month') ).month(), year: dayjs( dayjs() .month(selectedMonth.month) .year(selectedMonth.year) .subtract(1, 'month') ).year(), }); }; const goForward = () => { setSelectedMonth({ month: dayjs( dayjs() .month(selectedMonth.month) .year(selectedMonth.year) .add(1, 'month') ).month(), year: dayjs( dayjs() .month(selectedMonth.month) .year(selectedMonth.year) .add(1, 'month') ).year(), }); }; useEffect(() => { let days = createCalendar(); const chunkDays = () => { let results = []; while (days.length) { results.push(days.splice(0, 7)); } return results; }; setWeeksAndDays(chunkDays()); }, [selectedMonth]); const selectYear = (year: number) => { setSelectedYear(year); setStep('month'); }; const selectMonth = (month: number) => { setSelectedMonth({ year: selectedYear || dayjs().year(), month: month - 1, }); setStep('day'); }; return ( {step === 'year' && (
)} {step === 'month' && (
)} {step === 'day' && (
{dayjs().month(selectedMonth.month).format('MMMM')}
{weekDays.map((weekDay: string, key: number) => ( ))} {weeksAndDays?.map((week: WeekDay[], i: number) => ( {week.map((day: WeekDay, a: number) => ( ))} ))}
{weekDay}
!day.isDisabled && setHoverPlaceholder( dayjs(day.date) .set('hour', selectedDay.get('hour')) .set('minute', selectedDay.get('minute')) .format(getValueFormat()) ) } onMouseOut={() => setHoverPlaceholder(undefined)} onClick={() => { if (!day.isDisabled) { setInputValue( dayjs(day.date) .set('hour', selectedDay.get('hour')) .set('minute', selectedDay.get('minute')) .format(getValueFormat()) ); if (onChange) { onChange( dayjs(day.date, 'YYYY-MM-DD') .set('hour', selectedDay.get('hour')) .set('minute', selectedDay.get('minute')) ); } setSelectedDay(dayjs(day.date)); // selectedDay.set( // 'date', // dayjs(day.date, 'YYYY-MM-DD').get('date') // ) // ); if (!day.isCurrentMonth) { setSelectedMonth({ month: dayjs(day.date).month(), year: dayjs(day.date).year(), }); } setIsOptionsOpen(false); } }} > {dayjs(day.date).format('D')}
)}
); };