@pisell/private-materials 6.11.650 → 6.11.652

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.
Files changed (40) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.js +18 -18
  6. package/build/lowcode/view.js +18 -18
  7. package/es/components/bigSale/components/BookingFloatingPanel/useBookingPanelController.js +0 -1
  8. package/es/components/bigSale/components/TimeBar/index.js +0 -1
  9. package/es/components/bigSale/dialog.js +0 -1
  10. package/es/components/bigSale/hooks/useBigSaleContext.js +0 -1
  11. package/es/components/bigSale/hooks/useSelectFloorMapResourceForBigSale.js +0 -1
  12. package/es/components/bigSale/index.js +0 -1
  13. package/es/components/bigSale/templates/Kiosk/index.js +0 -1
  14. package/es/components/sharedSecondaryBigSale/SharedSecondaryBigSaleReceiver.js +0 -1
  15. package/es/index.js +0 -2
  16. package/es/plus/pisellReservation/data/bookingToReservationTables.js +1 -1
  17. package/es/plus/pisellReservation/floorMap/floorPlanApi.js +1 -1
  18. package/es/plus/pisellReservation/floorMap/reservationMock.js +1 -1
  19. package/es/plus/saleDetail/Base.js +0 -1
  20. package/es/plus/saleDetail/components/Client/hooks/useClientSelectorProps.js +0 -1
  21. package/es/plus/saleDetail/components/DetailActions/index.js +0 -1
  22. package/es/plus/saleDetail/components/SummaryFinancialSections/index.js +0 -1
  23. package/es/plus/saleDetail/index.js +0 -1
  24. package/es/plus/saleDetail/tmpl/B/components/Dish/index.js +0 -1
  25. package/es/plus/saleDetail/tmpl/B/index.js +0 -1
  26. package/es/plus/salesSdk/utils/addProductWithFlowDebounced.js +1 -1
  27. package/es/plus/salesSdk/utils/bookingDate.js +1 -1
  28. package/es/plus/salesSdk/utils/customerAuthGate.js +1 -1
  29. package/es/plus/salesSdk/utils/enrichCartLineHolderDisplay.js +1 -1
  30. package/es/private-materials/lowcode/authmodal/meta.d.ts +1 -0
  31. package/es/pro/Login2.0/AuthModal.d.ts +1 -1
  32. package/es/pro/Login2.0/index.d.ts +1 -2
  33. package/es/pro/Login2.0/shared/types.d.ts +1 -1
  34. package/es/pro/skuDetailModal/flow/modules/time/index.js +155 -55
  35. package/es/pro/skuDetailModal/flow/modules/time/posCustomTime.js +59 -0
  36. package/lib/pro/skuDetailModal/flow/modules/time/index.js +155 -55
  37. package/lib/pro/skuDetailModal/flow/modules/time/posCustomTime.js +69 -0
  38. package/package.json +3 -3
  39. package/es/plus/pisellReservation/index.js +0 -17
  40. package/es/plus/salesSdk/index.js +0 -51
