Merge branch 'feature/IO-2834-Enhance-DateTime-Picker' into release/2024-08-23

This commit is contained in:
Dave Richer
2024-08-21 21:09:17 -04:00
5 changed files with 2234 additions and 2223 deletions

View File

@@ -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}

View File

@@ -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"
]; ];

View File

@@ -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

View File

@@ -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": {