UNPKG

@hitachivantara/uikit-react-core

Version:

Core React components for the NEXT Design System.

281 lines (280 loc) 9.77 kB
import { jsxs, jsx } from "react/jsx-runtime"; import { useState, useCallback, useMemo, memo } from "react"; import { useTheme } from "@mui/material/styles"; import useMediaQuery from "@mui/material/useMediaQuery"; import dayjs from "dayjs"; import { uniqueId } from "../../../../utils/helpers.js"; import { useQueryBuilderContext } from "../../../Context.js"; import { useClasses } from "./DateTimeValue.styles.js"; import { padTime, parseDate, parseTime } from "./utils.js"; import { HvDatePicker } from "../../../../DatePicker/DatePicker.js"; import { HvTimePicker } from "../../../../TimePicker/TimePicker.js"; import { HvWarningText } from "../../../../FormElement/WarningText/WarningText.js"; function valueIsRange(operator) { return operator === "range"; } const DateTimeValue = ({ id, operator, value: valueProp = {}, initialTouched = false }) => { const { classes, cx } = useClasses(); const theme = useTheme(); const isMdDown = useMediaQuery(theme.breakpoints.down("md")); const isRange = valueIsRange(operator); const { labels, dispatchAction, readOnly } = useQueryBuilderContext(); const elementId = uniqueId(`datetime${id}`); const [touchedDate, setTouchedDate] = useState(initialTouched); const [touchedTime, setTouchedTime] = useState(initialTouched); const [touchedEndDate, setTouchedEndDate] = useState(initialTouched); const [touchedEndTime, setTouchedEndTime] = useState(initialTouched); const onDateChange = useCallback( (data) => { setTouchedDate(true); let date; if (data != null) { date = dayjs(data).format("YYYY-MM-DD"); } const oldValue = !isRange ? valueProp?.date : valueProp?.start?.date; if (date !== oldValue) { let value; if (!isRange) { value = { date, time: valueProp?.time }; } else { value = { start: { date, time: valueProp?.start?.time }, end: valueProp?.end }; } dispatchAction({ type: "set-value", id, value }); } }, [dispatchAction, id, isRange, valueProp] ); const onTimeChange = useCallback( (data) => { setTouchedTime(true); let time; if (data != null) { time = `${padTime(data.hours)}:${padTime(data.minutes)}:${padTime( data.seconds )}`; } const oldValue = !isRange ? valueProp?.time : valueProp?.start?.time; if (time !== oldValue) { let value; if (!isRange) { value = { date: valueProp?.date, time }; } else { value = { start: { date: valueProp?.start?.date, time }, end: valueProp?.end }; } dispatchAction({ type: "set-value", id, value }); } }, [dispatchAction, id, isRange, valueProp] ); const onEndDateChange = useCallback( (data) => { setTouchedEndDate(true); let date; if (data != null) { date = dayjs(data).format("YYYY-MM-DD"); } if (date !== valueProp?.end?.date) { const value = { start: valueProp?.start, end: { date, time: valueProp?.end?.time } }; dispatchAction({ type: "set-value", id, value }); } }, [dispatchAction, id, valueProp] ); const onEndTimeChange = useCallback( (data) => { setTouchedEndTime(true); let time; if (data != null) { time = `${padTime(data.hours)}:${padTime(data.minutes)}:${padTime( data.seconds )}`; } if (time !== valueProp?.end?.time) { const value = { start: valueProp?.start, end: { date: valueProp?.end?.date, time } }; dispatchAction({ type: "set-value", id, value }); } }, [dispatchAction, id, valueProp] ); const startDate = isRange ? valueProp?.start?.date : valueProp?.date; const datePickerValue = useMemo(() => parseDate(startDate), [startDate]); const datePickerStatus = datePickerValue != null ? "valid" : "invalid"; const startTime = (isRange ? valueProp?.start?.time : valueProp?.time) ?? ""; const timePickerValue = useMemo(() => parseTime(startTime), [startTime]); const timePickerStatus = timePickerValue != null ? "valid" : "invalid"; const endDate = isRange ? valueProp?.end?.date : null; const endDatePickerValue = useMemo(() => parseDate(endDate), [endDate]); const endTime = isRange ? valueProp?.end?.time : null; const endTimePickerValue = useMemo(() => parseTime(endTime), [endTime]); const dateStatus = !touchedDate ? "standBy" : datePickerStatus; const timeStatus = !touchedTime ? "standBy" : timePickerStatus; const endDateIsBefore = startDate != null && endDate != null && endDate < startDate; const endTimeIsBeforeOrSame = startDate != null && endDate != null && endDate === startDate && startTime != null && endTime != null && endTime <= startTime; const endDateTimeIsBefore = endDateIsBefore || endTimeIsBeforeOrSame; const endDatePickerStatus = endDatePickerValue == null || endDateTimeIsBefore ? "invalid" : "valid"; const endDateStatus = !touchedEndDate ? "standBy" : endDatePickerStatus; const endTimePickerStatus = endTimePickerValue == null || endDateTimeIsBefore ? "invalid" : "valid"; const endTimeStatus = !touchedEndTime ? "standBy" : endTimePickerStatus; return /* @__PURE__ */ jsxs("div", { className: classes.root, children: [ /* @__PURE__ */ jsxs( "div", { className: cx(classes.row, classes.horizontal, { [classes.isMdDown]: isMdDown }), children: [ /* @__PURE__ */ jsx( HvDatePicker, { className: classes.datePicker, name: `${elementId}-date`, required: true, status: dateStatus, statusMessage: labels.rule.value.datetime.validation.required, label: isRange ? labels.rule.value.datetime.startDateLabel : labels.rule.value.datetime.dateLabel, placeholder: isRange ? labels.rule.value.datetime.startDatePlaceholder : labels.rule.value.datetime.datePlaceholder, value: datePickerValue, onChange: onDateChange, readOnly } ), /* @__PURE__ */ jsx( HvTimePicker, { className: classes.timePicker, timeFormat: "24", name: `${elementId}-time`, required: true, status: timeStatus, statusMessage: labels.rule.value.datetime.validation.required, label: isRange ? labels.rule.value.datetime.startTimeLabel : labels.rule.value.datetime.timeLabel, placeholder: isRange ? labels.rule.value.datetime.startTimePlaceholder : labels.rule.value.datetime.timePlaceholder, value: timePickerValue || void 0, onChange: onTimeChange, onToggle: (_evt, open) => { if (!open && !touchedTime) { setTouchedTime(true); } }, readOnly } ) ] } ), isRange && /* @__PURE__ */ jsxs("div", { className: cx(classes.row, classes.vertical), children: [ /* @__PURE__ */ jsxs( "div", { className: cx(classes.horizontal, { [classes.isMdDown]: isMdDown }), children: [ /* @__PURE__ */ jsx( HvDatePicker, { className: classes.datePicker, name: `${elementId}-endDate`, required: true, status: endDateStatus, statusMessage: labels.rule.value.datetime.validation.required, "aria-errormessage": endDateTimeIsBefore ? `${elementId}-combined-error` : void 0, label: labels.rule.value.datetime.endDateLabel, placeholder: labels.rule.value.datetime.endDatePlaceholder, value: endDatePickerValue, onChange: onEndDateChange, readOnly } ), /* @__PURE__ */ jsx( HvTimePicker, { className: classes.timePicker, timeFormat: "24", name: `${elementId}-endTime`, required: true, status: endTimeStatus, statusMessage: labels.rule.value.datetime.validation.required, "aria-errormessage": endDateTimeIsBefore ? `${elementId}-combined-error` : void 0, label: labels.rule.value.datetime.endTimeLabel, placeholder: labels.rule.value.datetime.endTimePlaceholder, value: endTimePickerValue || void 0, onChange: onEndTimeChange, onToggle: (_evt, open) => { if (!open && !touchedEndTime) { setTouchedEndTime(true); } }, readOnly } ) ] } ), /* @__PURE__ */ jsx( HvWarningText, { disableBorder: true, id: `${elementId}-combined-error`, isVisible: endDateTimeIsBefore, children: labels.rule.value.datetime.validation.invalidInterval } ) ] }) ] }); }; memo(DateTimeValue); export { DateTimeValue };