@@ -10,6 +10,7 @@ import { buildDraftCacheItem, getModuleOptions, getUnsupportedBookingFlowReason,
10
10
  import TimeResourceSelector from "../../../../../components/eventBooking/components/timeResourceSelector/index.js";
11
11
  import { resolveAvailabilityStatus } from "../../../../../components/eventBooking/components/bookingAvailabilityCalendar/utils.js";
12
12
  import { validateAvailabilityTimeAutoResolution } from "../autoResolution.js";
13
+ import { getAvailabilityCandidateDurationMinutes, getSessionPresetCandidates, isFlexibleDurationValue, isSameAvailabilityCandidateRange, resolvePosCustomTimeBaseMinutes, resolvePosCustomTimeCandidate, resolvePosCustomTimeDefaultDurationMinutes, resolvePosCustomTimeDefaultStartTime, shouldShowPosCustomTimeCandidateCards } from "./posCustomTime.js";
13
14
  import dayjs from "dayjs";
14
15
  import React, { useEffect, useMemo } from "react";
15
16
  import { Alert, Space } from "antd";
@@ -95,7 +96,18 @@ const getProductDurationMinutes = (context) => {
95
96
  const duration = (_normalizeDurationMin = normalizeDurationMinutesValue(product === null || product === void 0 ? void 0 : product.duration)) !== null && _normalizeDurationMin !== void 0 ? _normalizeDurationMin : normalizeDurationMinutesValue(product === null || product === void 0 ? void 0 : product.service_duration);
96
97
  return duration ? Math.floor(duration) : null;
97
98
  };
98
- const isPosDurationAvailabilityContext = (context) => context.services.presentationPlatform === "pos" && getProductDurationMinutes(context) !== null;
99
+ const isPosDurationAvailabilityContext = (context) => {
100
+ var _product$cartDetailVa2, _product$_extend2;
101
+ const product = context.draft.productData;
102
+ const isSession = Boolean(isSessionProduct(product) || (product === null || product === void 0 || (_product$cartDetailVa2 = product.cartDetailValue) === null || _product$cartDetailVa2 === void 0 ? void 0 : _product$cartDetailVa2.session) || (product === null || product === void 0 || (_product$_extend2 = product._extend) === null || _product$_extend2 === void 0 || (_product$_extend2 = _product$_extend2.other) === null || _product$_extend2 === void 0 ? void 0 : _product$_extend2.session));
103
+ return context.services.presentationPlatform === "pos" && !isSession && (getProductDurationMinutes(context) !== null || isFlexibleDurationValue(product === null || product === void 0 ? void 0 : product.duration));
104
+ };
105
+ const isPosSessionAvailabilityContext = (context) => {
106
+ var _product$cartDetailVa3, _product$_extend3;
107
+ const product = context.draft.productData;
108
+ return context.services.presentationPlatform === "pos" && Boolean(isSessionProduct(product) || (product === null || product === void 0 || (_product$cartDetailVa3 = product.cartDetailValue) === null || _product$cartDetailVa3 === void 0 ? void 0 : _product$cartDetailVa3.session) || (product === null || product === void 0 || (_product$_extend3 = product._extend) === null || _product$_extend3 === void 0 || (_product$_extend3 = _product$_extend3.other) === null || _product$_extend3 === void 0 ? void 0 : _product$_extend3.session));
109
+ };
110
+ const isPosCustomTimeAvailabilityContext = (context) => isPosDurationAvailabilityContext(context) || isPosSessionAvailabilityContext(context);
99
111
  const getDraftRangeDurationMinutes = (context) => {
100
112
  const { startDate, endDate, startTime, endTime } = context.draft.booking;
101
113
  const normalizedStartTime = normalizeStartTimeValue(startTime);
@@ -109,13 +121,13 @@ const getDraftRangeDurationMinutes = (context) => {
109
121
  };
110
122
  const getAvailabilityDurationOverride = (context, durationOverride) => {
111
123
  var _ref, _ref2, _normalizeDurationMin2;
112
- if (!isPosDurationAvailabilityContext(context)) return void 0;
124
+ if (!isPosCustomTimeAvailabilityContext(context)) return void 0;
113
125
  const duration = (_ref = (_ref2 = (_normalizeDurationMin2 = normalizeDurationMinutesValue(durationOverride)) !== null && _normalizeDurationMin2 !== void 0 ? _normalizeDurationMin2 : normalizeDurationMinutesValue(context.draft.booking.duration)) !== null && _ref2 !== void 0 ? _ref2 : getDraftRangeDurationMinutes(context)) !== null && _ref !== void 0 ? _ref : getProductDurationMinutes(context);
114
126
  return duration && duration > 0 ? Math.floor(duration) : void 0;
115
127
  };
116
128
  const getAvailabilityStartTimeOverride = (context, startTimeOverride) => {
117
129
  var _normalizeStartTimeVa;
118
- if (!isPosDurationAvailabilityContext(context)) return void 0;
130
+ if (!isPosCustomTimeAvailabilityContext(context)) return void 0;
119
131
  return ((_normalizeStartTimeVa = normalizeStartTimeValue(startTimeOverride)) !== null && _normalizeStartTimeVa !== void 0 ? _normalizeStartTimeVa : normalizeStartTimeValue(context.draft.booking.startTime)) || void 0;
120
132
  };
121
133
  /**
@@ -150,20 +162,23 @@ const finalizeCandidateWithoutResourceStep = function() {
150
162
  };
151
163
  }();
152
164
  const refreshAvailabilityTimes = function() {
153
- var _ref4 = _asyncToGenerator(function* (context, module, durationOverride, startTimeOverride) {
154
- var _context$getModuleDat2;
165
+ var _ref5 = _asyncToGenerator(function* (context, module, options = {}) {
166
+ var _context$getModuleDat2, _ref4;
167
+ const { durationOverride, startTimeOverride, selectionIntent = "restore" } = options;
155
168
  const availability = context.services.availability;
156
169
  const allowUnavailable = context.services.allowUnavailableBookingSelection === true;
157
170
  const posDurationAvailability = isPosDurationAvailabilityContext(context);
171
+ const posSessionAvailability = isPosSessionAvailabilityContext(context);
172
+ const posCustomTimeAvailability = posDurationAvailability || posSessionAvailability;
158
173
  const requestedDuration = getAvailabilityDurationOverride(context, durationOverride);
159
174
  const requestedStartTime = getAvailabilityStartTimeOverride(context, startTimeOverride);
160
175
  const selectedDate = context.draft.booking.startDate.format("YYYY-MM-DD");
161
176
  const requestId = Date.now() + Math.random();
162
- const posDurationHydrationKey = posDurationAvailability && requestedDuration && requestedStartTime ? `${selectedDate}|${requestedStartTime}|${requestedDuration}` : void 0;
177
+ const posCustomTimeHydrationKey = posCustomTimeAvailability && requestedDuration && requestedStartTime ? `${selectedDate}|${requestedStartTime}|${requestedDuration}` : void 0;
163
178
  context.setModuleData(module.key, {
164
179
  requestId,
165
180
  timeSlots: [],
166
- posDurationHydrationKey
181
+ posCustomTimeHydrationKey
167
182
  });
168
183
  const group = (yield availability.getProductTimeRanges(availability.contextId, _objectSpread2({
169
184
  productIds: [availability.productId],
@@ -174,6 +189,39 @@ const refreshAvailabilityTimes = function() {
174
189
  partySize: resolveSelectionFlowQueryPartySize(context.draft, availability.partySize)
175
190
  }, requestedDuration ? _objectSpread2({ durationMinutesByProductId: { [String(availability.productId)]: requestedDuration } }, requestedStartTime ? { durationStartTimesByProductId: { [String(availability.productId)]: [requestedStartTime] } } : {}) : {}))).find((item) => String(item.productId) === String(availability.productId));
176
191
  const candidates = (group === null || group === void 0 ? void 0 : group.ranges) || [];
192
+ const product = context.draft.productData;
193
+ if (posDurationAvailability && selectionIntent === "restore" && isFlexibleDurationValue(product === null || product === void 0 ? void 0 : product.duration)) {
194
+ var _context$hostContext, _moduleOptions$slice, _normalizeDurationMin3;
195
+ const moduleOptions = getModuleOptions(module);
196
+ const configuredSlice = (_context$hostContext = context.hostContext) === null || _context$hostContext === void 0 || (_context$hostContext = _context$hostContext.bookingConfig) === null || _context$hostContext === void 0 || (_context$hostContext = _context$hostContext.config) === null || _context$hostContext === void 0 || (_context$hostContext = _context$hostContext.basic) === null || _context$hostContext === void 0 ? void 0 : _context$hostContext.service_time;
197
+ const fallbackSlice = (_moduleOptions$slice = moduleOptions.slice) !== null && _moduleOptions$slice !== void 0 ? _moduleOptions$slice : typeof configuredSlice === "object" ? configuredSlice === null || configuredSlice === void 0 ? void 0 : configuredSlice.value : configuredSlice;
198
+ const baseDurationMinutes = resolvePosCustomTimeBaseMinutes(group === null || group === void 0 ? void 0 : group.slotStepMinutes, fallbackSlice);
199
+ const nextStartTime = resolvePosCustomTimeDefaultStartTime(context.draft.booking.startTime, baseDurationMinutes);
200
+ const nextDuration = resolvePosCustomTimeDefaultDurationMinutes((_normalizeDurationMin3 = normalizeDurationMinutesValue(context.draft.booking.duration)) !== null && _normalizeDurationMin3 !== void 0 ? _normalizeDurationMin3 : context.draft.booking.duration, baseDurationMinutes);
201
+ const changedFields = [];
202
+ if (nextStartTime !== context.draft.booking.startTime) changedFields.push("booking.startTime");
203
+ if (nextDuration !== context.draft.booking.duration) changedFields.push("booking.duration");
204
+ if (context.draft.booking.selectedCandidate) changedFields.push("booking.selectedCandidate");
205
+ if (context.draft.booking.commitCandidate) changedFields.push("booking.commitCandidate");
206
+ if (changedFields.length > 0 && nextStartTime) {
207
+ context.updateDraft({ booking: {
208
+ startTime: nextStartTime,
209
+ duration: nextDuration,
210
+ selectedCandidate: void 0,
211
+ commitCandidate: void 0
212
+ } }, {
213
+ changedFields,
214
+ sourceModuleKey: module.key,
215
+ sourceModuleType: "time"
216
+ });
217
+ yield refreshAvailabilityTimes(context, module, {
218
+ durationOverride: nextDuration,
219
+ startTimeOverride: nextStartTime,
220
+ selectionIntent: "custom"
221
+ });
222
+ return;
223
+ }
224
+ }
177
225
  if (candidates.length === 0) {
178
226
  var _context$getModuleDat;
179
227
  if (((_context$getModuleDat = context.getModuleData(module.key)) === null || _context$getModuleDat === void 0 ? void 0 : _context$getModuleDat.requestId) !== requestId) return;
@@ -182,7 +230,7 @@ const refreshAvailabilityTimes = function() {
182
230
  timeSlots: [],
183
231
  selectedCandidate: void 0,
184
232
  slotStepMinutes: group === null || group === void 0 ? void 0 : group.slotStepMinutes,
185
- posDurationHydrationKey
233
+ posCustomTimeHydrationKey
186
234
  });
187
235
  return;
188
236
  }
@@ -199,17 +247,42 @@ const refreshAvailabilityTimes = function() {
199
247
  const draftStartTime = normalizeStartTimeValue(context.draft.booking.startTime);
200
248
  const draftEndTime = normalizeStartTimeValue(context.draft.booking.endTime);
201
249
  const requestedPosStartTime = requestedStartTime || draftStartTime;
202
- const restoredDraftCandidate = draftStartTime ? times.find((candidate) => isAvailabilityCandidateSelectable(candidate, allowUnavailable) && isSameCandidateStart(candidate, selectedDate, draftStartTime) && (posDurationAvailability || normalizeStartTimeValue(candidate.endTime) === draftEndTime)) : void 0;
203
- const restoredExistingCandidate = existingCandidate ? times.find((candidate) => isAvailabilityCandidateSelectable(candidate, allowUnavailable) && (candidate.key === existingCandidate.key || posDurationAvailability && isSameCandidateStart(candidate, existingCandidate.date, normalizeStartTimeValue(existingCandidate.startTime)))) : void 0;
204
- const fallbackOsCandidate = posDurationAvailability && requestedPosStartTime ? candidates.find((candidate) => isSameCandidateStart(candidate, selectedDate, requestedPosStartTime)) : void 0;
205
- const restoredCandidate = restoredDraftCandidate || restoredExistingCandidate || fallbackOsCandidate;
250
+ const requestedPosDuration = (_ref4 = requestedDuration !== null && requestedDuration !== void 0 ? requestedDuration : normalizeDurationMinutesValue(context.draft.booking.duration)) !== null && _ref4 !== void 0 ? _ref4 : getDraftRangeDurationMinutes(context);
251
+ const restoredDraftCandidate = draftStartTime ? times.find((candidate) => isAvailabilityCandidateSelectable(candidate, allowUnavailable) && (posSessionAvailability ? isSameAvailabilityCandidateRange(candidate, {
252
+ date: selectedDate,
253
+ startTime: draftStartTime,
254
+ durationMinutes: requestedPosDuration
255
+ }) : isSameCandidateStart(candidate, selectedDate, draftStartTime) && (posDurationAvailability || normalizeStartTimeValue(candidate.endTime) === draftEndTime))) : void 0;
256
+ const restoredExistingCandidate = existingCandidate ? times.find((candidate) => isAvailabilityCandidateSelectable(candidate, allowUnavailable) && (candidate.key === existingCandidate.key || (posSessionAvailability ? candidate.source === existingCandidate.source && isSameAvailabilityCandidateRange(candidate, {
257
+ date: existingCandidate.date,
258
+ startTime: normalizeStartTimeValue(existingCandidate.startTime),
259
+ durationMinutes: getAvailabilityCandidateDurationMinutes(existingCandidate)
260
+ }) : posDurationAvailability && isSameCandidateStart(candidate, existingCandidate.date, normalizeStartTimeValue(existingCandidate.startTime))))) : void 0;
261
+ const fallbackOsCandidate = posCustomTimeAvailability && requestedPosStartTime ? candidates.find((candidate) => posSessionAvailability ? isSameAvailabilityCandidateRange(candidate, {
262
+ date: selectedDate,
263
+ startTime: requestedPosStartTime,
264
+ durationMinutes: requestedPosDuration
265
+ }) : isSameCandidateStart(candidate, selectedDate, requestedPosStartTime)) : void 0;
266
+ const customSelectionIntent = posCustomTimeAvailability && selectionIntent === "custom";
267
+ const restoredCandidate = resolvePosCustomTimeCandidate({
268
+ candidates: times.filter((candidate) => isAvailabilityCandidateSelectable(candidate, allowUnavailable)),
269
+ customSelectionIntent,
270
+ requestedCustomRange: customSelectionIntent && requestedPosStartTime && requestedPosDuration ? {
271
+ date: selectedDate,
272
+ startTime: requestedPosStartTime,
273
+ durationMinutes: requestedPosDuration
274
+ } : void 0,
275
+ restoredDraftCandidate,
276
+ restoredExistingCandidate,
277
+ fallbackCandidate: fallbackOsCandidate
278
+ });
206
279
  const normallySelectableCandidates = times.filter((candidate) => isAvailabilityCandidateSelectable(candidate));
207
280
  const selectableCandidates = normallySelectableCandidates.length > 0 || !allowUnavailable ? normallySelectableCandidates : times;
208
- const initialCandidate = restoredCandidate || (posDurationAvailability && Boolean(requestedPosStartTime) ? void 0 : selectableCandidates[0]);
281
+ const initialCandidate = restoredCandidate || (posCustomTimeAvailability && Boolean(requestedPosStartTime && requestedPosDuration) ? void 0 : selectableCandidates[0]);
209
282
  context.setModuleData(module.key, {
210
283
  requestId,
211
284
  slotStepMinutes: group === null || group === void 0 ? void 0 : group.slotStepMinutes,
212
- timeSlots: times.map((candidate) => ({
285
+ timeSlots: (posSessionAvailability ? getSessionPresetCandidates(times) : times).map((candidate) => ({
213
286
  id: candidate.key,
214
287
  start_time: candidate.startTime,
215
288
  end_time: candidate.endTime,
@@ -219,9 +292,9 @@ const refreshAvailabilityTimes = function() {
219
292
  candidate
220
293
  })),
221
294
  selectedCandidate: initialCandidate,
222
- posDurationHydrationKey
295
+ posCustomTimeHydrationKey
223
296
  });
224
- const shouldWriteInitialCandidate = Boolean(initialCandidate) && (posDurationAvailability || !existingCandidate || initialCandidate.key !== existingCandidate.key);
297
+ const shouldWriteInitialCandidate = Boolean(initialCandidate) && (posCustomTimeAvailability || !existingCandidate || initialCandidate.key !== existingCandidate.key);
225
298
  if (initialCandidate && shouldWriteInitialCandidate) {
226
299
  const startAt = dayjs(initialCandidate.startAt);
227
300
  const endAt = dayjs(initialCandidate.endAt);
@@ -249,8 +322,8 @@ const refreshAvailabilityTimes = function() {
249
322
  }
250
323
  if (initialCandidate && !hasCompiledResourceModule(context)) yield finalizeCandidateWithoutResourceStep(context, initialCandidate);
251
324
  });
252
- return function refreshAvailabilityTimes(_x3, _x4, _x5, _x6) {
253
- return _ref4.apply(this, arguments);
325
+ return function refreshAvailabilityTimes(_x3, _x4) {
326
+ return _ref5.apply(this, arguments);
254
327
  };
255
328
  }();
256
329
  const hasDurationValue = (value) => typeof value === "number" && value > 0 || typeof value === "string" && value.length > 0;
@@ -328,7 +401,7 @@ const getFlexibleDuration = (timeObj) => {
328
401
  return (timeObj === null || timeObj === void 0 || (_timeObj$durationSlic = timeObj.durationSlicesBasedOnTime) === null || _timeObj$durationSlic === void 0 || (_timeObj$durationSlic = _timeObj$durationSlic.find((item) => typeof (item === null || item === void 0 ? void 0 : item.value) === "string" && item.value.startsWith("flexible_") && !item.disabled)) === null || _timeObj$durationSlic === void 0 ? void 0 : _timeObj$durationSlic.value) || (timeObj === null || timeObj === void 0 || (_timeObj$durationSlic2 = timeObj.durationSlicesBasedOnTime) === null || _timeObj$durationSlic2 === void 0 || (_timeObj$durationSlic2 = _timeObj$durationSlic2.find((item) => typeof (item === null || item === void 0 ? void 0 : item.value) === "string" && item.value.startsWith("flexible_"))) === null || _timeObj$durationSlic2 === void 0 ? void 0 : _timeObj$durationSlic2.value);
329
402
  };
330
403
  const resolveInitialDuration = (context) => {
331
- var _context$services$get, _context$services, _serviceCacheItem$_ex, _serviceCacheItem$_ex2, _context$draft$produc, _context$draft$produc2, _timeObj$durationSlic3, _ref5, _configuredOption$val, _timeObj$durationSlic4;
404
+ var _context$services$get, _context$services, _serviceCacheItem$_ex, _serviceCacheItem$_ex2, _context$draft$produc, _context$draft$produc2, _timeObj$durationSlic3, _ref6, _configuredOption$val, _timeObj$durationSlic4;
332
405
  if (hasDurationValue(context.draft.booking.duration)) return context.draft.booking.duration;
333
406
  const serviceCacheItem = (_context$services$get = (_context$services = context.services).getCurrentCacheItem) === null || _context$services$get === void 0 ? void 0 : _context$services$get.call(_context$services);
334
407
  const existingDuration = normalizeSelectionDuration((_serviceCacheItem$_ex = serviceCacheItem === null || serviceCacheItem === void 0 || (_serviceCacheItem$_ex2 = serviceCacheItem._extend) === null || _serviceCacheItem$_ex2 === void 0 ? void 0 : _serviceCacheItem$_ex2.duration) !== null && _serviceCacheItem$_ex !== void 0 ? _serviceCacheItem$_ex : (_context$draft$produc = context.draft.productData) === null || _context$draft$produc === void 0 || (_context$draft$produc = _context$draft$produc._extend) === null || _context$draft$produc === void 0 ? void 0 : _context$draft$produc.duration);
@@ -340,7 +413,7 @@ const resolveInitialDuration = (context) => {
340
413
  if (hasDurationValue(normalizedDuration)) return normalizedDuration;
341
414
  const configuredValue = productDuration === null || productDuration === void 0 ? void 0 : productDuration.value;
342
415
  const configuredOption = timeObj === null || timeObj === void 0 || (_timeObj$durationSlic3 = timeObj.durationSlicesBasedOnTime) === null || _timeObj$durationSlic3 === void 0 ? void 0 : _timeObj$durationSlic3.find((item) => (item === null || item === void 0 ? void 0 : item.value) == configuredValue);
343
- return (_ref5 = (_configuredOption$val = configuredOption === null || configuredOption === void 0 ? void 0 : configuredOption.value) !== null && _configuredOption$val !== void 0 ? _configuredOption$val : timeObj === null || timeObj === void 0 || (_timeObj$durationSlic4 = timeObj.durationSlicesBasedOnTime) === null || _timeObj$durationSlic4 === void 0 || (_timeObj$durationSlic4 = _timeObj$durationSlic4[0]) === null || _timeObj$durationSlic4 === void 0 ? void 0 : _timeObj$durationSlic4.value) !== null && _ref5 !== void 0 ? _ref5 : null;
416
+ return (_ref6 = (_configuredOption$val = configuredOption === null || configuredOption === void 0 ? void 0 : configuredOption.value) !== null && _configuredOption$val !== void 0 ? _configuredOption$val : timeObj === null || timeObj === void 0 || (_timeObj$durationSlic4 = timeObj.durationSlicesBasedOnTime) === null || _timeObj$durationSlic4 === void 0 || (_timeObj$durationSlic4 = _timeObj$durationSlic4[0]) === null || _timeObj$durationSlic4 === void 0 ? void 0 : _timeObj$durationSlic4.value) !== null && _ref6 !== void 0 ? _ref6 : null;
344
417
  };
345
418
  const deriveTimeBooking = (context, startTime, duration) => {
346
419
  let nextDuration = duration;
@@ -387,7 +460,7 @@ const refreshTimeModule = (context, module) => {
387
460
  });
388
461
  };
389
462
  const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
390
- var _context$moduleState$2, _context$moduleState$3, _context$moduleState$4, _context$hostContext, _options$slice, _durationProps$select2, _options$durationSele2;
463
+ var _context$moduleState$2, _context$moduleState$3, _context$moduleState$4, _context$hostContext2, _options$slice, _durationProps$select2, _options$durationSele2;
391
464
  const options = getModuleOptions(module);
392
465
  const unsupportedReason = getUnsupportedBookingFlowReason(context.draft.productData);
393
466
  const required = options.required !== false;
@@ -395,7 +468,9 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
395
468
  const duration = context.draft.booking.duration;
396
469
  const useAvailability = options.mode === "availability";
397
470
  const productDurationMinutes = getProductDurationMinutes(context);
398
- const usePosDurationAvailability = useAvailability && isPosDurationAvailabilityContext(context) && Boolean(productDurationMinutes);
471
+ const usePosDurationAvailability = useAvailability && isPosDurationAvailabilityContext(context);
472
+ const usePosSessionAvailability = useAvailability && isPosSessionAvailabilityContext(context);
473
+ const usePosCustomTimeAvailability = usePosDurationAvailability || usePosSessionAvailability;
399
474
  const availability = useAvailability ? context.services.availability : void 0;
400
475
  const availabilityData = context.getModuleData(module.key);
401
476
  const capacityDisplaySettings = getCapacityDisplaySettings(context.hostContext);
@@ -405,7 +480,7 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
405
480
  const dateModule = context.steps.flatMap((step) => step.modules).find((item) => item.type === "date");
406
481
  const isDateModuleLoading = dateModule ? ((_context$moduleState$3 = context.moduleState[dateModule.key]) === null || _context$moduleState$3 === void 0 ? void 0 : _context$moduleState$3.status) === "loading" : false;
407
482
  const hasNoSelectableAvailabilityDate = Boolean(useAvailability && dateModule && ((_context$moduleState$4 = context.moduleState[dateModule.key]) === null || _context$moduleState$4 === void 0 ? void 0 : _context$moduleState$4.status) === "ready" && !isAvailabilityDateReadyForTime(context));
408
- const configuredSlice = (_context$hostContext = context.hostContext) === null || _context$hostContext === void 0 || (_context$hostContext = _context$hostContext.bookingConfig) === null || _context$hostContext === void 0 || (_context$hostContext = _context$hostContext.config) === null || _context$hostContext === void 0 || (_context$hostContext = _context$hostContext.basic) === null || _context$hostContext === void 0 ? void 0 : _context$hostContext.service_time;
483
+ const configuredSlice = (_context$hostContext2 = context.hostContext) === null || _context$hostContext2 === void 0 || (_context$hostContext2 = _context$hostContext2.bookingConfig) === null || _context$hostContext2 === void 0 || (_context$hostContext2 = _context$hostContext2.config) === null || _context$hostContext2 === void 0 || (_context$hostContext2 = _context$hostContext2.basic) === null || _context$hostContext2 === void 0 ? void 0 : _context$hostContext2.service_time;
409
484
  const slice = (_options$slice = options.slice) !== null && _options$slice !== void 0 ? _options$slice : typeof configuredSlice === "object" ? configuredSlice === null || configuredSlice === void 0 ? void 0 : configuredSlice.value : configuredSlice;
410
485
  const resourceModule = context.steps.flatMap((step) => step.modules).find((item) => item.type === "resource");
411
486
  const resourceModuleData = resourceModule ? context.getModuleData(resourceModule.key) : void 0;
@@ -426,14 +501,16 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
426
501
  resourceModuleData === null || resourceModuleData === void 0 ? void 0 : resourceModuleData.cacheItem,
427
502
  resourceModuleData === null || resourceModuleData === void 0 ? void 0 : resourceModuleData.requestId
428
503
  ]);
429
- const posDurationTimeObj = useMemo(() => usePosDurationAvailability && productDurationMinutes ? buildPosDurationTimeObj(runtime.timeObj, productDurationMinutes, duration) : runtime.timeObj, [
430
- usePosDurationAvailability,
431
- productDurationMinutes,
504
+ const posCustomTimeBaseMinutes = usePosDurationAvailability ? resolvePosCustomTimeBaseMinutes(productDurationMinutes, availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.slotStepMinutes, slice) : usePosSessionAvailability ? availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.slotStepMinutes : null;
505
+ const posCustomTimeObj = useMemo(() => usePosCustomTimeAvailability && posCustomTimeBaseMinutes ? buildPosDurationTimeObj(runtime.timeObj, posCustomTimeBaseMinutes, duration) : runtime.timeObj, [
506
+ usePosCustomTimeAvailability,
507
+ posCustomTimeBaseMinutes,
432
508
  runtime.timeObj,
433
509
  duration
434
510
  ]);
435
511
  const durationProps = runtime.durationProps;
436
512
  const applyAvailabilityCandidate = (candidate) => {
513
+ if (!availabilityData) return;
437
514
  context.setModuleData(module.key, _objectSpread2(_objectSpread2({}, availabilityData), {}, { selectedCandidate: candidate }));
438
515
  if (!candidate) return;
439
516
  const startAt = dayjs(candidate.startAt);
@@ -508,7 +585,7 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
508
585
  }, [handle, registerHandle]);
509
586
  useEffect(() => {
510
587
  var _context$draft$bookin2;
511
- if (!usePosDurationAvailability || !availability) return;
588
+ if (!usePosCustomTimeAvailability || !availability) return;
512
589
  if (!startTime || !hasDurationValue(duration)) return;
513
590
  if (availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.selectedCandidate) return;
514
591
  if (moduleStatus === "loading") return;
@@ -517,12 +594,16 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
517
594
  const requestedStartTime = getAvailabilityStartTimeOverride(context);
518
595
  if (!selectedDate || !requestedDuration || !requestedStartTime) return;
519
596
  const hydrationKey = `${selectedDate}|${requestedStartTime}|${requestedDuration}`;
520
- if ((availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.posDurationHydrationKey) === hydrationKey) return;
597
+ if ((availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.posCustomTimeHydrationKey) === hydrationKey) return;
521
598
  context.setModuleStatus(module.key, "loading");
522
- refreshAvailabilityTimes(context, module, duration, startTime).then(() => context.setModuleStatus(module.key, "ready")).catch((error) => context.setModuleStatus(module.key, "error", error instanceof Error ? error.message : String(error), error));
599
+ refreshAvailabilityTimes(context, module, {
600
+ durationOverride: duration,
601
+ startTimeOverride: startTime,
602
+ selectionIntent: "custom"
603
+ }).then(() => context.setModuleStatus(module.key, "ready")).catch((error) => context.setModuleStatus(module.key, "error", error instanceof Error ? error.message : String(error), error));
523
604
  }, [
524
605
  availability,
525
- availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.posDurationHydrationKey,
606
+ availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.posCustomTimeHydrationKey,
526
607
  availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.selectedCandidate,
527
608
  context,
528
609
  context.draft.booking.startDate,
@@ -530,8 +611,23 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
530
611
  module,
531
612
  moduleStatus,
532
613
  startTime,
533
- usePosDurationAvailability
614
+ usePosCustomTimeAvailability
534
615
  ]);
616
+ const renderAvailabilityTimeSelector = () => /* @__PURE__ */ React.createElement(TimeResourceSelector, {
617
+ className: classNames("selection-flow-time-resource-selector", `selection-flow-time-resource-selector--columns-${timeSlotColumns}`),
618
+ displayMode: "plain",
619
+ timeSlots: hasNoSelectableAvailabilityDate ? [] : (availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.timeSlots) || [],
620
+ defaultSelectFirst: false,
621
+ showEmptySelectionError: false,
622
+ columns: timeSlotColumns,
623
+ capacityDisplaySettings,
624
+ allowUnavailableSelection: context.services.allowUnavailableBookingSelection === true,
625
+ value: !hasNoSelectableAvailabilityDate && (availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.selectedCandidate) ? [availabilityData.selectedCandidate.key] : [],
626
+ onSelectionChange: (items) => {
627
+ var _items$;
628
+ applyAvailabilityCandidate((_items$ = items[0]) === null || _items$ === void 0 ? void 0 : _items$.candidate);
629
+ }
630
+ });
535
631
  if (unsupportedReason) return /* @__PURE__ */ React.createElement(Alert, {
536
632
  type: "error",
537
633
  showIcon: true,
@@ -545,15 +641,25 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
545
641
  if (useAvailability) {
546
642
  if (isDateModuleLoading) return null;
547
643
  if (!hasNoSelectableAvailabilityDate && (moduleStatus === "loading" || !(availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.timeSlots))) return /* @__PURE__ */ React.createElement(SkuDetailLoadingPanel, null);
548
- if (usePosDurationAvailability) {
549
- var _availabilityData$slo, _durationProps$select, _options$durationSele;
644
+ if (usePosCustomTimeAvailability) {
645
+ var _availabilityData$slo, _availabilityData$tim, _durationProps$select, _options$durationSele;
646
+ if (usePosSessionAvailability && !posCustomTimeBaseMinutes) return /* @__PURE__ */ React.createElement(Alert, {
647
+ type: "error",
648
+ showIcon: true,
649
+ message: selectionFlowText("pisell2.text.sku.detail.modal.validation.availability.wait")
650
+ });
550
651
  const selectedCandidate = availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.selectedCandidate;
551
- const posStartTimeSlice = (_availabilityData$slo = availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.slotStepMinutes) !== null && _availabilityData$slo !== void 0 ? _availabilityData$slo : slice;
652
+ const posStartTimeSlice = usePosSessionAvailability ? availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.slotStepMinutes : (_availabilityData$slo = availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.slotStepMinutes) !== null && _availabilityData$slo !== void 0 ? _availabilityData$slo : slice;
552
653
  selectedCandidate && context.services.allowUnavailableBookingSelection === true && isAvailabilityCandidateSelectable(selectedCandidate);
654
+ const showCandidateCards = shouldShowPosCustomTimeCandidateCards({
655
+ isSessionAvailability: usePosSessionAvailability,
656
+ isDurationAvailability: usePosDurationAvailability,
657
+ candidateCount: (availabilityData === null || availabilityData === void 0 || (_availabilityData$tim = availabilityData.timeSlots) === null || _availabilityData$tim === void 0 ? void 0 : _availabilityData$tim.length) || 0
658
+ });
553
659
  return /* @__PURE__ */ React.createElement(Space, {
554
660
  direction: "vertical",
555
661
  style: { width: "100%" }
556
- }, /* @__PURE__ */ React.createElement("div", { style: { fontWeight: 500 } }, selectionFlowText("pisell2.text.start_time")), /* @__PURE__ */ React.createElement(SelectTime, {
662
+ }, showCandidateCards ? renderAvailabilityTimeSelector() : null, /* @__PURE__ */ React.createElement("div", { style: { fontWeight: 500 } }, selectionFlowText("pisell2.text.start_time")), /* @__PURE__ */ React.createElement(SelectTime, {
557
663
  value: startTime || "",
558
664
  slice: posStartTimeSlice,
559
665
  theme: options.theme,
@@ -577,10 +683,14 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
577
683
  sourceModuleType: "time"
578
684
  });
579
685
  context.setModuleStatus(module.key, "loading");
580
- refreshAvailabilityTimes(context, module, duration, nextStartTime).then(() => context.setModuleStatus(module.key, "ready")).catch((error) => context.setModuleStatus(module.key, "error", error instanceof Error ? error.message : String(error), error));
686
+ refreshAvailabilityTimes(context, module, {
687
+ durationOverride: duration,
688
+ startTimeOverride: nextStartTime,
689
+ selectionIntent: "custom"
690
+ }).then(() => context.setModuleStatus(module.key, "ready")).catch((error) => context.setModuleStatus(module.key, "error", error instanceof Error ? error.message : String(error), error));
581
691
  }
582
692
  }), /* @__PURE__ */ React.createElement("div", { style: { fontWeight: 500 } }, selectionFlowText("pisell2.text.duration")), /* @__PURE__ */ React.createElement(Duration, _objectSpread2(_objectSpread2(_objectSpread2({}, durationProps), options.durationProps), {}, {
583
- timeObj: posDurationTimeObj,
693
+ timeObj: posCustomTimeObj,
584
694
  value: duration !== null && duration !== void 0 ? duration : void 0,
585
695
  selectProps: _objectSpread2(_objectSpread2(_objectSpread2({}, (durationProps === null || durationProps === void 0 ? void 0 : durationProps.selectProps) || {}), options.durationSelectProps), {}, { style: _objectSpread2(_objectSpread2({ width: "100%" }, (durationProps === null || durationProps === void 0 || (_durationProps$select = durationProps.selectProps) === null || _durationProps$select === void 0 ? void 0 : _durationProps$select.style) || {}), ((_options$durationSele = options.durationSelectProps) === null || _options$durationSele === void 0 ? void 0 : _options$durationSele.style) || {}) }),
586
696
  style: { width: "100%" },
@@ -600,25 +710,15 @@ const TimeFlowModuleComponent = ({ context, module, registerHandle }) => {
600
710
  sourceModuleType: "time"
601
711
  });
602
712
  context.setModuleStatus(module.key, "loading");
603
- refreshAvailabilityTimes(context, module, nextDuration, startTime).then(() => context.setModuleStatus(module.key, "ready")).catch((error) => context.setModuleStatus(module.key, "error", error instanceof Error ? error.message : String(error), error));
713
+ refreshAvailabilityTimes(context, module, {
714
+ durationOverride: nextDuration,
715
+ startTimeOverride: startTime,
716
+ selectionIntent: "custom"
717
+ }).then(() => context.setModuleStatus(module.key, "ready")).catch((error) => context.setModuleStatus(module.key, "error", error instanceof Error ? error.message : String(error), error));
604
718
  }
605
719
  })));
606
720
  }
607
- return /* @__PURE__ */ React.createElement(TimeResourceSelector, {
608
- className: classNames("selection-flow-time-resource-selector", `selection-flow-time-resource-selector--columns-${timeSlotColumns}`),
609
- displayMode: "plain",
610
- timeSlots: hasNoSelectableAvailabilityDate ? [] : (availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.timeSlots) || [],
611
- defaultSelectFirst: false,
612
- showEmptySelectionError: false,
613
- columns: timeSlotColumns,
614
- capacityDisplaySettings,
615
- allowUnavailableSelection: context.services.allowUnavailableBookingSelection === true,
616
- value: !hasNoSelectableAvailabilityDate && (availabilityData === null || availabilityData === void 0 ? void 0 : availabilityData.selectedCandidate) ? [availabilityData.selectedCandidate.key] : [],
617
- onSelectionChange: (items) => {
618
- var _items$;
619
- applyAvailabilityCandidate((_items$ = items[0]) === null || _items$ === void 0 ? void 0 : _items$.candidate);
620
- }
621
- });
721
+ return renderAvailabilityTimeSelector();
622
722
  }
623
723
  if (!SelectTime) return /* @__PURE__ */ React.createElement(Alert, {
624
724
  type: "error",
@@ -700,8 +800,8 @@ const timeFlowModule = {
700
800
  "booking.capacity"
701
801
  ],
702
802
  isApplicable: (context) => {
703
- var _context$hostContext2;
704
- return !isNormalProductByDurationSchedule(context.draft.productData) && ((_context$hostContext2 = context.hostContext) === null || _context$hostContext2 === void 0 ? void 0 : _context$hostContext2.renderType) !== "eventBooking";
803
+ var _context$hostContext3;
804
+ return !isNormalProductByDurationSchedule(context.draft.productData) && ((_context$hostContext3 = context.hostContext) === null || _context$hostContext3 === void 0 ? void 0 : _context$hostContext3.renderType) !== "eventBooking";
705
805
  },
706
806
  canInitialize: (context, module) => {
707
807
  const unsupportedReason = getUnsupportedBookingFlowReason(context.draft.productData);
@@ -0,0 +1,59 @@
1
+ import dayjs from "dayjs";
2
+ //#region src/pro/skuDetailModal/flow/modules/time/posCustomTime.ts
3
+ const isFlexibleDurationValue = (value) => {
4
+ if (typeof value === "string") {
5
+ const text = value.trim().toLowerCase();
6
+ return text === "flexible" || text.startsWith("flexible_");
7
+ }
8
+ return Boolean(value && typeof value === "object" && String(value.type || "").trim().toLowerCase() === "flexible");
9
+ };
10
+ const resolvePosCustomTimeBaseMinutes = (...values) => {
11
+ for (const value of values) {
12
+ const minutes = Number(value);
13
+ if (Number.isFinite(minutes) && minutes > 0) return Math.max(1, Math.floor(minutes));
14
+ }
15
+ return 30;
16
+ };
17
+ const resolvePosCustomTimeDefaultStartTime = (currentValue, sliceMinutes, now) => {
18
+ if (typeof currentValue === "string") {
19
+ const matched = currentValue.trim().match(/^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d)?$/);
20
+ if (matched) return `${matched[1]}:${matched[2]}`;
21
+ }
22
+ const current = now === void 0 ? dayjs() : dayjs(now);
23
+ if (!current.isValid()) return null;
24
+ const step = Math.min(resolvePosCustomTimeBaseMinutes(sliceMinutes), 1440);
25
+ const minuteOfDay = current.hour() * 60 + current.minute();
26
+ const alignedMinute = Math.floor(minuteOfDay / step) * step;
27
+ const hours = Math.floor(alignedMinute / 60);
28
+ const minutes = alignedMinute % 60;
29
+ return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
30
+ };
31
+ const resolvePosCustomTimeDefaultDurationMinutes = (currentValue, baseDurationMinutes) => {
32
+ if (typeof currentValue === "string") {
33
+ const flexibleMatch = currentValue.trim().toLowerCase().match(/^flexible_(\d+(?:\.\d+)?)$/);
34
+ if (flexibleMatch) return Math.max(1, Math.floor(Number(flexibleMatch[1])));
35
+ }
36
+ const currentMinutes = Number(currentValue);
37
+ if (Number.isFinite(currentMinutes) && currentMinutes > 0) return Math.max(1, Math.floor(currentMinutes));
38
+ return resolvePosCustomTimeBaseMinutes(baseDurationMinutes);
39
+ };
40
+ const shouldShowPosCustomTimeCandidateCards = (params) => params.isSessionAvailability || params.isDurationAvailability && params.candidateCount > 0;
41
+ const getAvailabilityCandidateDurationMinutes = (candidate) => {
42
+ const startAt = dayjs(candidate.startAt);
43
+ const endAt = dayjs(candidate.endAt);
44
+ if (!startAt.isValid() || !endAt.isValid()) return null;
45
+ const duration = endAt.diff(startAt, "minute");
46
+ return duration > 0 ? duration : null;
47
+ };
48
+ const isSameAvailabilityCandidateRange = (candidate, params) => Boolean(params.startTime) && candidate.date === params.date && candidate.startTime.slice(0, 5) === params.startTime && Boolean(params.durationMinutes) && getAvailabilityCandidateDurationMinutes(candidate) === params.durationMinutes;
49
+ const resolvePosCustomTimeCandidate = (params) => {
50
+ const requestedCustomRange = params.requestedCustomRange;
51
+ if (params.customSelectionIntent) {
52
+ if (!requestedCustomRange) return void 0;
53
+ return params.candidates.find((candidate) => candidate.source === "duration_window" && isSameAvailabilityCandidateRange(candidate, requestedCustomRange));
54
+ }
55
+ return params.restoredDraftCandidate || params.restoredExistingCandidate || params.fallbackCandidate;
56
+ };
57
+ const getSessionPresetCandidates = (candidates) => candidates.filter((candidate) => candidate.source === "session_schedule");
58
+ //#endregion
59
+ export { getAvailabilityCandidateDurationMinutes, getSessionPresetCandidates, isFlexibleDurationValue, isSameAvailabilityCandidateRange, resolvePosCustomTimeBaseMinutes, resolvePosCustomTimeCandidate, resolvePosCustomTimeDefaultDurationMinutes, resolvePosCustomTimeDefaultStartTime, shouldShowPosCustomTimeCandidateCards };