@hitachivantara/uikit-react-core
Version:
Core React components for the NEXT Design System.
281 lines (280 loc) • 9.77 kB
JavaScript
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
};