Merge branch 'feature/IO-2834-Enhance-DateTime-Picker' into release/2024-08-23
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
import React, { useCallback, useState } from "react";
|
|
||||||
import { DatePicker } from "antd";
|
import { DatePicker } from "antd";
|
||||||
import dayjs from "../../utils/day";
|
|
||||||
import { formats, shorthandFormats } from "./formats.js";
|
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
import React, { useCallback, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import dayjs from "../../utils/day";
|
||||||
|
import { dateFormats, dateTimeFormats } from "./formats.js";
|
||||||
|
|
||||||
const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => {
|
const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => {
|
||||||
const [isManualInput, setIsManualInput] = useState(false);
|
const [isManualInput, setIsManualInput] = useState(false);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
(newDate) => {
|
(newDate) => {
|
||||||
@@ -19,6 +21,24 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is
|
|||||||
[onChange]
|
[onChange]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const normalizeDateTimeString = (input) => {
|
||||||
|
const upperV = input.toUpperCase().replaceAll(".", "/").replaceAll("-", "/");
|
||||||
|
|
||||||
|
const [datePart, ...timeParts] = upperV.split(" ");
|
||||||
|
|
||||||
|
if (timeParts.length === 0) {
|
||||||
|
return datePart; // If there's no time part, just return the date part.
|
||||||
|
}
|
||||||
|
|
||||||
|
const timePart = timeParts.join(" "); // In case there are multiple spaces, join them back
|
||||||
|
|
||||||
|
// Normalize the time part by ensuring there's a space before AM/PM if not already present
|
||||||
|
const normalizedTime = timePart.replace(/(\d{1,2})(:\d{2})?\s?(AM|PM)/, "$1$2 $3");
|
||||||
|
|
||||||
|
// Combine the date part with the normalized time part
|
||||||
|
return `${datePart} ${normalizedTime}`.trim();
|
||||||
|
};
|
||||||
|
|
||||||
const handleBlur = useCallback(
|
const handleBlur = useCallback(
|
||||||
(e) => {
|
(e) => {
|
||||||
if (!isManualInput) {
|
if (!isManualInput) {
|
||||||
@@ -30,29 +50,21 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is
|
|||||||
const v = e.target.value;
|
const v = e.target.value;
|
||||||
if (!v) return;
|
if (!v) return;
|
||||||
|
|
||||||
const upperV = v.toUpperCase();
|
const upperV = normalizeDateTimeString(v);
|
||||||
|
let parsedDate;
|
||||||
|
|
||||||
let _a;
|
for (const format of isDateOnly ? dateFormats : dateTimeFormats) {
|
||||||
|
parsedDate = dayjs(upperV, format);
|
||||||
for (const format of shorthandFormats) {
|
if (parsedDate.isValid()) break;
|
||||||
_a = dayjs(upperV, format);
|
|
||||||
if (_a.isValid()) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_a || !_a.isValid()) {
|
if (parsedDate && parsedDate.isValid()) {
|
||||||
for (const format of formats) {
|
|
||||||
_a = dayjs(upperV, format);
|
|
||||||
if (_a.isValid()) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_a && _a.isValid()) {
|
|
||||||
if (isDateOnly) {
|
if (isDateOnly) {
|
||||||
_a = _a.startOf("day");
|
parsedDate = parsedDate.startOf("day");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value && value.isValid && value.isValid()) {
|
if (value && value.isValid && value.isValid()) {
|
||||||
_a.set({
|
parsedDate = parsedDate.set({
|
||||||
hours: value.hours(),
|
hours: value.hours(),
|
||||||
minutes: value.minutes(),
|
minutes: value.minutes(),
|
||||||
seconds: value.seconds(),
|
seconds: value.seconds(),
|
||||||
@@ -61,13 +73,13 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (onlyFuture) {
|
if (onlyFuture) {
|
||||||
if (dayjs().subtract(1, "day").isBefore(_a)) {
|
if (dayjs().subtract(1, "day").isBefore(parsedDate)) {
|
||||||
onChange(_a);
|
onChange(parsedDate);
|
||||||
} else {
|
} else {
|
||||||
onChange(dayjs().startOf("day"));
|
onChange(dayjs().startOf("day"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onChange(_a);
|
onChange(parsedDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -79,6 +91,7 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is
|
|||||||
setIsManualInput(true);
|
setIsManualInput(true);
|
||||||
|
|
||||||
if (e.key.toLowerCase() === "t" && onChange) {
|
if (e.key.toLowerCase() === "t" && onChange) {
|
||||||
|
e.preventDefault();
|
||||||
setIsManualInput(false);
|
setIsManualInput(false);
|
||||||
onChange(dayjs());
|
onChange(dayjs());
|
||||||
} else if (e.key.toLowerCase() === "enter") {
|
} else if (e.key.toLowerCase() === "enter") {
|
||||||
@@ -115,6 +128,7 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is
|
|||||||
format={isDateOnly ? "MM/DD/YYYY" : "MM/DD/YYYY hh:mm a"}
|
format={isDateOnly ? "MM/DD/YYYY" : "MM/DD/YYYY hh:mm a"}
|
||||||
value={value ? dayjs(value) : null}
|
value={value ? dayjs(value) : null}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
placeholder={isDateOnly ? t("general.labels.date") : t("general.labels.datetime")}
|
||||||
onBlur={onBlur || handleBlur}
|
onBlur={onBlur || handleBlur}
|
||||||
disabledDate={handleDisabledDate}
|
disabledDate={handleDisabledDate}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,93 +1,96 @@
|
|||||||
export const shorthandFormats = [
|
export const dateTimeFormats = [
|
||||||
"M/D/YY hA",
|
// Four-digit year with time
|
||||||
"M/D/YY h:mmA",
|
"M/D/YYYY h:mm A", // Example: 1/5/2023 9:00 AM
|
||||||
"M/D/YYYY hA",
|
"M/D/YYYY h:mmA", // Example: 1/5/2023 9:00AM
|
||||||
"M/D/YYYY h:mmA",
|
"M/D/YYYY h A", // Example: 1/5/2023 9 AM
|
||||||
"M/D/YY ha",
|
"M/D/YYYY hA", // Example: 1/5/2023 9AM
|
||||||
"M/D/YY h:mma",
|
"M/D/YYYY hh:mm A", // Example: 1/5/2023 02:25 PM
|
||||||
"M/D/YYYY ha",
|
"M/D/YYYY hh:mm:ss A", // Example: 1/5/2023 02:25:45 PM
|
||||||
"M/D/YYYY h:mma"
|
|
||||||
|
"MM/D/YYYY h:mm A", // Example: 12/5/2023 9:00 AM
|
||||||
|
"MM/D/YYYY h:mmA", // Example: 12/5/2023 9:00AM
|
||||||
|
"MM/D/YYYY h A", // Example: 12/5/2023 9 AM
|
||||||
|
"MM/D/YYYY hA", // Example: 12/5/2023 9AM
|
||||||
|
"MM/D/YYYY hh:mm A", // Example: 12/5/2023 02:25 PM
|
||||||
|
"MM/D/YYYY hh:mm:ss A", // Example: 12/5/2023 02:25:45 PM
|
||||||
|
|
||||||
|
"M/DD/YYYY h:mm A", // Example: 1/25/2023 9:00 AM
|
||||||
|
"M/DD/YYYY h:mmA", // Example: 1/25/2023 9:00AM
|
||||||
|
"M/DD/YYYY h A", // Example: 1/25/2023 9 AM
|
||||||
|
"M/DD/YYYY hA", // Example: 1/25/2023 9AM
|
||||||
|
"M/DD/YYYY hh:mm A", // Example: 1/25/2023 02:25 PM
|
||||||
|
"M/DD/YYYY hh:mm:ss A", // Example: 1/25/2023 02:25:45 PM
|
||||||
|
|
||||||
|
"MM/DD/YYYY h:mm A", // Example: 12/25/2023 9:00 AM
|
||||||
|
"MM/DD/YYYY h:mmA", // Example: 12/25/2023 9:00AM
|
||||||
|
"MM/DD/YYYY h A", // Example: 12/25/2023 9 AM
|
||||||
|
"MM/DD/YYYY hA", // Example: 12/25/2023 9AM
|
||||||
|
"MM/DD/YYYY hh:mm A", // Example: 12/25/2023 02:25 PM
|
||||||
|
"MM/DD/YYYY hh:mm:ss A", // Example: 12/25/2023 02:25:45 PM
|
||||||
|
|
||||||
|
// Two-digit year with time
|
||||||
|
"M/D/YY h:mm A", // Example: 1/5/23 9:00 AM
|
||||||
|
"M/D/YY h:mmA", // Example: 1/5/23 9:00AM
|
||||||
|
"M/D/YY h A", // Example: 1/5/23 9 AM
|
||||||
|
"M/D/YY hA", // Example: 1/5/23 9AM
|
||||||
|
"M/D/YY hh:mm A", // Example: 1/5/23 02:25 PM
|
||||||
|
"M/D/YY hh:mm:ss A", // Example: 1/5/23 02:25:45 PM
|
||||||
|
|
||||||
|
"MM/D/YY h:mm A", // Example: 12/5/23 9:00 AM
|
||||||
|
"MM/D/YY h:mmA", // Example: 12/5/23 9:00AM
|
||||||
|
"MM/D/YY h A", // Example: 12/5/23 9 AM
|
||||||
|
"MM/D/YY hA", // Example: 12/5/23 9AM
|
||||||
|
"MM/D/YY hh:mm A", // Example: 12/5/23 02:25 PM
|
||||||
|
"MM/D/YY hh:mm:ss A", // Example: 12/5/23 02:25:45 PM
|
||||||
|
|
||||||
|
"M/DD/YY h:mm A", // Example: 1/25/23 9:00 AM
|
||||||
|
"M/DD/YY h:mmA", // Example: 1/25/23 9:00AM
|
||||||
|
"M/DD/YY h A", // Example: 1/25/23 9 AM
|
||||||
|
"M/DD/YY hA", // Example: 1/25/23 9AM
|
||||||
|
"M/DD/YY hh:mm A", // Example: 1/25/23 02:25 PM
|
||||||
|
"M/DD/YY hh:mm:ss A", // Example: 1/25/23 02:25:45 PM
|
||||||
|
|
||||||
|
"MM/DD/YY h:mm A", // Example: 12/25/23 9:00 AM
|
||||||
|
"MM/DD/YY h:mmA", // Example: 12/25/23 9:00AM
|
||||||
|
"MM/DD/YY h A", // Example: 12/25/23 9 AM
|
||||||
|
"MM/DD/YY hA", // Example: 12/25/23 9AM
|
||||||
|
"MM/DD/YY hh:mm A", // Example: 12/25/23 02:25 PM
|
||||||
|
"MM/DD/YY hh:mm:ss A", // Example: 12/25/23 02:25:45 PM
|
||||||
|
|
||||||
|
// Four-digit year without time
|
||||||
|
"M/D/YYYY", // Example: 1/5/2023
|
||||||
|
"MM/D/YYYY", // Example: 12/5/2023
|
||||||
|
"M/DD/YYYY", // Example: 1/25/2023
|
||||||
|
"MM/DD/YYYY", // Example: 12/25/2023
|
||||||
|
|
||||||
|
// Two-digit year without time
|
||||||
|
"M/D/YY", // Example: 1/5/23
|
||||||
|
"MM/D/YY", // Example: 12/5/23
|
||||||
|
"M/DD/YY", // Example: 1/25/23
|
||||||
|
"MM/DD/YY" // Example: 12/25/23
|
||||||
];
|
];
|
||||||
|
|
||||||
export const formats = [
|
// CONFIRMED
|
||||||
"MMDDYY",
|
export const dateFormats = [
|
||||||
"MMDDYYYY",
|
"MMDDYYYY",
|
||||||
"MM/DD/YY",
|
"MMDDYY",
|
||||||
"MM/DD/YYYY",
|
// Four-digit year
|
||||||
"M/DD/YY",
|
"M/D/YYYY", // Example: 1/5/2023
|
||||||
"M/DD/YYYY",
|
"MM/D/YYYY", // Example: 12/5/2023
|
||||||
"MM/D/YY",
|
"M/DD/YYYY", // Example: 1/25/2023
|
||||||
"MM/D/YYYY",
|
"MM/DD/YYYY", // Example: 12/25/2023
|
||||||
"M/D/YY",
|
|
||||||
"M/D/YYYY",
|
// Two-digit year
|
||||||
"D/MM/YY",
|
"M/D/YY", // Example: 1/5/23
|
||||||
"D/MM/YYYY",
|
"MM/D/YY", // Example: 12/5/23
|
||||||
"DD/M/YY",
|
"M/DD/YY", // Example: 1/25/23
|
||||||
"DD/M/YYYY",
|
"MM/DD/YY", // Example: 12/25/23
|
||||||
"D/M/YY",
|
|
||||||
"D/M/YYYY",
|
// Explicitly handle single-digit month and day
|
||||||
"MMDDYY hh:mm A",
|
"M/D/YY", // Example: 1/5/23
|
||||||
"MMDDYYYY hh:mm A",
|
"M/D/YYYY", // Example: 1/5/2023
|
||||||
"MM/DD/YY hh:mm A",
|
"M/DD/YY", // Example: 1/25/23
|
||||||
"MM/DD/YYYY hh:mm A",
|
"M/DD/YYYY", // Example: 1/25/2023
|
||||||
"M/DD/YY hh:mm A",
|
"MM/D/YY", // Example: 12/5/23
|
||||||
"M/DD/YYYY hh:mm A",
|
"MM/D/YYYY" // Example: 12/5/2023
|
||||||
"MM/D/YY hh:mm A",
|
|
||||||
"MM/D/YYYY hh:mm A",
|
|
||||||
"M/D/YY hh:mm A",
|
|
||||||
"M/D/YYYY hh:mm A",
|
|
||||||
"D/MM/YY hh:mm A",
|
|
||||||
"D/MM/YYYY hh:mm A",
|
|
||||||
"DD/M/YY hh:mm A",
|
|
||||||
"DD/M/YYYY hh:mm A",
|
|
||||||
"D/M/YY hh:mm A",
|
|
||||||
"D/M/YYYY hh:mm A",
|
|
||||||
"MMDDYY hh:mm:ss A",
|
|
||||||
"MMDDYYYY hh:mm:ss A",
|
|
||||||
"MM/DD/YY hh:mm:ss A",
|
|
||||||
"MM/DD/YYYY hh:mm:ss A",
|
|
||||||
"M/DD/YY hh:mm:ss A",
|
|
||||||
"M/DD/YYYY hh:mm:ss A",
|
|
||||||
"MM/D/YY hh:mm:ss A",
|
|
||||||
"MM/D/YYYY hh:mm:ss A",
|
|
||||||
"M/D/YY hh:mm:ss A",
|
|
||||||
"M/D/YYYY hh:mm:ss A",
|
|
||||||
"D/MM/YY hh:mm:ss A",
|
|
||||||
"D/MM/YYYY hh:mm:ss A",
|
|
||||||
"DD/M/YY hh:mm:ss A",
|
|
||||||
"DD/M/YYYY hh:mm:ss A",
|
|
||||||
"D/M/YY hh:mm:ss A",
|
|
||||||
"D/M/YYYY hh:mm:ss A",
|
|
||||||
"MMDDYY HH:mm",
|
|
||||||
"MMDDYYYY HH:mm",
|
|
||||||
"MM/DD/YY HH:mm",
|
|
||||||
"MM/DD/YYYY HH:mm",
|
|
||||||
"M/DD/YY HH:mm",
|
|
||||||
"M/DD/YYYY HH:mm",
|
|
||||||
"MM/D/YY HH:mm",
|
|
||||||
"MM/D/YYYY HH:mm",
|
|
||||||
"M/D/YY HH:mm",
|
|
||||||
"M/D/YYYY HH:mm",
|
|
||||||
"D/MM/YY HH:mm",
|
|
||||||
"D/MM/YYYY HH:mm",
|
|
||||||
"DD/M/YY HH:mm",
|
|
||||||
"DD/M/YYYY HH:mm",
|
|
||||||
"D/M/YY HH:mm",
|
|
||||||
"D/M/YYYY HH:mm",
|
|
||||||
"MMDDYY HH:mm:ss",
|
|
||||||
"MMDDYYYY HH:mm:ss",
|
|
||||||
"MM/DD/YY HH:mm:ss",
|
|
||||||
"MM/DD/YYYY HH:mm:ss",
|
|
||||||
"M/DD/YY HH:mm:ss",
|
|
||||||
"M/DD/YYYY HH:mm:ss",
|
|
||||||
"MM/D/YY HH:mm:ss",
|
|
||||||
"MM/D/YYYY HH:mm:ss",
|
|
||||||
"M/D/YY HH:mm:ss",
|
|
||||||
"M/D/YYYY HH:mm:ss",
|
|
||||||
"D/MM/YY HH:mm:ss",
|
|
||||||
"D/MM/YYYY HH:mm:ss",
|
|
||||||
"DD/M/YY HH:mm:ss",
|
|
||||||
"DD/M/YYYY HH:mm:ss",
|
|
||||||
"D/M/YY HH:mm:ss",
|
|
||||||
"D/M/YYYY HH:mm:ss"
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1189,6 +1189,8 @@
|
|||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"confirmpassword": "Confirm Password",
|
"confirmpassword": "Confirm Password",
|
||||||
"created_at": "Created At",
|
"created_at": "Created At",
|
||||||
|
"date": "Select Date",
|
||||||
|
"datetime": "Select Date & Time",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"errors": "Errors",
|
"errors": "Errors",
|
||||||
"excel": "Excel",
|
"excel": "Excel",
|
||||||
@@ -2737,7 +2739,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"constants":{
|
"constants": {
|
||||||
"main_profile": "Default"
|
"main_profile": "Default"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1189,6 +1189,8 @@
|
|||||||
"clear": "",
|
"clear": "",
|
||||||
"confirmpassword": "",
|
"confirmpassword": "",
|
||||||
"created_at": "",
|
"created_at": "",
|
||||||
|
"date": "",
|
||||||
|
"datetime": "",
|
||||||
"email": "",
|
"email": "",
|
||||||
"errors": "",
|
"errors": "",
|
||||||
"excel": "",
|
"excel": "",
|
||||||
@@ -2737,7 +2739,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"constants":{
|
"constants": {
|
||||||
"main_profile": ""
|
"main_profile": ""
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|||||||
Reference in New Issue
Block a user