feat: create TimeSelector time range component

This commit is contained in:
gnezim
2026-04-05 20:59:02 +03:00
parent 9bc930fe91
commit fd054bc688
3 changed files with 156 additions and 0 deletions
@@ -0,0 +1,2 @@
export { TimeSelector } from './time-selector'
export type { TimeSelectorProps } from './time-selector'
@@ -0,0 +1,42 @@
.time-selector {
display: flex;
gap: 20px;
margin: 16px 0;
}
.time-selector__group {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
.time-selector__label {
font-size: 12px;
font-weight: 500;
color: #666;
text-transform: uppercase;
}
.time-selector__inputs {
display: flex;
align-items: center;
gap: 8px;
}
.time-selector__input {
width: 60px;
text-align: center;
:global {
.p-inputnumber-input {
padding: 8px 4px;
font-size: 14px;
}
}
}
.time-selector__separator {
font-weight: 600;
color: #666;
}
@@ -0,0 +1,112 @@
import React from 'react'
import { InputNumber } from 'primereact/inputnumber'
import { useTranslation } from 'react-i18next'
import './time-selector.scss'
export interface TimeSelectorProps {
startTime?: string
endTime?: string
onStartTimeChange?: (time: string) => void
onEndTimeChange?: (time: string) => void
'data-testid'?: string
}
export const TimeSelector: React.FC<TimeSelectorProps> = ({
startTime = '00:00',
endTime = '23:59',
onStartTimeChange,
onEndTimeChange,
'data-testid': dataTestId,
}) => {
const { t } = useTranslation()
const parseTime = (timeStr: string): { hours: number; minutes: number } => {
const [h, m] = timeStr.split(':').map(Number)
return { hours: h || 0, minutes: m || 0 }
}
const formatTime = (hours: number, minutes: number): string => {
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`
}
const handleStartHoursChange = (value: number | null | undefined) => {
if (onStartTimeChange && value !== null && value !== undefined) {
const { minutes } = parseTime(startTime)
onStartTimeChange(formatTime(value, minutes))
}
}
const handleStartMinutesChange = (value: number | null | undefined) => {
if (onStartTimeChange && value !== null && value !== undefined) {
const { hours } = parseTime(startTime)
onStartTimeChange(formatTime(hours, value))
}
}
const handleEndHoursChange = (value: number | null | undefined) => {
if (onEndTimeChange && value !== null && value !== undefined) {
const { minutes } = parseTime(endTime)
onEndTimeChange(formatTime(value, minutes))
}
}
const handleEndMinutesChange = (value: number | null | undefined) => {
if (onEndTimeChange && value !== null && value !== undefined) {
const { hours } = parseTime(endTime)
onEndTimeChange(formatTime(hours, value))
}
}
const startParsed = parseTime(startTime)
const endParsed = parseTime(endTime)
return (
<div className="time-selector" data-testid={dataTestId || 'time-selector'}>
<div className="time-selector__group">
<label className="time-selector__label">{t('SHARED.FROM')}</label>
<div className="time-selector__inputs">
<InputNumber
value={startParsed.hours}
onValueChange={(e) => handleStartHoursChange(e.value)}
min={0}
max={23}
className="time-selector__input"
data-testid="time-selector-start-hours"
/>
<span className="time-selector__separator">:</span>
<InputNumber
value={startParsed.minutes}
onValueChange={(e) => handleStartMinutesChange(e.value)}
min={0}
max={59}
className="time-selector__input"
data-testid="time-selector-start-minutes"
/>
</div>
</div>
<div className="time-selector__group">
<label className="time-selector__label">{t('SHARED.TO')}</label>
<div className="time-selector__inputs">
<InputNumber
value={endParsed.hours}
onValueChange={(e) => handleEndHoursChange(e.value)}
min={0}
max={23}
className="time-selector__input"
data-testid="time-selector-end-hours"
/>
<span className="time-selector__separator">:</span>
<InputNumber
value={endParsed.minutes}
onValueChange={(e) => handleEndMinutesChange(e.value)}
min={0}
max={59}
className="time-selector__input"
data-testid="time-selector-end-minutes"
/>
</div>
</div>
</div>
)
}