- enhancements / improvements / stuff
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
import { DatePicker } from "antd";
|
||||
import dayjs from "../../utils/day.js";
|
||||
import React, { useRef } from "react";
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
|
||||
const dateFormat = "MM/DD/YYYY h:mm a";
|
||||
|
||||
export function FormDateTimePickerEnhanced({
|
||||
bodyshop,
|
||||
value,
|
||||
onBlur,
|
||||
onlyFuture,
|
||||
onlyToday,
|
||||
isDateOnly = true,
|
||||
...restProps
|
||||
}) {
|
||||
const ref = useRef();
|
||||
return (
|
||||
<div>
|
||||
<DatePicker
|
||||
ref={ref}
|
||||
value={value ? dayjs(value) : null}
|
||||
format={dateFormat}
|
||||
onBlur={onBlur}
|
||||
showToday={false}
|
||||
disabledDate={(d) => {
|
||||
if (onlyToday) {
|
||||
return !dayjs().isSame(d, "day");
|
||||
} else if (onlyFuture) {
|
||||
return dayjs().subtract(1, "day").isAfter(d);
|
||||
}
|
||||
}}
|
||||
{...restProps}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(FormDateTimePickerEnhanced);
|
||||
@@ -1,205 +1,135 @@
|
||||
import React, { forwardRef, useState } from "react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { DatePicker } from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import { formats, shorthandFormats } from "./formats.js";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
// To be used as a form element only.
|
||||
|
||||
const DateTimePicker = (
|
||||
{ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps },
|
||||
ref
|
||||
) => {
|
||||
const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => {
|
||||
const [isManualInput, setIsManualInput] = useState(false);
|
||||
|
||||
const handleChange = (newDate) => {
|
||||
if (newDate && onChange) {
|
||||
onChange(newDate);
|
||||
}
|
||||
setIsManualInput(false); // Reset the manual input flag when using GUI
|
||||
};
|
||||
|
||||
const handleKeyDown = (e) => {
|
||||
setIsManualInput(true); // User is typing, so set the manual input flag
|
||||
|
||||
if (e.key.toLowerCase() === "t") {
|
||||
if (onChange) {
|
||||
onChange(dayjs());
|
||||
const handleChange = useCallback(
|
||||
(newDate) => {
|
||||
if (newDate === null && onChange) {
|
||||
onChange(null);
|
||||
} else if (newDate && onChange) {
|
||||
onChange(newDate);
|
||||
}
|
||||
} else if (e.key.toLowerCase() === "enter") {
|
||||
handleBlur(e);
|
||||
}
|
||||
};
|
||||
setIsManualInput(false);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const handleBlur = (e) => {
|
||||
if (!isManualInput) {
|
||||
// If the input is not manual, skip the format processing
|
||||
return;
|
||||
}
|
||||
const handleBlur = useCallback(
|
||||
(e) => {
|
||||
if (!isManualInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsManualInput(false); // Reset the flag after processing
|
||||
setIsManualInput(false);
|
||||
|
||||
const v = e.target.value;
|
||||
if (!v) return;
|
||||
const v = e.target.value;
|
||||
if (!v) return;
|
||||
|
||||
// Convert input to uppercase to handle 'am/pm' as well as 'AM/PM'
|
||||
const upperV = v.toUpperCase();
|
||||
const upperV = v.toUpperCase();
|
||||
|
||||
let _a;
|
||||
let _a;
|
||||
|
||||
// Handling common shorthand datetime inputs
|
||||
const shorthandFormats = [
|
||||
"M/D/YY hA",
|
||||
"M/D/YY h:mmA",
|
||||
"M/D/YYYY hA",
|
||||
"M/D/YYYY h:mmA",
|
||||
"M/D/YY ha",
|
||||
"M/D/YY h:mma",
|
||||
"M/D/YYYY ha",
|
||||
"M/D/YYYY h:mma"
|
||||
];
|
||||
|
||||
for (let format of shorthandFormats) {
|
||||
_a = dayjs(upperV, format);
|
||||
if (_a.isValid()) break;
|
||||
}
|
||||
|
||||
// If shorthand parsing didn't work, fall back to existing formats
|
||||
if (!_a || !_a.isValid()) {
|
||||
const formats = [
|
||||
"MMDDYY",
|
||||
"MMDDYYYY",
|
||||
"MM/DD/YY",
|
||||
"MM/DD/YYYY",
|
||||
"M/DD/YY",
|
||||
"M/DD/YYYY",
|
||||
"MM/D/YY",
|
||||
"MM/D/YYYY",
|
||||
"M/D/YY",
|
||||
"M/D/YYYY",
|
||||
"D/MM/YY",
|
||||
"D/MM/YYYY",
|
||||
"DD/M/YY",
|
||||
"DD/M/YYYY",
|
||||
"D/M/YY",
|
||||
"D/M/YYYY",
|
||||
"MMDDYY hh:mm A",
|
||||
"MMDDYYYY hh:mm A",
|
||||
"MM/DD/YY hh:mm A",
|
||||
"MM/DD/YYYY hh:mm A",
|
||||
"M/DD/YY hh:mm A",
|
||||
"M/DD/YYYY hh:mm A",
|
||||
"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"
|
||||
];
|
||||
|
||||
for (let format of formats) {
|
||||
for (const format of shorthandFormats) {
|
||||
_a = dayjs(upperV, format);
|
||||
if (_a.isValid()) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_a && _a.isValid()) {
|
||||
if (isDateOnly) {
|
||||
_a = _a.startOf("day"); // Only apply startOf("day") when isDateOnly is true
|
||||
}
|
||||
|
||||
if (value && value.isValid && value.isValid()) {
|
||||
_a.set({
|
||||
hours: value.hours(),
|
||||
minutes: value.minutes(),
|
||||
seconds: value.seconds(),
|
||||
milliseconds: value.milliseconds()
|
||||
});
|
||||
}
|
||||
|
||||
if (onlyFuture) {
|
||||
if (dayjs().subtract(1, "day").isBefore(_a)) {
|
||||
onChange(_a);
|
||||
} else {
|
||||
onChange(dayjs().startOf("day"));
|
||||
if (!_a || !_a.isValid()) {
|
||||
for (const format of formats) {
|
||||
_a = dayjs(upperV, format);
|
||||
if (_a.isValid()) break;
|
||||
}
|
||||
} else {
|
||||
onChange(_a);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (_a && _a.isValid()) {
|
||||
if (isDateOnly) {
|
||||
_a = _a.startOf("day");
|
||||
}
|
||||
|
||||
if (value && value.isValid && value.isValid()) {
|
||||
_a.set({
|
||||
hours: value.hours(),
|
||||
minutes: value.minutes(),
|
||||
seconds: value.seconds(),
|
||||
milliseconds: value.milliseconds()
|
||||
});
|
||||
}
|
||||
|
||||
if (onlyFuture) {
|
||||
if (dayjs().subtract(1, "day").isBefore(_a)) {
|
||||
onChange(_a);
|
||||
} else {
|
||||
onChange(dayjs().startOf("day"));
|
||||
}
|
||||
} else {
|
||||
onChange(_a);
|
||||
}
|
||||
}
|
||||
},
|
||||
[isManualInput, isDateOnly, onlyFuture, onChange, value]
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e) => {
|
||||
setIsManualInput(true);
|
||||
|
||||
if (e.key.toLowerCase() === "t" && onChange) {
|
||||
onChange(dayjs());
|
||||
} else if (e.key.toLowerCase() === "enter") {
|
||||
handleBlur(e);
|
||||
}
|
||||
},
|
||||
[onChange, handleBlur]
|
||||
);
|
||||
|
||||
const handleDisabledDate = useCallback(
|
||||
(current) => {
|
||||
if (onlyToday) {
|
||||
return !dayjs().isSame(current, "day");
|
||||
} else if (onlyFuture) {
|
||||
return dayjs().subtract(1, "day").isAfter(current);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[onlyToday, onlyFuture]
|
||||
);
|
||||
|
||||
return (
|
||||
<div onKeyDown={handleKeyDown} id={id} style={{ width: "100%" }}>
|
||||
<DatePicker
|
||||
ref={ref}
|
||||
showTime={isDateOnly ? false : { format: "hh:mm a", minuteStep: 15 }}
|
||||
showTime={
|
||||
isDateOnly
|
||||
? false
|
||||
: {
|
||||
format: "hh:mm a",
|
||||
minuteStep: 15,
|
||||
defaultValue: dayjs(dayjs(), "HH:mm:ss")
|
||||
}
|
||||
}
|
||||
format={isDateOnly ? "MM/DD/YYYY" : "MM/DD/YYYY hh:mm a"}
|
||||
value={value ? dayjs(value) : null}
|
||||
onChange={handleChange}
|
||||
onBlur={onBlur || handleBlur}
|
||||
disabledDate={(d) => {
|
||||
if (onlyToday) {
|
||||
return !dayjs().isSame(d, "day");
|
||||
} else if (onlyFuture) {
|
||||
return dayjs().subtract(1, "day").isAfter(d);
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
disabledDate={handleDisabledDate}
|
||||
{...restProps}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default forwardRef(DateTimePicker);
|
||||
DateTimePicker.propTypes = {
|
||||
value: PropTypes.any,
|
||||
onChange: PropTypes.func,
|
||||
onBlur: PropTypes.func,
|
||||
id: PropTypes.string,
|
||||
onlyFuture: PropTypes.bool,
|
||||
onlyToday: PropTypes.bool,
|
||||
isDateOnly: PropTypes.bool
|
||||
};
|
||||
|
||||
export default React.memo(DateTimePicker);
|
||||
|
||||
93
client/src/components/form-date-time-picker/formats.js
Normal file
93
client/src/components/form-date-time-picker/formats.js
Normal file
@@ -0,0 +1,93 @@
|
||||
export const shorthandFormats = [
|
||||
"M/D/YY hA",
|
||||
"M/D/YY h:mmA",
|
||||
"M/D/YYYY hA",
|
||||
"M/D/YYYY h:mmA",
|
||||
"M/D/YY ha",
|
||||
"M/D/YY h:mma",
|
||||
"M/D/YYYY ha",
|
||||
"M/D/YYYY h:mma"
|
||||
];
|
||||
|
||||
export const formats = [
|
||||
"MMDDYY",
|
||||
"MMDDYYYY",
|
||||
"MM/DD/YY",
|
||||
"MM/DD/YYYY",
|
||||
"M/DD/YY",
|
||||
"M/DD/YYYY",
|
||||
"MM/D/YY",
|
||||
"MM/D/YYYY",
|
||||
"M/D/YY",
|
||||
"M/D/YYYY",
|
||||
"D/MM/YY",
|
||||
"D/MM/YYYY",
|
||||
"DD/M/YY",
|
||||
"DD/M/YYYY",
|
||||
"D/M/YY",
|
||||
"D/M/YYYY",
|
||||
"MMDDYY hh:mm A",
|
||||
"MMDDYYYY hh:mm A",
|
||||
"MM/DD/YY hh:mm A",
|
||||
"MM/DD/YYYY hh:mm A",
|
||||
"M/DD/YY hh:mm A",
|
||||
"M/DD/YYYY hh:mm A",
|
||||
"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"
|
||||
];
|
||||
@@ -7,7 +7,6 @@ import dayjs from "../../utils/day";
|
||||
import { connect } from "react-redux";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx";
|
||||
import JobSearchSelectComponent from "../job-search-select/job-search-select.component.jsx";
|
||||
import { FormDateTimePickerEnhanced } from "../form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx";
|
||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -279,12 +278,7 @@ export function TaskUpsertModalComponent({
|
||||
}
|
||||
]}
|
||||
>
|
||||
<FormDateTimePickerEnhanced
|
||||
onlyFuture
|
||||
showTime
|
||||
minuteStep={15}
|
||||
presets={generatePresets(selectedJobDetails)}
|
||||
/>
|
||||
<DateTimePicker onlyFuture presets={generatePresets(selectedJobDetails)} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
Reference in New Issue
Block a user