From ffeb365e8d17e070bcc4d54404def6b9fc47db95 Mon Sep 17 00:00:00 2001 From: "Aidar Shaikhutdin @makeweb.space" Date: Mon, 8 May 2023 20:47:21 +0600 Subject: [PATCH] fix: date time picker bugs has fixed --- src/components/BirthdayPage/index.tsx | 2 +- src/components/BirthtimePage/index.tsx | 2 +- src/components/DateTimePicker/DateInput.tsx | 10 ++--- src/components/DateTimePicker/DatePicker.tsx | 45 ++++++++++--------- src/components/DateTimePicker/utils.ts | 18 +++----- .../EmailInput.tsx} | 0 src/components/EmailEnterPage/index.tsx | 2 +- .../{EmailInput => EmailEnterPage}/styles.css | 0 src/store/birthtime.ts | 2 +- 9 files changed, 40 insertions(+), 41 deletions(-) rename src/components/{EmailInput/index.tsx => EmailEnterPage/EmailInput.tsx} (100%) rename src/components/{EmailInput => EmailEnterPage}/styles.css (100%) diff --git a/src/components/BirthdayPage/index.tsx b/src/components/BirthdayPage/index.tsx index f990a62..d91783d 100644 --- a/src/components/BirthdayPage/index.tsx +++ b/src/components/BirthdayPage/index.tsx @@ -25,7 +25,7 @@ function BirthdayPage(): JSX.Element { const handleNext = () => navigate(routes.client.birthtime()) const handleValid = (birthdate: string) => { dispatch(actions.birthdate.update(birthdate)) - setIsDisabled(false) + setIsDisabled(birthdate === '') } return ( diff --git a/src/components/BirthtimePage/index.tsx b/src/components/BirthtimePage/index.tsx index 313e28b..f58a654 100644 --- a/src/components/BirthtimePage/index.tsx +++ b/src/components/BirthtimePage/index.tsx @@ -20,7 +20,7 @@ function BirthtimePage(): JSX.Element { {t('bornTimeQuestion')}

{t('nasaDataUsing')}

- + ) } diff --git a/src/components/DateTimePicker/DateInput.tsx b/src/components/DateTimePicker/DateInput.tsx index 8d7bc26..8783211 100644 --- a/src/components/DateTimePicker/DateInput.tsx +++ b/src/components/DateTimePicker/DateInput.tsx @@ -1,23 +1,23 @@ import { FormField } from '../../types' import { normalize, calculateMaxValue } from './utils' -type DatePartValue = number | undefined +type DatePartValue = string | undefined type DateInputProps = Omit, 'onValid' | 'onInvalid'> & { max: number maxLength: number - onChange: (part: number) => void + onChange: (part: string) => void } function DateInput(props: DateInputProps): JSX.Element { - const { label, placeholder, name, value, max, maxLength, onChange } = props + const { label, placeholder, name, value = '', max, maxLength, onChange } = props const validate = (value: number): boolean => value >= 0 && value <= max const handleChange = (e: React.ChangeEvent) => { const datePart = parseInt(e.target.value, 10) if (isNaN(datePart)) return if (datePart > calculateMaxValue(maxLength)) return if (!validate(datePart)) return - onChange(datePart) + onChange(datePart > 0 ? normalize(datePart, maxLength) : '') } return (
@@ -28,7 +28,7 @@ function DateInput(props: DateInputProps): JSX.Element { type="number" placeholder=" " maxLength={maxLength} - value={value ? normalize(value, maxLength) : ''} + value={value} onChange={handleChange} />

{placeholder}

diff --git a/src/components/DateTimePicker/DatePicker.tsx b/src/components/DateTimePicker/DatePicker.tsx index d16851d..c266315 100644 --- a/src/components/DateTimePicker/DatePicker.tsx +++ b/src/components/DateTimePicker/DatePicker.tsx @@ -3,30 +3,33 @@ import { useTranslation } from 'react-i18next' import { FormField } from '../../types' import DateInput from './DateInput' import ErrorText from './ErrorText' -import { stringify, getMaxYear, isNotTheDate, getDaysInMonth } from './utils' +import { stringify, getCurrentYear } from './utils' export function DatePicker(props: FormField): JSX.Element { const { t } = useTranslation() const { name, value, onValid, onInvalid } = props - - const date = new Date(value) - - const [year, setYear] = useState(date.getFullYear()) - const [month, setMonth] = useState(date.getMonth()) - const [day, setDay] = useState(date.getDate()) + const [initYear, initMonth, initDay] = value.split('-') + const [year, setYear] = useState(initYear) + const [month, setMonth] = useState(initMonth) + const [day, setDay] = useState(initDay) const [hasError, setHasError] = useState(false) + const isValid = (value: string) => { + const date = new Date(value) + const isCorrectDate = stringify(date) === value + const isNotFutureDate = date.getTime() <= Date.now() + const isNotMinDate = date.getFullYear() >= getCurrentYear() - 200 + return isCorrectDate && isNotFutureDate && isNotMinDate + } useEffect(() => { - if (isNaN(year) || isNaN(month) || isNaN(day)) return - const combinedDate = `${year}-${month}-${day}` - const date = new Date(combinedDate) - if (isNotTheDate(date)) { - setHasError(true) - onInvalid() - return + if (year && month && day) { + const currentValue = `${year}-${month}-${day}` + setHasError(!isValid(currentValue)) + isValid(currentValue) ? onValid(currentValue) : onInvalid() + } else { + setHasError(false) + onValid('') } - setHasError(false) - onValid(stringify(date)) }, [year, month, day, hasError, onValid, onInvalid]) return ( @@ -35,11 +38,11 @@ export function DatePicker(props: FormField): JSX.Element { setYear(year)} + onChange={(year: string) => setYear(year)} /> ): JSX.Element { maxLength={2} label={t('month')} placeholder='MM' - onChange={(month: number) => setMonth(month)} + onChange={(month: string) => setMonth(month)} /> setDay(day)} + onChange={(day: string) => setDay(day)} />
{ return Math.pow(10, digits) - 1; } -export const getMaxYear = (): number => { +export const getCurrentYear = (): number => { return new Date().getFullYear() } @@ -23,19 +23,15 @@ export const getDaysInMonth = (year: number, month: number): number => { } export const format = (hour: string, minute: string, period: string) => { - const formattedHour = period === 'AM' ? normalize(hour, 2) : String(Number(hour) + 12) + const formattedHour = hour === '12' ? (period === 'AM' ? '00' : '12') : (period === 'PM' ? String(Number(hour) + 12) : hour) const formattedMinute = normalize(minute, 2) return `${formattedHour}:${formattedMinute}` } export const parse = (value: string) => { - const [hour, minute] = value.split(':') - const numHour = Number(hour) - const period = numHour < 12 ? 'AM' : 'PM' - const formattedHour = numHour > 12 ? String(numHour - 12) : String(numHour) - return { - hour: formattedHour, - minute, - period - } + const [hourStr, minute] = value.split(':') + const hour = Number(hourStr) + const formattedHour = hour === 0 || hour === 12 ? '12' : hour > 12 ? String(hour - 12) : hourStr + const period = hour < 12 ? 'AM' : 'PM' + return { hour: formattedHour, minute, period } } diff --git a/src/components/EmailInput/index.tsx b/src/components/EmailEnterPage/EmailInput.tsx similarity index 100% rename from src/components/EmailInput/index.tsx rename to src/components/EmailEnterPage/EmailInput.tsx diff --git a/src/components/EmailEnterPage/index.tsx b/src/components/EmailEnterPage/index.tsx index 8c6fa77..f846086 100644 --- a/src/components/EmailEnterPage/index.tsx +++ b/src/components/EmailEnterPage/index.tsx @@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux' import { actions, RootState } from '../../store' import Title from '../Title' import Policy from '../Policy' -import EmailInput from '../EmailInput' +import EmailInput from './EmailInput' import MainButton from '../MainButton' import routes from '../../routes' diff --git a/src/components/EmailInput/styles.css b/src/components/EmailEnterPage/styles.css similarity index 100% rename from src/components/EmailInput/styles.css rename to src/components/EmailEnterPage/styles.css diff --git a/src/store/birthtime.ts b/src/store/birthtime.ts index 265f7ff..b651641 100644 --- a/src/store/birthtime.ts +++ b/src/store/birthtime.ts @@ -3,7 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit' const birthtimeSlice = createSlice({ name: 'birthtime', - initialState: '', + initialState: '12:00', reducers: { update(state, action: PayloadAction) { state = action.payload