/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. * * OpenCRVS is also distributed under the terms of the Civil Registration * & Healthcare Disclaimer located at http://opencrvs.org/license. * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ import * as React from 'react' import styled from 'styled-components' import { ITextInputProps, IRef, TextInput } from '../TextInput/TextInput' export interface IProps { id: string disabled?: boolean meta?: { touched: boolean; error: string } focusInput?: boolean notice?: string value?: string ignorePlaceHolder?: boolean onChange: (dateString: string) => void } interface IState { hh: string mm: string } const Container = styled.div` width: 100%; display: flex; gap: 16px; ` export type ITimeFieldProps = IProps & Omit function getFormattedValue(time: { hh: string; mm: string }) { return `${time.hh.padStart(2, '0')}:${time.mm.padStart(2, '0')}` } function isValidMinutes(minutes: string) { if (minutes.length !== 2) { return false } const parsed = Number(minutes) if (isNaN(parsed)) { return false } return parsed >= 0 && parsed <= 59 } function isValidHours(hours: string) { if (hours.length !== 2) { return false } const parsed = Number(hours) if (isNaN(parsed)) { return false } return parsed >= 0 && parsed <= 23 } export function TimeField(props: ITimeFieldProps) { const { id, meta, focusInput, notice, ignorePlaceHolder, onChange, ...otherProps } = props const [state, setState] = React.useState({ hh: '', mm: '' }) React.useEffect(() => { function getInitialState(time: string): IState { const dateSegmentVals = time.split(':') return { hh: dateSegmentVals[0], mm: dateSegmentVals[1] } } const isValidTime = (time: string) => { const parts = time.split(':') if (parts.length !== 2) { return false } return isValidHours(parts[0]) && isValidMinutes(parts[1]) } if (props.value && isValidTime(props.value)) { setState(getInitialState(props.value)) } }, [props.value]) const hh = React.useRef(null) const mm = React.useRef(null) function change(event: React.ChangeEvent) { const val = event.target.value if (event.target.id.includes('hh')) { if (Number(val) < 0 || Number(val) > 23) return if (val.length === 2 && mm?.current !== null) { mm.current.focusField() } setState((state) => ({ ...state, hh: val })) } else if (event.target.id.includes('mm')) { if (Number(val) < 0 || Number(val) > 59 || val.length > 2) return setState((state) => ({ ...state, mm: val })) } } function padStart(part: 'hh' | 'mm') { return (event: React.FocusEvent) => { const val = event.target.value if (part === 'hh') { setState((state) => ({ ...state, hh: val.padStart(2, '0') })) } else if (part === 'mm') { setState((state) => ({ ...state, mm: val.padStart(2, '0') })) } } } React.useEffect(() => { if (isValidHours(state.hh) && isValidMinutes(state.mm)) { onChange(getFormattedValue(state)) } }, [state, onChange]) return ( ) => { event.currentTarget.blur() }} /> ) => { event.currentTarget.blur() }} /> ) }