datepicker.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { ReactiveCache } from '/imports/reactiveCache';
  2. import { TAPi18n } from '/imports/i18n';
  3. import {
  4. formatDateTime,
  5. formatDate,
  6. formatDateByUserPreference,
  7. formatTime,
  8. getISOWeek,
  9. isValidDate,
  10. isBefore,
  11. isAfter,
  12. isSame,
  13. add,
  14. subtract,
  15. startOf,
  16. endOf,
  17. format,
  18. parseDate,
  19. now,
  20. createDate,
  21. fromNow,
  22. calendar
  23. } from '/imports/lib/dateUtils';
  24. // Helper function to get time format for 24 hours
  25. function adjustedTimeFormat() {
  26. return 'HH:mm';
  27. }
  28. // .replace(/HH/i, 'H');
  29. export class DatePicker extends BlazeComponent {
  30. template() {
  31. return 'datepicker';
  32. }
  33. onCreated(defaultTime = '1970-01-01 08:00:00') {
  34. this.error = new ReactiveVar('');
  35. this.card = this.data();
  36. this.date = new ReactiveVar(new Date('invalid'));
  37. this.defaultTime = defaultTime;
  38. }
  39. startDayOfWeek() {
  40. const currentUser = ReactiveCache.getCurrentUser();
  41. if (currentUser) {
  42. return currentUser.getStartDayOfWeek();
  43. } else {
  44. return 1;
  45. }
  46. }
  47. onRendered() {
  48. // Set initial values for text and time inputs
  49. if (isValidDate(this.date.get())) {
  50. const dateInput = this.find('#date');
  51. const timeInput = this.find('#time');
  52. if (dateInput) {
  53. // Use user's preferred format for text input
  54. const currentUser = ReactiveCache.getCurrentUser();
  55. const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
  56. dateInput.value = formatDateByUserPreference(this.date.get(), userFormat, false);
  57. }
  58. if (timeInput) {
  59. if (!timeInput.value && this.defaultTime) {
  60. const defaultDate = new Date(this.defaultTime);
  61. timeInput.value = formatTime(defaultDate);
  62. } else if (isValidDate(this.date.get())) {
  63. timeInput.value = formatTime(this.date.get());
  64. }
  65. }
  66. }
  67. }
  68. showDate() {
  69. if (isValidDate(this.date.get())) {
  70. // Use user's preferred format for display, but HTML date input needs YYYY-MM-DD
  71. const currentUser = ReactiveCache.getCurrentUser();
  72. const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
  73. return formatDateByUserPreference(this.date.get(), userFormat, false);
  74. }
  75. return '';
  76. }
  77. showTime() {
  78. if (isValidDate(this.date.get())) return formatTime(this.date.get());
  79. return '';
  80. }
  81. dateFormat() {
  82. const currentUser = ReactiveCache.getCurrentUser();
  83. const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
  84. // Convert format to localized placeholder
  85. switch (userFormat) {
  86. case 'DD-MM-YYYY':
  87. return TAPi18n.__('date-format-dd-mm-yyyy') || 'PP-KK-VVVV';
  88. case 'MM-DD-YYYY':
  89. return TAPi18n.__('date-format-mm-dd-yyyy') || 'KK-PP-VVVV';
  90. case 'YYYY-MM-DD':
  91. default:
  92. return TAPi18n.__('date-format-yyyy-mm-dd') || 'VVVV-KK-PP';
  93. }
  94. }
  95. timeFormat() {
  96. return 'LT';
  97. }
  98. events() {
  99. return [
  100. {
  101. 'change .js-date-field'() {
  102. // Text input date validation
  103. const dateInput = this.find('#date');
  104. if (!dateInput) return;
  105. const dateValue = dateInput.value;
  106. if (dateValue) {
  107. // Try to parse different date formats
  108. const formats = [
  109. 'YYYY-MM-DD',
  110. 'DD-MM-YYYY',
  111. 'MM-DD-YYYY',
  112. 'DD/MM/YYYY',
  113. 'MM/DD/YYYY',
  114. 'DD.MM.YYYY',
  115. 'MM.DD.YYYY'
  116. ];
  117. let parsedDate = null;
  118. for (const format of formats) {
  119. parsedDate = parseDate(dateValue, [format], true);
  120. if (parsedDate) break;
  121. }
  122. // Fallback to native Date parsing
  123. if (!parsedDate) {
  124. parsedDate = new Date(dateValue);
  125. }
  126. if (isValidDate(parsedDate)) {
  127. this.error.set('');
  128. } else {
  129. this.error.set('invalid-date');
  130. }
  131. }
  132. },
  133. 'change .js-time-field'() {
  134. // Native HTML time input validation
  135. const timeInput = this.find('#time');
  136. if (!timeInput) return;
  137. const timeValue = timeInput.value;
  138. if (timeValue) {
  139. const timeObj = new Date(`1970-01-01T${timeValue}`);
  140. if (isValidDate(timeObj)) {
  141. this.error.set('');
  142. } else {
  143. this.error.set('invalid-time');
  144. }
  145. }
  146. },
  147. 'submit .edit-date'(evt) {
  148. evt.preventDefault();
  149. const dateValue = evt.target.date.value;
  150. const timeValue = evt.target.time.value || '12:00'; // Default to 12:00 if no time given
  151. if (!dateValue) {
  152. this.error.set('invalid-date');
  153. evt.target.date.focus();
  154. return;
  155. }
  156. // Try to parse different date formats
  157. const formats = [
  158. 'YYYY-MM-DD',
  159. 'DD-MM-YYYY',
  160. 'MM-DD-YYYY',
  161. 'DD/MM/YYYY',
  162. 'MM/DD/YYYY',
  163. 'DD.MM.YYYY',
  164. 'MM.DD.YYYY'
  165. ];
  166. let parsedDate = null;
  167. for (const format of formats) {
  168. parsedDate = parseDate(dateValue, [format], true);
  169. if (parsedDate) break;
  170. }
  171. // Fallback to native Date parsing
  172. if (!parsedDate) {
  173. parsedDate = new Date(dateValue);
  174. }
  175. if (!isValidDate(parsedDate)) {
  176. this.error.set('invalid');
  177. return;
  178. }
  179. // Combine with time
  180. const timeObj = new Date(`1970-01-01T${timeValue}`);
  181. if (!isValidDate(timeObj)) {
  182. this.error.set('invalid-time');
  183. return;
  184. }
  185. // Set the time on the parsed date
  186. parsedDate.setHours(timeObj.getHours(), timeObj.getMinutes(), 0, 0);
  187. this._storeDate(parsedDate);
  188. Popup.back();
  189. },
  190. 'click .js-delete-date'(evt) {
  191. evt.preventDefault();
  192. this._deleteDate();
  193. Popup.back();
  194. },
  195. },
  196. ];
  197. }
  198. }