2023-01-16 23:00:10 +01:00
|
|
|
import { ReactiveCache } from '/imports/reactiveCache';
|
2021-07-10 10:55:54 +02:00
|
|
|
import { TAPi18n } from '/imports/i18n';
|
2025-10-17 00:26:11 +03:00
|
|
|
import {
|
|
|
|
|
formatDateTime,
|
|
|
|
|
formatDate,
|
2025-10-23 01:00:11 +03:00
|
|
|
formatDateByUserPreference,
|
2025-10-17 00:26:11 +03:00
|
|
|
formatTime,
|
|
|
|
|
getISOWeek,
|
|
|
|
|
isValidDate,
|
|
|
|
|
isBefore,
|
|
|
|
|
isAfter,
|
|
|
|
|
isSame,
|
|
|
|
|
add,
|
|
|
|
|
subtract,
|
|
|
|
|
startOf,
|
|
|
|
|
endOf,
|
|
|
|
|
format,
|
|
|
|
|
parseDate,
|
|
|
|
|
now,
|
|
|
|
|
createDate,
|
|
|
|
|
fromNow,
|
|
|
|
|
calendar
|
|
|
|
|
} from '/imports/lib/dateUtils';
|
2021-07-10 10:55:54 +02:00
|
|
|
|
2025-10-17 00:26:11 +03:00
|
|
|
// Helper function to get time format for 24 hours
|
2021-02-11 03:54:12 +01:00
|
|
|
function adjustedTimeFormat() {
|
2025-10-17 00:26:11 +03:00
|
|
|
return 'HH:mm';
|
2021-02-11 03:54:12 +01:00
|
|
|
}
|
|
|
|
|
|
2025-05-25 00:11:09 +03:00
|
|
|
// .replace(/HH/i, 'H');
|
|
|
|
|
|
2021-04-06 18:00:03 +02:00
|
|
|
export class DatePicker extends BlazeComponent {
|
2018-05-18 10:24:51 +02:00
|
|
|
template() {
|
|
|
|
|
return 'datepicker';
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2017-10-14 01:38:25 +02:00
|
|
|
|
2019-10-28 08:25:55 +01:00
|
|
|
onCreated(defaultTime = '1970-01-01 08:00:00') {
|
2018-05-18 10:24:51 +02:00
|
|
|
this.error = new ReactiveVar('');
|
|
|
|
|
this.card = this.data();
|
2025-10-17 00:26:11 +03:00
|
|
|
this.date = new ReactiveVar(new Date('invalid'));
|
2019-10-24 12:57:07 +02:00
|
|
|
this.defaultTime = defaultTime;
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2017-10-14 01:38:25 +02:00
|
|
|
|
2020-04-22 14:44:08 +02:00
|
|
|
startDayOfWeek() {
|
2023-01-16 23:00:10 +01:00
|
|
|
const currentUser = ReactiveCache.getCurrentUser();
|
2020-04-22 14:44:08 +02:00
|
|
|
if (currentUser) {
|
|
|
|
|
return currentUser.getStartDayOfWeek();
|
|
|
|
|
} else {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2020-04-22 14:44:08 +02:00
|
|
|
|
2018-05-18 10:24:51 +02:00
|
|
|
onRendered() {
|
2025-10-23 01:00:11 +03:00
|
|
|
// Set initial values for text and time inputs
|
2025-10-17 00:26:11 +03:00
|
|
|
if (isValidDate(this.date.get())) {
|
2025-10-16 23:19:26 +03:00
|
|
|
const dateInput = this.find('#date');
|
|
|
|
|
const timeInput = this.find('#time');
|
|
|
|
|
|
|
|
|
|
if (dateInput) {
|
2025-10-23 01:00:11 +03:00
|
|
|
// Use user's preferred format for text input
|
|
|
|
|
const currentUser = ReactiveCache.getCurrentUser();
|
|
|
|
|
const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
|
|
|
|
dateInput.value = formatDateByUserPreference(this.date.get(), userFormat, false);
|
2025-10-16 23:19:26 +03:00
|
|
|
}
|
2025-10-23 01:00:11 +03:00
|
|
|
if (timeInput) {
|
|
|
|
|
if (!timeInput.value && this.defaultTime) {
|
|
|
|
|
const defaultDate = new Date(this.defaultTime);
|
|
|
|
|
timeInput.value = formatTime(defaultDate);
|
|
|
|
|
} else if (isValidDate(this.date.get())) {
|
|
|
|
|
timeInput.value = formatTime(this.date.get());
|
|
|
|
|
}
|
2025-10-16 23:19:26 +03:00
|
|
|
}
|
2018-05-18 10:24:51 +02:00
|
|
|
}
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2017-10-14 01:38:25 +02:00
|
|
|
|
2018-05-18 10:24:51 +02:00
|
|
|
showDate() {
|
2025-10-23 01:00:11 +03:00
|
|
|
if (isValidDate(this.date.get())) {
|
|
|
|
|
// Use user's preferred format for display, but HTML date input needs YYYY-MM-DD
|
|
|
|
|
const currentUser = ReactiveCache.getCurrentUser();
|
|
|
|
|
const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
|
|
|
|
return formatDateByUserPreference(this.date.get(), userFormat, false);
|
|
|
|
|
}
|
2018-05-18 10:24:51 +02:00
|
|
|
return '';
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2018-05-18 10:24:51 +02:00
|
|
|
showTime() {
|
2025-10-17 00:26:11 +03:00
|
|
|
if (isValidDate(this.date.get())) return formatTime(this.date.get());
|
2018-05-18 10:24:51 +02:00
|
|
|
return '';
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2018-05-18 10:24:51 +02:00
|
|
|
dateFormat() {
|
2025-10-23 01:00:11 +03:00
|
|
|
const currentUser = ReactiveCache.getCurrentUser();
|
|
|
|
|
const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
|
|
|
|
// Convert format to localized placeholder
|
|
|
|
|
switch (userFormat) {
|
|
|
|
|
case 'DD-MM-YYYY':
|
|
|
|
|
return TAPi18n.__('date-format-dd-mm-yyyy') || 'PP-KK-VVVV';
|
|
|
|
|
case 'MM-DD-YYYY':
|
|
|
|
|
return TAPi18n.__('date-format-mm-dd-yyyy') || 'KK-PP-VVVV';
|
|
|
|
|
case 'YYYY-MM-DD':
|
|
|
|
|
default:
|
|
|
|
|
return TAPi18n.__('date-format-yyyy-mm-dd') || 'VVVV-KK-PP';
|
|
|
|
|
}
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2018-05-18 10:24:51 +02:00
|
|
|
timeFormat() {
|
2025-10-17 00:26:11 +03:00
|
|
|
return 'LT';
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
2017-10-14 01:38:25 +02:00
|
|
|
|
2018-05-18 10:24:51 +02:00
|
|
|
events() {
|
2025-05-25 00:11:09 +03:00
|
|
|
return [
|
|
|
|
|
{
|
2025-10-16 23:19:26 +03:00
|
|
|
'change .js-date-field'() {
|
2025-10-23 01:00:11 +03:00
|
|
|
// Text input date validation
|
|
|
|
|
const dateInput = this.find('#date');
|
|
|
|
|
if (!dateInput) return;
|
|
|
|
|
|
|
|
|
|
const dateValue = dateInput.value;
|
2025-10-16 23:19:26 +03:00
|
|
|
if (dateValue) {
|
2025-10-23 01:00:11 +03:00
|
|
|
// Try to parse different date formats
|
|
|
|
|
const formats = [
|
|
|
|
|
'YYYY-MM-DD',
|
|
|
|
|
'DD-MM-YYYY',
|
|
|
|
|
'MM-DD-YYYY',
|
|
|
|
|
'DD/MM/YYYY',
|
|
|
|
|
'MM/DD/YYYY',
|
|
|
|
|
'DD.MM.YYYY',
|
|
|
|
|
'MM.DD.YYYY'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let parsedDate = null;
|
|
|
|
|
for (const format of formats) {
|
|
|
|
|
parsedDate = parseDate(dateValue, [format], true);
|
|
|
|
|
if (parsedDate) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fallback to native Date parsing
|
|
|
|
|
if (!parsedDate) {
|
|
|
|
|
parsedDate = new Date(dateValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isValidDate(parsedDate)) {
|
2025-10-16 23:19:26 +03:00
|
|
|
this.error.set('');
|
|
|
|
|
} else {
|
|
|
|
|
this.error.set('invalid-date');
|
|
|
|
|
}
|
2025-05-25 00:11:09 +03:00
|
|
|
}
|
|
|
|
|
},
|
2025-10-16 23:19:26 +03:00
|
|
|
'change .js-time-field'() {
|
|
|
|
|
// Native HTML time input validation
|
2025-10-23 01:00:11 +03:00
|
|
|
const timeInput = this.find('#time');
|
|
|
|
|
if (!timeInput) return;
|
|
|
|
|
|
|
|
|
|
const timeValue = timeInput.value;
|
2025-10-16 23:19:26 +03:00
|
|
|
if (timeValue) {
|
2025-10-17 00:26:11 +03:00
|
|
|
const timeObj = new Date(`1970-01-01T${timeValue}`);
|
|
|
|
|
if (isValidDate(timeObj)) {
|
2025-10-16 23:19:26 +03:00
|
|
|
this.error.set('');
|
|
|
|
|
} else {
|
|
|
|
|
this.error.set('invalid-time');
|
|
|
|
|
}
|
2025-05-25 00:11:09 +03:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
'submit .edit-date'(evt) {
|
|
|
|
|
evt.preventDefault();
|
|
|
|
|
|
2025-10-16 23:19:26 +03:00
|
|
|
const dateValue = evt.target.date.value;
|
|
|
|
|
const timeValue = evt.target.time.value || '12:00'; // Default to 12:00 if no time given
|
|
|
|
|
|
|
|
|
|
if (!dateValue) {
|
2025-05-25 00:11:09 +03:00
|
|
|
this.error.set('invalid-date');
|
|
|
|
|
evt.target.date.focus();
|
2025-10-16 23:19:26 +03:00
|
|
|
return;
|
2025-05-25 00:11:09 +03:00
|
|
|
}
|
2025-10-16 23:19:26 +03:00
|
|
|
|
2025-10-23 01:00:11 +03:00
|
|
|
// Try to parse different date formats
|
|
|
|
|
const formats = [
|
|
|
|
|
'YYYY-MM-DD',
|
|
|
|
|
'DD-MM-YYYY',
|
|
|
|
|
'MM-DD-YYYY',
|
|
|
|
|
'DD/MM/YYYY',
|
|
|
|
|
'MM/DD/YYYY',
|
|
|
|
|
'DD.MM.YYYY',
|
|
|
|
|
'MM.DD.YYYY'
|
|
|
|
|
];
|
2025-10-16 23:19:26 +03:00
|
|
|
|
2025-10-23 01:00:11 +03:00
|
|
|
let parsedDate = null;
|
|
|
|
|
for (const format of formats) {
|
|
|
|
|
parsedDate = parseDate(dateValue, [format], true);
|
|
|
|
|
if (parsedDate) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fallback to native Date parsing
|
|
|
|
|
if (!parsedDate) {
|
|
|
|
|
parsedDate = new Date(dateValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isValidDate(parsedDate)) {
|
2025-05-25 00:11:09 +03:00
|
|
|
this.error.set('invalid');
|
2025-10-16 23:19:26 +03:00
|
|
|
return;
|
2025-05-25 00:11:09 +03:00
|
|
|
}
|
2025-10-16 23:19:26 +03:00
|
|
|
|
2025-10-23 01:00:11 +03:00
|
|
|
// Combine with time
|
|
|
|
|
const timeObj = new Date(`1970-01-01T${timeValue}`);
|
|
|
|
|
if (!isValidDate(timeObj)) {
|
|
|
|
|
this.error.set('invalid-time');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set the time on the parsed date
|
|
|
|
|
parsedDate.setHours(timeObj.getHours(), timeObj.getMinutes(), 0, 0);
|
|
|
|
|
|
|
|
|
|
this._storeDate(parsedDate);
|
2025-10-16 23:19:26 +03:00
|
|
|
Popup.back();
|
2025-05-25 00:11:09 +03:00
|
|
|
},
|
|
|
|
|
'click .js-delete-date'(evt) {
|
|
|
|
|
evt.preventDefault();
|
|
|
|
|
this._deleteDate();
|
|
|
|
|
Popup.back();
|
|
|
|
|
},
|
2018-05-18 10:24:51 +02:00
|
|
|
},
|
2025-05-25 00:11:09 +03:00
|
|
|
];
|
2021-04-06 18:00:03 +02:00
|
|
|
}
|
|
|
|
|
}
|