All files / src/components/DatePicker MobileCalendar.tsx

10% Statements 3/30
0% Branches 0/21
0% Functions 0/4
10% Lines 3/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100    9x                     9x                                 9x                                                                                                                                          
'use client';
 
import {dateTime} from '@gravity-ui/date-utils';
import type {DateTime} from '@gravity-ui/date-utils';
 
import {block} from '../../utils/cn';
import {createPlaceholderValue, mergeDateTime} from '../utils/dates';
 
import type {DatePickerProps} from './DatePicker';
import type {DatePickerState} from './hooks/useDatePickerState';
 
import './MobileCalendar.scss';
 
const b = block('mobile-calendar');
 
type InputDateType = 'date' | 'time' | 'datetime-local';
 
interface MobileCalendarProps {
    props: DatePickerProps;
    state: DatePickerState;
}
export function MobileCalendar({props, state}: MobileCalendarProps) {
    let type: InputDateType = 'date';
    if (state.formatInfo.hasTime && state.formatInfo.hasDate) {
        type = 'datetime-local';
    } else if (state.formatInfo.hasTime) {
        type = 'time';
    }
 
    return (
        <input
            className={b()}
            disabled={props.disabled}
            type={type}
            value={formatNative(state.dateFieldState.value, type)}
            id={props.id}
            min={formatNative(props.minValue?.timeZone(state.timeZone), type)}
            max={formatNative(props.maxValue?.timeZone(state.timeZone), type)}
            tabIndex={-1}
            onChange={(e) => {
                if (props.readOnly) {
                    return;
                }
                const newValue = e.target.value;
                if (newValue) {
                    const localDate = dateTime({
                        input: newValue,
                        format: getDateFormat(type),
                        timeZone: 'system',
                    }).timeZone(state.timeZone, true);
                    let newDate = state.formatInfo.hasDate
                        ? localDate
                        : createPlaceholderValue({
                              placeholderValue: props.placeholderValue?.timeZone(state.timeZone),
                              timeZone: state.timeZone,
                          });
                    if (state.formatInfo.hasTime) {
                        newDate = mergeDateTime(newDate, localDate);
                    } else if (state.value) {
                        newDate = mergeDateTime(newDate, state.value.timeZone(state.timeZone));
                    } else {
                        newDate = mergeDateTime(
                            newDate,
                            createPlaceholderValue({
                                placeholderValue: props.placeholderValue?.timeZone(state.timeZone),
                                timeZone: state.timeZone,
                            }),
                        );
                    }
                    state.setValue(newDate);
                } else {
                    state.setValue(null);
                }
            }}
        />
    );
}
 
function getDateFormat(type: InputDateType) {
    switch (type) {
        case 'time': {
            return 'HH:mm';
        }
        case 'datetime-local': {
            return 'YYYY-MM-DDTHH:mm';
        }
        default: {
            return 'YYYY-MM-DD';
        }
    }
}
function formatNative(date: DateTime | null | undefined, type: InputDateType) {
    if (!date) {
        return '';
    }
 
    const format = getDateFormat(type);
    return date.format(format);
}