fix: date time picker bugs has fixed
This commit is contained in:
parent
13a378b45c
commit
ffeb365e8d
@ -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 (
|
||||
|
||||
@ -20,7 +20,7 @@ function BirthtimePage(): JSX.Element {
|
||||
<Title variant="h2" className="mt-24">{t('bornTimeQuestion')}</Title>
|
||||
<p className="description">{t('nasaDataUsing')}</p>
|
||||
<TimePicker value={birthtime} onChange={handleChange}/>
|
||||
<MainButton label={t('next')} onClick={handleNext} disabled={!birthtime}/>
|
||||
<MainButton label={t('next')} onClick={handleNext}/>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import { FormField } from '../../types'
|
||||
import { normalize, calculateMaxValue } from './utils'
|
||||
|
||||
type DatePartValue = number | undefined
|
||||
type DatePartValue = string | undefined
|
||||
|
||||
type DateInputProps = Omit<FormField<DatePartValue>, '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<HTMLInputElement>) => {
|
||||
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 (
|
||||
<div className="date-picker__field">
|
||||
@ -28,7 +28,7 @@ function DateInput(props: DateInputProps): JSX.Element {
|
||||
type="number"
|
||||
placeholder=" "
|
||||
maxLength={maxLength}
|
||||
value={value ? normalize(value, maxLength) : ''}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<p className="date-picker__input-placeholder">{placeholder}</p>
|
||||
|
||||
@ -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<string>): 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(stringify(date))
|
||||
onValid('')
|
||||
}
|
||||
}, [year, month, day, hasError, onValid, onInvalid])
|
||||
|
||||
return (
|
||||
@ -35,11 +38,11 @@ export function DatePicker(props: FormField<string>): JSX.Element {
|
||||
<DateInput
|
||||
name='year'
|
||||
value={year}
|
||||
max={getMaxYear()}
|
||||
max={getCurrentYear()}
|
||||
maxLength={4}
|
||||
label={t('year')}
|
||||
placeholder='YYYY'
|
||||
onChange={(year: number) => setYear(year)}
|
||||
onChange={(year: string) => setYear(year)}
|
||||
/>
|
||||
<DateInput
|
||||
name='month'
|
||||
@ -48,16 +51,16 @@ export function DatePicker(props: FormField<string>): JSX.Element {
|
||||
maxLength={2}
|
||||
label={t('month')}
|
||||
placeholder='MM'
|
||||
onChange={(month: number) => setMonth(month)}
|
||||
onChange={(month: string) => setMonth(month)}
|
||||
/>
|
||||
<DateInput
|
||||
name='day'
|
||||
value={day}
|
||||
max={getDaysInMonth(year, month)}
|
||||
max={31}
|
||||
maxLength={2}
|
||||
label={t('day')}
|
||||
placeholder='DD'
|
||||
onChange={(day: number) => setDay(day)}
|
||||
onChange={(day: string) => setDay(day)}
|
||||
/>
|
||||
</div>
|
||||
<ErrorText
|
||||
|
||||
@ -6,7 +6,7 @@ export const calculateMaxValue = (digits: number): number => {
|
||||
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 }
|
||||
}
|
||||
|
||||
@ -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'
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'
|
||||
|
||||
const birthtimeSlice = createSlice({
|
||||
name: 'birthtime',
|
||||
initialState: '',
|
||||
initialState: '12:00',
|
||||
reducers: {
|
||||
update(state, action: PayloadAction<string>) {
|
||||
state = action.payload
|
||||
|
||||
Loading…
Reference in New Issue
Block a user