@bigbinary/neeto-molecules 4.0.142 → 4.0.144

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -61,12 +61,17 @@ var yup__namespace = /*#__PURE__*/_interopNamespaceDefault(yup);
61
61
 
62
62
  var DAYS = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
63
63
  var DEFAULT_SLOT_INTERVAL = 30;
64
+ var HOUR_FORMATS = {
65
+ H24: "24h"};
66
+ var DEFAULT_HOUR_FORMAT = HOUR_FORMATS.H24;
64
67
 
65
68
  // To avoid prop drilling `allowAddPeriod` to `ScheduleRow` component
66
69
  // eslint-disable-next-line @bigbinary/neeto/use-zustand-for-global-state-management
67
70
  var ScheduleContext = /*#__PURE__*/React.createContext({
68
71
  allowAddPeriod: true,
69
- firstDay: 0
72
+ firstDay: 0,
73
+ slotInterval: DEFAULT_SLOT_INTERVAL,
74
+ hourFormat: DEFAULT_HOUR_FORMAT
70
75
  });
71
76
 
72
77
  var INTERVALS = ["year", "quarter", "month", "week", "day", "hour", "minute", "second"];
@@ -89,9 +94,10 @@ var BLUR_TEXT_WHEN_SELECT_MENU_IS_OPEN = {
89
94
  }
90
95
  };
91
96
  var SLOT_TIME_FORMAT = "hh:mm A";
97
+ var SLOT_TIME_FORMAT_24H = "HH:mm";
92
98
 
93
99
  // eslint-disable-next-line @bigbinary/neeto/use-standard-date-time-formats
94
- var END_OF_DAY = utils.dayjs().endOf("day").format(SLOT_TIME_FORMAT);
100
+ var END_OF_DAY = utils.dayjs().endOf("day").format(SLOT_TIME_FORMAT_24H);
95
101
 
