import { useEffect, useRef, useState } from 'react'; import * as Popover from '@radix-ui/react-popover'; import { useField } from '@unform/core'; import { HiClock, HiOutlineX } from 'react-icons/hi'; import styled, { css } from 'styled-components'; import { toPattern } from 'vanilla-masker'; import { useTheme, Colors } from '../../hooks/theme'; import { IconButton } from '../IconButton'; import { InputContainer, Label, InputBody, Error } from './styles'; interface Props { name: string; label?: string; placeholder?: string; } type TimePickerProps = JSX.IntrinsicElements['input'] & Props; type CardProps = { colorScheme: Colors; }; const Card = styled(Popover.Content)` border-radius: 8px; background-color: ${({ theme }) => theme.colors.cardBackground}; box-shadow: ${({ theme }) => theme.shadows.sm}; border: 1px solid ${({ theme }) => theme.colors.gray[3]}; display: flex; max-height: 220px; overflow: auto; `; const TriggerButton = styled(Popover.Trigger)` background-color: transparent; border: 0; cursor: pointer; height: 20px; width: 20px; display: flex; align-items: center; color: ${({ theme }) => theme.colors.gray[9]}; `; const List = styled.div` overflow: auto; `; type ItemProps = { colorScheme: Colors; selected: boolean; }; const Item = styled.button` all: unset; width: 48px; height: 28px; display: flex; justify-content: center; align-items: center; cursor: pointer; ${({ selected, theme, colorScheme }) => selected && css` background-color: ${theme.colors[colorScheme][3]}; `} &:hover { background-color: ${({ theme, colorScheme }) => theme.colors[colorScheme][4]}; } `; export function TimePicker({ name, label, disabled, ...rest }: TimePickerProps): JSX.Element { const { colorScheme } = useTheme(); const inputRef = useRef(null); const { fieldName, defaultValue, registerField, error } = useField(name); const [isFocused, setIsFocused] = useState(false); const [isFilled, setIsFilled] = useState(defaultValue); const [hour, setHour] = useState(''); const [minute, setMinute] = useState(''); function handleChange(value: string): void { const masked = toPattern(value, '99:99'); if (inputRef.current) { inputRef.current.value = masked; } setIsFilled(masked); if (masked.length === 5) { const maskedSplitted = masked.split(':'); setHour(maskedSplitted[0]); setMinute(maskedSplitted[1]); } } function handleClear(): void { setIsFilled(''); setHour(''); setMinute(''); if (inputRef.current) { inputRef.current.value = ''; } } useEffect(() => { registerField({ name: fieldName, ref: inputRef, getValue: (ref) => { return ref.current.value; }, setValue: (_, value: string) => { handleChange(value); }, clearValue: () => handleClear(), }); }, [fieldName, registerField]); return ( {label && ( )} setIsFocused(true)} onBlur={() => { setIsFocused(false); }} onChange={(event) => handleChange(event.target.value)} {...rest} /> } size="sm" variant="ghost" colorScheme="gray" onClick={handleClear} tabIndex={-1} visible={!!isFilled && !disabled} /> {Array.from(Array(24).keys()) .map((item) => String(item).padStart(2, '0')) .map((item) => ( { setHour(item); if (inputRef.current) { const selectedSplitted = inputRef.current.value.split(':'); let value = ''; if (selectedSplitted.length === 1) { value = `${item}:00`; } else { value = `${item}:${selectedSplitted[1]}`; } handleChange(value); } }} > {item} ))} {Array.from(Array(60).keys()) .map((item) => String(item).padStart(2, '0')) .map((item) => ( { setMinute(item); if (inputRef.current) { const selectedSplitted = inputRef.current.value.split(':'); let value = ''; if (selectedSplitted.length === 1) { value = `00:${item}`; } else { value = `${selectedSplitted[0]}:${item}`; } handleChange(value); } }} > {item} ))} {error && {error}} ); }