96
102
  var DayjsRange = /*#__PURE__*/function () {
97
103
  function DayjsRange(startDate, endDate) {
@@ -129,7 +135,7 @@ var DayjsRange = /*#__PURE__*/function () {
129
135
  var endTime = this.endDate.add(1, "days");
130
136
  var allTimes = [];
131
137
  while (startTime < endTime) {
132
- allTimes.push(startTime.format(SLOT_TIME_FORMAT));
138
+ allTimes.push(startTime.format(SLOT_TIME_FORMAT_24H));
133
139
  startTime = startTime.add(interval, "minutes");
134
140
  }
135
141
  return allTimes;
@@ -195,7 +201,7 @@ yup__namespace.addMethod(yup__namespace.array, "ensureSlotsCantOverlap", functio
195
201
  });
196
202
  var isFromAndToSame = function isFromAndToSame(startTime, endTime) {
197
203
  if (!startTime || !endTime) return true;
198
- return utils.dayjs(startTime, SLOT_TIME_FORMAT).isSame(utils.dayjs(endTime, SLOT_TIME_FORMAT));
204
+ return utils.dayjs(startTime, SLOT_TIME_FORMAT_24H).isSame(utils.dayjs(endTime, SLOT_TIME_FORMAT_24H));
199
205
  };
200
206
  var sortDays = function sortDays(chosenIndex) {
201
207
  if (chosenIndex < 0 || chosenIndex >= 7) return DAYS;
@@ -235,7 +241,7 @@ var getTimeZoneAndTime = function getTimeZoneAndTime() {
235
241
  return "".concat(humanReadableTimezone, ": ").concat(utils.dayjs().tz(timeZone).format(SLOT_TIME_FORMAT));
236
242
  };
237
243
  var isTimeBehind = function isTimeBehind(timeA, timeB) {
238
- return utils.dayjs(timeA, SLOT_TIME_FORMAT).isBefore(utils.dayjs(timeB, SLOT_TIME_FORMAT));
244
+ return utils.dayjs(timeA, SLOT_TIME_FORMAT_24H).isBefore(utils.dayjs(timeB, SLOT_TIME_FORMAT_24H));
239
245
  };
240
246
  var sortPeriodsByKey = function sortPeriodsByKey(_ref) {
241
247
  var periods = _ref.periods,
@@ -276,8 +282,8 @@ var checkForOverlapBetweenPeriods = function checkForOverlapBetweenPeriods(perio
276
282
  value = _step$value[1];
277
283
  var seg1 = value;
278
284
  var seg2 = slotsSortedByStartTime[index + 1];
279
- var range1 = dayjsExtended.range(dayjsExtended(seg1.startTime, SLOT_TIME_FORMAT), dayjsExtended(seg1.endTime, SLOT_TIME_FORMAT));
280
- var range2 = dayjsExtended.range(dayjsExtended(seg2.startTime, SLOT_TIME_FORMAT), dayjsExtended(seg2.endTime, SLOT_TIME_FORMAT));
285
+ var range1 = dayjsExtended.range(dayjsExtended(seg1.startTime, SLOT_TIME_FORMAT_24H), dayjsExtended(seg1.endTime, SLOT_TIME_FORMAT_24H));
286
+ var range2 = dayjsExtended.range(dayjsExtended(seg2.startTime, SLOT_TIME_FORMAT_24H), dayjsExtended(seg2.endTime, SLOT_TIME_FORMAT_24H));
281
287
  if (range1.isOverlap(range2)) {
282
288
  response = {
283
289
  exists: true,
@@ -299,10 +305,10 @@ var findIndicesOfOverlappingRangesInPeriods = function findIndicesOfOverlappingR
299
305
  range2 = _ref2.range2,
300
306
  periods = _ref2.periods;
301
307
  var firstIndex = neetoCist.findIndexBy({
302
- startTime: range1.startDate.format(SLOT_TIME_FORMAT)
308
+ startTime: range1.startDate.format(SLOT_TIME_FORMAT_24H)
303
309
  }, periods);
304
310
  var secondIndex = periods.findIndex(function (slot, index) {
305
- return index > firstIndex && slot.startTime === range2.startDate.format(SLOT_TIME_FORMAT);
311
+ return index > firstIndex && slot.startTime === range2.startDate.format(SLOT_TIME_FORMAT_24H);
306
312
  });
307
313
  return {
308
314
  firstIndex: firstIndex,
@@ -365,13 +371,26 @@ var processFormValues = function processFormValues(values, firstDay) {
365
371
  })
366
372
  };
367
373
  };
374
+ var convert24hTo12h = function convert24hTo12h(time) {
375
+ return (
376
+ // eslint-disable-next-line @bigbinary/neeto/use-standard-date-time-formats
377
+ utils.dayjs(time, SLOT_TIME_FORMAT_24H).format(SLOT_TIME_FORMAT)
378
+ );
379
+ };
368
380
 
369
381
  var DisplayAvailability = function DisplayAvailability(_ref) {
370
382
  var periods = _ref.periods;
371
383
  var _useTranslation = reactI18next.useTranslation(),
372
384
  t = _useTranslation.t;
373
385
  var _useContext = React.useContext(ScheduleContext),
374
- firstDay = _useContext.firstDay;
386
+ firstDay = _useContext.firstDay,
387
+ hourFormat = _useContext.hourFormat;
388
+ var formatHour = function formatHour(hour) {
389
+ if (hourFormat === HOUR_FORMATS.H24) {
390
+ return hour;
391
+ }
392
+ return convert24hTo12h(hour);
393
+ };
375
394
  return /*#__PURE__*/jsxRuntime.jsx("div", {
376
395
  className: "flex w-full flex-col gap-y-3",
377
396
  children: sortDays(firstDay).map(function (day) {
@@ -400,7 +419,7 @@ var DisplayAvailability = function DisplayAvailability(_ref) {
400
419
  style: "h5",
401
420
  weight: "semibold",
402
421
  "data-testid": general.joinHyphenCase(day, period.startTime, "start-time-text"),
403
- children: period.startTime
422
+ children: formatHour(period.startTime)
404
423
  }), /*#__PURE__*/jsxRuntime.jsx(Typography, {
405
424
  className: "neeto-ui-text-gray-600",
406
425
  component: "span",
@@ -411,7 +430,7 @@ var DisplayAvailability = function DisplayAvailability(_ref) {
411
430
  style: "h5",
412
431
  weight: "semibold",
413
432
  "data-testid": general.joinHyphenCase(day, period.endTime, "start-time-text"),
414
- children: period.endTime
433
+ children: formatHour(period.endTime)
415
434
  })]
416
435
  }, period.id);
417
436
  }) : /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -429,16 +448,32 @@ var DisplayAvailability = function DisplayAvailability(_ref) {
429
448
 
430
449
  var buildSlotIntervals = function buildSlotIntervals(_ref) {
431
450
  var interval = _ref.interval,
432
- bookedSlots = _ref.bookedSlots;
451
+ bookedSlots = _ref.bookedSlots,
452
+ _ref$hourFormat = _ref.hourFormat,
453
+ hourFormat = _ref$hourFormat === void 0 ? DEFAULT_HOUR_FORMAT : _ref$hourFormat;
433
454
  var allIntervalsForADay = dayjsExtended.timeIntervalsForDay(interval);
434
455
  allIntervalsForADay.push(END_OF_DAY);
435
456
  return function (slotType) {
436
457
  var selectedValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
437
458
  var uniqBookedSlots = ramda.uniq(ramda.pluck(slotType, bookedSlots));
438
459
  var slotsAvailableForBooking = ramda.difference(allIntervalsForADay, uniqBookedSlots);
439
- var slots = slotsAvailableForBooking.map(neetoCist.toLabelAndValue);
460
+ var slots;
461
+ if (hourFormat === "12h") {
462
+ slots = slotsAvailableForBooking.map(function (value) {
463
+ return {
464
+ value: value,
465
+ label: convert24hTo12h(value)
466
+ };
467
+ });
468
+ } else {
469
+ slots = slotsAvailableForBooking.map(neetoCist.toLabelAndValue);
470
+ }
440
471
  if (!selectedValue) return slots;
441
- return sortSlots([neetoCist.toLabelAndValue(selectedValue)].concat(_toConsumableArray(slots)));
472
+ var selectedSlot = {
473
+ value: selectedValue,
474
+ label: hourFormat === "12h" ? convert24hTo12h(selectedValue) : selectedValue
475
+ };
476
+ return sortSlots([selectedSlot].concat(_toConsumableArray(slots)));
442
477
  };
443
478
  };
444
479
  var sortSlots = function sortSlots(slots) {
@@ -460,28 +495,33 @@ var filterSlots = function filterSlots(option, searchTerm) {
460
495
  };
461
496
  var formatCreateLabel = ramda.identity;
462
497
  var isValidTimeSlotOption = function isValidTimeSlotOption(value) {
463
- // Allow HH:MM AM/PM, H:MM AM/PM, H:MM am/pm, or HH:MM (24h)
464
- // Accepts 1 or 2 digit hour (1-12) with AM/PM OR 00-23:00-59 for 24h, AM/PM (any case) optional, optional leading zero
465
- // eslint-disable-next-line prettier/prettier
466
- var timeRegex = /^(((0?[1-9]|1[0-2]):[0-5]\d ?[AaPp][Mm])|([01]?\d|2[0-3]):[0-5]\d)$/;
467
- return timeRegex.test(value);
498
+ if (!value || typeof value !== "string") return false;
499
+ var valueTrimmed = value.trim();
500
+
501
+ // Try 24h format (e.g. "14:30")
502
+ var time = dayjsExtended(valueTrimmed, SLOT_TIME_FORMAT_24H, true);
503
+ if (time.isValid()) return true;
504
+
505
+ // Try 12h format with padded hour
506
+ time = dayjsExtended(valueTrimmed, SLOT_TIME_FORMAT, true);
507
+ return time.isValid();
468
508
  };
469
509
  var formatTimeSlotOption = function formatTimeSlotOption(v) {
470
- var value = (v || "").toUpperCase();
510
+ var value = v || "";
471
511
  if (neetoCist.isNotEmpty(value)) {
472
512
  // If value is in 24h format and missing AM/PM, convert to 12h with AM/PM
473
- var time24hMatch = value.match(/^([01]?\d|2[0-3]):([0-5]\d)$/);
474
- if (time24hMatch) {
475
- var _time24hMatch = _slicedToArray(time24hMatch, 3),
476
- hours = _time24hMatch[1],
477
- minutes = _time24hMatch[2];
478
- var hoursInt = parseInt(hours, 10);
479
- var suffix = hoursInt >= 12 ? "PM" : "AM";
480
- var hour12 = hoursInt % 12 || 12;
481
- value = "".concat(hour12.toString().padStart(2, "0"), ":").concat(minutes, " ").concat(suffix);
482
- } else if (value[1] === ":") {
483
- // Pad hour with 0 if single digit (legacy logic)
484
- value = "0".concat(value);
513
+ // Use dayjs to parse and format instead of manual regex, etc.
514
+ var parsed24h = dayjsExtended(value, SLOT_TIME_FORMAT_24H, true);
515
+ if (parsed24h.isValid()) {
516
+ value = parsed24h.format(SLOT_TIME_FORMAT_24H);
517
+ } else {
518
+ var parsed12h = dayjsExtended(value, SLOT_TIME_FORMAT, true);
519
+ if (parsed12h.isValid()) {
520
+ value = parsed12h.format(SLOT_TIME_FORMAT_24H);
521
+ } else if (value[1] === ":") {
522
+ // Pad hour with 0 if single digit (legacy logic)
523
+ value = "0".concat(value);
524
+ }
485
525
  }
486
526
  }
487
527
  return value;
@@ -493,19 +533,19 @@ var roundToNearestHour = function roundToNearestHour(time) {
493
533
  };
494
534
  var generateNewPeriod = function generateNewPeriod(periods, wday) {
495
535
  var lastEndTime = periods[periods.length - 1].endTime;
496
- var newStartTime = roundToNearestHour(dayjsExtended(lastEndTime, SLOT_TIME_FORMAT));
497
- var newEndTime = dayjsExtended(newStartTime, SLOT_TIME_FORMAT).add(1, "hour");
536
+ var newStartTime = roundToNearestHour(dayjsExtended(lastEndTime, SLOT_TIME_FORMAT_24H));
537
+ var newEndTime = dayjsExtended(newStartTime, SLOT_TIME_FORMAT_24H).add(1, "hour");
498
538
  return {
499
- startTime: dayjsExtended(newStartTime).format(SLOT_TIME_FORMAT),
500
- endTime: dayjsExtended(newEndTime).format(SLOT_TIME_FORMAT),
539
+ startTime: dayjsExtended(newStartTime).format(SLOT_TIME_FORMAT_24H),
540
+ endTime: dayjsExtended(newEndTime).format(SLOT_TIME_FORMAT_24H),
501
541
  wday: wday
502
542
  };
503
543
  };
504
544
  var addDefaultPeriod = function addDefaultPeriod(wday) {
505
545
  return {
506
546
  wday: wday,
507
- startTime: dayjsExtended().hour(9).minute(0).format(SLOT_TIME_FORMAT),
508
- endTime: dayjsExtended().hour(17).minute(0).format(SLOT_TIME_FORMAT)
547
+ startTime: dayjsExtended().hour(9).minute(0).format(SLOT_TIME_FORMAT_24H),
548
+ endTime: dayjsExtended().hour(17).minute(0).format(SLOT_TIME_FORMAT_24H)
509
549
  };
510
550
  };
511
551
 
@@ -517,15 +557,23 @@ var ScheduleRow = function ScheduleRow(_ref) {
517
557
  var bookedSlots = values.wdays[day].periods;
518
558
  var _useContext = React.useContext(ScheduleContext),
519
559
  allowAddPeriod = _useContext.allowAddPeriod,
520
- slotInterval = _useContext.slotInterval;
560
+ slotInterval = _useContext.slotInterval,
561
+ hourFormat = _useContext.hourFormat;
521
562
  var _useTranslation = reactI18next.useTranslation(),
522
563
  t = _useTranslation.t;
523
564
  var sortSlotsInterval = React.useMemo(function () {
524
565
  return buildSlotIntervals({
525
566
  interval: slotInterval,
526
- bookedSlots: bookedSlots
567
+ bookedSlots: bookedSlots,
568
+ hourFormat: hourFormat
527
569
  });
528
- }, [slotInterval, bookedSlots]);
570
+ }, [slotInterval, bookedSlots, hourFormat]);
571
+ var startTimeOptions = function startTimeOptions(period) {
572
+ return sortSlotsInterval("startTime", period === null || period === void 0 ? void 0 : period.startTime);
573
+ };
574
+ var endTimeOptions = function endTimeOptions(period) {
575
+ return sortSlotsInterval("endTime", period === null || period === void 0 ? void 0 : period.endTime);
576
+ };
529
577
  var handleChange = function handleChange(index, field, e) {
530
578
  var value = formatTimeSlotOption(e === null || e === void 0 ? void 0 : e.value);
531
579
  setFieldValue("wdays.".concat(day, ".periods[").concat(index, "].").concat(field), value);
@@ -566,11 +614,13 @@ var ScheduleRow = function ScheduleRow(_ref) {
566
614
  filterOption: filterSlots,
567
615
  isValidNewOption: isValidTimeSlotOption,
568
616
  name: "wdays.".concat(day, ".periods[").concat(index, "].startTime"),
617
+ options: startTimeOptions(period),
569
618
  placeholder: t("neetoMolecules.schedule.startTime"),
570
619
  strategy: "fixed",
571
620
  styles: BLUR_TEXT_WHEN_SELECT_MENU_IS_OPEN,
572
- options: sortSlotsInterval("startTime", period === null || period === void 0 ? void 0 : period.startTime),
573
- value: slotsSelectComponentDefaultValue(period === null || period === void 0 ? void 0 : period.startTime),
621
+ value: neetoCist.findBy({
622
+ value: period === null || period === void 0 ? void 0 : period.startTime
623
+ }, startTimeOptions(period)),
574
624
  onChange: function onChange(e) {
575
625
  return handleChange(index, "startTime", e);
576
626
  }
@@ -584,11 +634,13 @@ var ScheduleRow = function ScheduleRow(_ref) {
584
634
  filterOption: filterSlots,
585
635
  isValidNewOption: isValidTimeSlotOption,
586
636
  name: "wdays.".concat(day, ".periods[").concat(index, "].endTime"),
587
- options: sortSlotsInterval("endTime", period === null || period === void 0 ? void 0 : period.endTime),
637
+ options: endTimeOptions(period),
588
638
  placeholder: t("neetoMolecules.schedule.endTime"),
589
639
  strategy: "fixed",
590
640
  styles: BLUR_TEXT_WHEN_SELECT_MENU_IS_OPEN,
591
- value: slotsSelectComponentDefaultValue(period === null || period === void 0 ? void 0 : period.endTime),
641
+ value: neetoCist.findBy({
642
+ value: period === null || period === void 0 ? void 0 : period.endTime
643
+ }, endTimeOptions(period)),
592
644
  onChange: function onChange(e) {
593
645
  return handleChange(index, "endTime", e);
594
646
  }
@@ -924,7 +976,9 @@ var Schedule = /*#__PURE__*/React.forwardRef(function (_ref, scheduleRef) {
924
976
  _ref$showTimeZone = _ref.showTimeZone,
925
977
  showTimeZone = _ref$showTimeZone === void 0 ? true : _ref$showTimeZone,
926
978
  _ref$slotInterval = _ref.slotInterval,
927
- slotInterval = _ref$slotInterval === void 0 ? DEFAULT_SLOT_INTERVAL : _ref$slotInterval;
979
+ slotInterval = _ref$slotInterval === void 0 ? DEFAULT_SLOT_INTERVAL : _ref$slotInterval,
980
+ _ref$hourFormat = _ref.hourFormat,
981
+ hourFormat = _ref$hourFormat === void 0 ? DEFAULT_HOUR_FORMAT : _ref$hourFormat;
928
982
  var validationSchema = React.useMemo(getScheduleValidationSchema, []);
929
983
  var getInitialFormValues = function getInitialFormValues() {
930
984
  var isSubmitHandler = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
@@ -942,7 +996,8 @@ var Schedule = /*#__PURE__*/React.forwardRef(function (_ref, scheduleRef) {
942
996
  value: {
943
997
  allowAddPeriod: allowAddPeriod,
944
998
  firstDay: firstDay,
945
- slotInterval: slotInterval
999
+ slotInterval: slotInterval,
1000
+ hourFormat: hourFormat
946
1001
  },
947
1002
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
948
1003
  className: "neeto-molecules-schedule neeto-ui-border-gray-200 flex-shrink-0",