@licklist/design 0.63.3 → 0.65.0-dev.1

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 (145) hide show
  1. package/bitbucket-pipelines.yml +0 -8
  2. package/dist/date-time-button/DateTimeButton.js +1 -1
  3. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.d.ts.map +1 -1
  4. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.js +1 -1
  5. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.d.ts.map +1 -1
  6. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.js +1 -1
  7. package/dist/iframe/payment/order-items-table/utils/paymentSummary.d.ts.map +1 -1
  8. package/dist/iframe/ryft/RyftPaymentForm.d.ts +4 -1
  9. package/dist/iframe/ryft/RyftPaymentForm.d.ts.map +1 -1
  10. package/dist/iframe/ryft/RyftPaymentForm.js +1 -1
  11. package/dist/iframe/ryft/utils/ryft-form.d.ts +5 -2
  12. package/dist/iframe/ryft/utils/ryft-form.d.ts.map +1 -1
  13. package/dist/iframe/ryft/utils/ryft-form.js +1 -1
  14. package/dist/product-set/control/DateAndRecurrenceInput.d.ts +1 -1
  15. package/dist/product-set/control/DateAndRecurrenceInput.d.ts.map +1 -1
  16. package/dist/product-set/control/DateAndRecurrenceInput.js +1 -1
  17. package/dist/product-set/control/DateInput.js +1 -1
  18. package/dist/product-set/control/ProductSetControl.d.ts +3 -2
  19. package/dist/product-set/control/ProductSetControl.d.ts.map +1 -1
  20. package/dist/product-set/control/ProductSetControl.js +1 -1
  21. package/dist/product-set/form/ProductCategoriesControl.d.ts +3 -1
  22. package/dist/product-set/form/ProductCategoriesControl.d.ts.map +1 -1
  23. package/dist/product-set/form/ProductCategoriesControl.js +1 -1
  24. package/dist/product-set/form/ProductSetForm.d.ts +6 -2
  25. package/dist/product-set/form/ProductSetForm.d.ts.map +1 -1
  26. package/dist/product-set/form/ProductSetForm.js +1 -1
  27. package/dist/product-set/form/ProductsControl.d.ts +3 -1
  28. package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
  29. package/dist/product-set/form/ProductsControl.js +1 -1
  30. package/dist/product-set/form/StepsControl.d.ts +3 -1
  31. package/dist/product-set/form/StepsControl.d.ts.map +1 -1
  32. package/dist/product-set/form/StepsControl.js +1 -1
  33. package/dist/product-set/product/ProductControl.d.ts +1 -0
  34. package/dist/product-set/product/ProductControl.d.ts.map +1 -1
  35. package/dist/product-set/product/ProductControl.js +1 -1
  36. package/dist/product-set/step/StepControl.d.ts +2 -1
  37. package/dist/product-set/step/StepControl.d.ts.map +1 -1
  38. package/dist/product-set/step/StepControl.js +1 -1
  39. package/dist/provider/working-hours-input/WorkingHoursInputDescription.d.ts.map +1 -1
  40. package/dist/provider/working-hours-input/WorkingHoursInputDescription.js +1 -1
  41. package/dist/recurring-date-picker-input/RecurrenceIntervalAndFrequencyInput.d.ts.map +1 -1
  42. package/dist/recurring-date-picker-input/RecurrenceIntervalAndFrequencyInput.js +1 -1
  43. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts +3 -1
  44. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts.map +1 -1
  45. package/dist/recurring-date-picker-input/RecurringDatePickerInput.js +1 -1
  46. package/dist/recurring-date-picker-input/utils.d.ts +5 -0
  47. package/dist/recurring-date-picker-input/utils.d.ts.map +1 -1
  48. package/dist/recurring-date-picker-input/utils.js +1 -1
  49. package/dist/report/ReportRunnerModal/ReportRunnerModal.d.ts +1 -1
  50. package/dist/report/ReportRunnerModal/ReportRunnerModal.d.ts.map +1 -1
  51. package/dist/report/ReportRunnerModal/ReportRunnerModal.js +1 -1
  52. package/dist/sales/booking/results/components/ResultCard.d.ts.map +1 -1
  53. package/dist/setting/admin/AdminSettingForm.d.ts +2 -2
  54. package/dist/setting/admin/AdminSettingForm.d.ts.map +1 -1
  55. package/dist/sortable-tree/SortableTreeItem.d.ts +1 -2
  56. package/dist/sortable-tree/SortableTreeItem.d.ts.map +1 -1
  57. package/dist/sortable-tree/SortableTreeItem.js +1 -1
  58. package/dist/styles/date-time-button/DateTimeButton.scss +1 -0
  59. package/dist/styles/iframe-page/PageBody.scss +0 -1
  60. package/dist/styles/ryft-payment-form/RyftPaymentForm.scss +8 -0
  61. package/dist/styles/sales/BookingResults.scss +1 -1
  62. package/dist/styles/zones/ZoneForm.scss +2 -1
  63. package/dist/zone/form/ZoneForm.d.ts +2 -2
  64. package/dist/zone/form/ZoneForm.d.ts.map +1 -1
  65. package/dist/zone/form/ZoneForm.js +1 -1
  66. package/dist/zone/form/components/ZoneControl.d.ts +2 -2
  67. package/dist/zone/form/components/ZoneControl.d.ts.map +1 -1
  68. package/dist/zone/form/components/ZoneControl.js +1 -1
  69. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts +4 -4
  70. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts.map +1 -1
  71. package/dist/zone/form/components/ZoneRecurrencesControl.js +1 -1
  72. package/dist/zone/form/utils/dates.d.ts.map +1 -1
  73. package/package.json +14 -39
  74. package/src/date-time-button/DateTimeButton.stories.tsx +2 -1
  75. package/src/date-time-button/DateTimeButton.tsx +7 -5
  76. package/src/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.tsx +14 -9
  77. package/src/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.tsx +2 -0
  78. package/src/iframe/payment/order-items-table/utils/paymentSummary.tsx +1 -0
  79. package/src/iframe/ryft/RyftPaymentForm.tsx +11 -2
  80. package/src/iframe/ryft/utils/ryft-form.ts +23 -4
  81. package/src/product-set/control/DateAndRecurrenceInput.tsx +3 -4
  82. package/src/product-set/control/DateInput.tsx +2 -2
  83. package/src/product-set/control/ProductSetControl.tsx +17 -5
  84. package/src/product-set/form/ProductCategoriesControl.tsx +15 -4
  85. package/src/product-set/form/ProductSetForm.tsx +13 -2
  86. package/src/product-set/form/ProductsControl.tsx +93 -77
  87. package/src/product-set/form/StepsControl.tsx +15 -7
  88. package/src/product-set/product/ProductControl.tsx +8 -5
  89. package/src/product-set/step/StepControl.tsx +4 -3
  90. package/src/provider/working-hours-input/WorkingHoursInputDescription.tsx +4 -18
  91. package/src/recurring-date-picker-input/RecurrenceIntervalAndFrequencyInput.tsx +40 -21
  92. package/src/recurring-date-picker-input/RecurringDatePickerInput.stories.tsx +13 -7
  93. package/src/recurring-date-picker-input/RecurringDatePickerInput.tsx +12 -1
  94. package/src/recurring-date-picker-input/utils.ts +90 -1
  95. package/src/report/ReportRunnerModal/ReportRunnerModal.stories.tsx +307 -0
  96. package/src/report/ReportRunnerModal/ReportRunnerModal.tsx +24 -14
  97. package/src/sales/booking/results/components/ResultCard.tsx +0 -3
  98. package/src/setting/admin/AdminSettingForm.tsx +2 -2
  99. package/src/sortable-tree/SortableTreeItem.tsx +0 -3
  100. package/src/static/switch/BooleanSwitch.tsx +1 -1
  101. package/src/styles/date-time-button/DateTimeButton.scss +1 -0
  102. package/src/styles/iframe-page/PageBody.scss +0 -1
  103. package/src/styles/ryft-payment-form/RyftPaymentForm.scss +8 -0
  104. package/src/styles/sales/BookingResults.scss +1 -1
  105. package/src/styles/zones/ZoneForm.scss +2 -1
  106. package/src/zone/form/ZoneForm.tsx +3 -2
  107. package/src/zone/form/components/ZoneControl.tsx +3 -3
  108. package/src/zone/form/components/ZoneRecurrencesControl.tsx +7 -5
  109. package/src/zone/form/utils/dates.ts +9 -10
  110. package/jest.config.js +0 -29
  111. package/tests/Auth/Authorizer.test.tsx +0 -194
  112. package/tests/Auth/Layout/UserNavDropDown.test.tsx +0 -43
  113. package/tests/Auth/Layout/UserNavDropDownToggle.test.tsx +0 -33
  114. package/tests/Auth/Login/LoginComponent.test.tsx +0 -246
  115. package/tests/Auth/Login/LoginFormComponent.test.tsx +0 -182
  116. package/tests/Auth/Register/RegisterComponent.test.tsx +0 -285
  117. package/tests/Auth/Register/RegisterFormComponent.test.tsx +0 -170
  118. package/tests/Auth/Settings/Dashboard/IpInput.test.tsx +0 -130
  119. package/tests/Auth/Social/SocialCallbackComponent.test.tsx +0 -133
  120. package/tests/Auth/Social/SocialFormComponent.test.tsx +0 -118
  121. package/tests/FileUpload/FileUpload.test.tsx +0 -42
  122. package/tests/Notification/EmailTemplate.test.tsx +0 -82
  123. package/tests/ProductSet/ProductSetPopover.test.tsx +0 -40
  124. package/tests/Report/Report.test.tsx +0 -48
  125. package/tests/Sales/Coupon.test.tsx +0 -51
  126. package/tests/Sales/SalesAndVIews.test.tsx +0 -63
  127. package/tests/SnippetTemplates/SnippetTemplates.test.tsx +0 -56
  128. package/tests/Table/FilterHelperComponent.test.tsx +0 -88
  129. package/tests/Table/PaginationHelperComponent.test.tsx +0 -109
  130. package/tests/Table/PerPageHelperComponent.test.tsx +0 -34
  131. package/tests/Table/TableHelperComponent.test.tsx +0 -295
  132. package/tests/TipTapEditor/TipTapEditor.test.tsx +0 -28
  133. package/tests/__mock__/hooks/useAuthApi.ts +0 -13
  134. package/tests/__mock__/hooks/useAuthMock.ts +0 -13
  135. package/tests/__mock__/hooks/useFormMock.ts +0 -27
  136. package/tests/__mock__/hooks/useNotificationMock.ts +0 -13
  137. package/tests/__mock__/hooks/useQueryMock.ts +0 -16
  138. package/tests/__mock__/hooks/useSocialApiMock.ts +0 -20
  139. package/tests/__mock__/hooks/useTranslationMock.ts +0 -17
  140. package/tests/__mock__/hooks/useUserApiMock.ts +0 -18
  141. package/tests/__mock__/hooks/useUserMock.ts +0 -13
  142. package/tests/__mock__/styleMock.js +0 -1
  143. package/tests/__mock__/windowMock.ts +0 -5
  144. package/tests/packages/react-query.tsx +0 -28
  145. package/tests/setupTests.ts +0 -10
@@ -26,12 +26,16 @@ import { checkAvailableTimesErrors, getFilteredTemplates } from "../utils";
26
26
  export interface WithIsLoading {
27
27
  isLoading: boolean;
28
28
  }
29
+ export interface WithIdOptional {
30
+ id?: number;
31
+ }
32
+
29
33
  export interface WithId {
30
34
  id: number;
31
35
  }
32
36
  export interface ProductSetFormValues
33
37
  extends FormValues,
34
- WithId,
38
+ WithIdOptional,
35
39
  ProductSetControlValues {
36
40
  steps: Step[];
37
41
  isOverrides?: boolean;
@@ -53,6 +57,7 @@ export interface ProductSetFormProps
53
57
  isCreateAction?: boolean;
54
58
  isOverrides?: boolean;
55
59
  workHours?: WorkHour[];
60
+ isCreateNewOverrides?: boolean;
56
61
  }
57
62
 
58
63
  export function ProductSetForm({
@@ -70,6 +75,7 @@ export function ProductSetForm({
70
75
  isCreateAction,
71
76
  workHours,
72
77
  isOverrides,
78
+ isCreateNewOverrides,
73
79
  ...shared
74
80
  }: ProductSetFormProps) {
75
81
  const { t } = useTranslation("Design");
@@ -115,7 +121,11 @@ export function ProductSetForm({
115
121
  }, [serverErrors, setError]);
116
122
 
117
123
  useEffect(() => {
118
- window.history.pushState(null, "", window.location.pathname);
124
+ window.history.pushState(
125
+ null,
126
+ "",
127
+ window.location.pathname + window.location.search
128
+ );
119
129
  window.addEventListener("beforeunload", onBeforeUnload);
120
130
  window.addEventListener("popstate", onPopState);
121
131
 
@@ -166,6 +176,7 @@ export function ProductSetForm({
166
176
  workHours={workHours}
167
177
  providerHasBookingManagement={providerHasBookingManagement}
168
178
  isOverrides={isOverrides}
179
+ isCreateNewOverrides={isCreateNewOverrides}
169
180
  />
170
181
  <Row>
171
182
  <Col md={6} sm={12} />
@@ -35,6 +35,8 @@ interface ProductsControlProps extends WithIsLoading {
35
35
  categoryType: CategoryType;
36
36
  zones?: Zone[];
37
37
  isOverrides?: boolean;
38
+ isEventEditProductSet?: boolean;
39
+ isCreateNewOverrides?: boolean;
38
40
  }
39
41
 
40
42
  const getDefaultProductValue = (sort: number): Product => ({
@@ -57,6 +59,7 @@ const getDefaultProductValue = (sort: number): Product => ({
57
59
  quantitySelector: 1,
58
60
  hasSpecialNotes: false,
59
61
  weight: 0,
62
+ originalProductId: null,
60
63
  type: DEFAULT_PRODUCT_TYPE,
61
64
  tierId: Number(uniqueId()),
62
65
  zoneId: null,
@@ -79,6 +82,8 @@ export function ProductsControl({
79
82
  categoryType,
80
83
  zones,
81
84
  isOverrides,
85
+ isEventEditProductSet,
86
+ isCreateNewOverrides,
82
87
  }: ProductsControlProps) {
83
88
  const { t } = useTranslation("Design");
84
89
  const form = useFormContext<ProductSetFormValues>();
@@ -203,90 +208,101 @@ export function ProductsControl({
203
208
  onDragEnd={handleDragEnd}
204
209
  sensors={[mouseSensor]}
205
210
  >
206
- {fields.map((product, index) => (
207
- <Controller
208
- key={product._id}
209
- control={control}
210
- name={`${productControlFieldName}.${index}.name` as const}
211
- rules={{
212
- required: t("Validation:fieldRequired", {
213
- attribute: t("name"),
214
- }) as string,
215
- }}
216
- render={({ field: { value, onChange } }) => (
217
- <SortableTree.Item
218
- key={`product-${product._id}`}
219
- id={String(product._id)}
220
- isExpanded={isFirstProductAdded}
221
- isInvalid={!!categoryProductErrors}
222
- title={value}
223
- isOverride={isOverrides}
224
- badge={<Badge className="product-badge">{t("product")}</Badge>}
225
- isIconInHeader={false}
226
- cancelChanges={() => cancelChanges(index)}
227
- edit={() => edit(index)}
228
- isProduct
229
- secondaryBadge={getBadgeConfig(categoryType, t(categoryType))}
230
- subTitle={
231
- <div className="product-set-badges-container">
232
- <div className="product-set-subtitle-dot product-set-subtitle-product-dot" />
233
- <span>
234
- {`£${prices[index]} ${t("each")} - ${t("qty")}:${
235
- !isUnlimitedQuantities[index]
236
- ? ` ${quantities[index]}`
237
- : t(" unlimited")
238
- } ${
239
- !isUnlimitedQuantities[index]
240
- ? ` - ${t("possibleRevenue")} £${
241
- prices[index] * quantities[index]
242
- }`
243
- : ""
244
- } `}
245
- </span>
246
- </div>
247
- }
248
- modalLabel={t("addNewProduct")}
249
- modalClass={ProductSetModalClasses.product}
250
- isNewAdded={showProductModal}
251
- body={
252
- <ProductControl<ProductSetFormValues>
211
+ {fields.map((product, index) => {
212
+ const isOverridesProductSet = isEventEditProductSet
213
+ ? !!product.id
214
+ : isOverrides && !!product.originalProductId;
215
+
216
+ const isNewProductOverrides = isCreateNewOverrides && !!product.id;
217
+
218
+ return (
219
+ <Controller
220
+ key={product._id}
221
+ control={control}
222
+ name={`${productControlFieldName}.${index}.name` as const}
223
+ rules={{
224
+ required: t("Validation:fieldRequired", {
225
+ attribute: t("name"),
226
+ }) as string,
227
+ }}
228
+ render={({ field: { value, onChange } }) => (
229
+ <SortableTree.Item
230
+ key={`product-${product._id}`}
231
+ id={String(product._id)}
232
+ isExpanded={isFirstProductAdded}
233
+ isInvalid={!!categoryProductErrors}
234
+ title={value}
235
+ isOverride={isOverrides}
236
+ badge={
237
+ <Badge className="product-badge">{t("product")}</Badge>
238
+ }
239
+ isIconInHeader={false}
240
+ cancelChanges={() => cancelChanges(index)}
241
+ edit={() => edit(index)}
242
+ secondaryBadge={getBadgeConfig(categoryType, t(categoryType))}
243
+ subTitle={
244
+ <div className="product-set-badges-container">
245
+ <div className="product-set-subtitle-dot product-set-subtitle-product-dot" />
246
+ <span>
247
+ {`£${prices[index]} ${t("each")} - ${t("qty")}:${
248
+ !isUnlimitedQuantities[index]
249
+ ? ` ${quantities[index]}`
250
+ : t(" unlimited")
251
+ } ${
252
+ !isUnlimitedQuantities[index]
253
+ ? ` - ${t("possibleRevenue")} £${
254
+ prices[index] * quantities[index]
255
+ }`
256
+ : ""
257
+ } `}
258
+ </span>
259
+ </div>
260
+ }
261
+ modalLabel={t("addNewProduct")}
262
+ modalClass={ProductSetModalClasses.product}
263
+ isNewAdded={showProductModal}
264
+ body={
265
+ <ProductControl<ProductSetFormValues>
266
+ isLoading={isLoading}
267
+ quantityType={quantityType}
268
+ allowDeposits={allowDeposits}
269
+ hasBookingManagement={false}
270
+ fieldNamePrefix={
271
+ `${productControlFieldName}.${index}` as const
272
+ }
273
+ productName={value}
274
+ onProductNameChange={onChange}
275
+ hasTicket={hasTicket}
276
+ categoryType={categoryType}
277
+ zoneDuration={catergoryZone?.defaultDuration}
278
+ isOverrides={
279
+ isNewProductOverrides || isOverridesProductSet
280
+ }
281
+ />
282
+ }
283
+ onDelete={() => onProductRemove(index)}
284
+ validate={() =>
285
+ trigger(`${productControlFieldName}.${index}`)
286
+ }
287
+ saveValidField={saveValidField}
288
+ // preItem={<Popover className="d-none d-sm-block" />}
289
+ >
290
+ <SubProductsControl
253
291
  isLoading={isLoading}
254
292
  quantityType={quantityType}
255
- allowDeposits={allowDeposits}
256
- hasBookingManagement={false}
257
- fieldNamePrefix={
258
- `${productControlFieldName}.${index}` as const
259
- }
260
- productName={value}
261
- onProductNameChange={onChange}
262
- hasTicket={hasTicket}
263
- categoryType={categoryType}
264
- zoneDuration={catergoryZone?.defaultDuration}
265
- isOverrides={isOverrides}
293
+ stepIndex={stepIndex}
294
+ productCategoryIndex={productCategoryIndex}
295
+ productIndex={index}
266
296
  />
267
- }
268
- onDelete={() => onProductRemove(index)}
269
- validate={() => trigger(`${productControlFieldName}.${index}`)}
270
- saveValidField={saveValidField}
271
- // preItem={<Popover className="d-none d-sm-block" />}
272
- >
273
- <SubProductsControl
274
- isLoading={isLoading}
275
- quantityType={quantityType}
276
- stepIndex={stepIndex}
277
- productCategoryIndex={productCategoryIndex}
278
- productIndex={index}
279
- />
280
- </SortableTree.Item>
281
- )}
282
- />
283
- ))}
297
+ </SortableTree.Item>
298
+ )}
299
+ />
300
+ );
301
+ })}
284
302
  </SortableTree>
285
303
  <CreateProductSetItem
286
304
  title={t("addProduct")}
287
- isOverride={isOverrides}
288
305
  onClick={() => {
289
- if (isOverrides) return;
290
306
  append(getDefaultProductValue(fields.length));
291
307
  setShowProductModal(true);
292
308
 
@@ -19,9 +19,16 @@ import { ProductSetFormValues } from "./ProductSetForm";
19
19
  interface StepsControlProps {
20
20
  isLoading: boolean;
21
21
  isOverrides?: boolean;
22
+ isEventEditProductSet?: boolean;
23
+ isCreateNewOverrides?: boolean;
22
24
  }
23
25
 
24
- export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
26
+ export function StepsControl({
27
+ isLoading,
28
+ isOverrides,
29
+ isEventEditProductSet,
30
+ isCreateNewOverrides,
31
+ }: StepsControlProps) {
25
32
  const form = useFormContext<ProductSetFormValues>();
26
33
  const { t } = useTranslation("Design");
27
34
  const [showStepModal, setShowStepModal] = useState(false);
@@ -68,9 +75,9 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
68
75
  <>
69
76
  {fields.map((step, index) => {
70
77
  const stepFieldName = `steps.${index}` as const;
71
-
72
78
  const stepData = getValues(stepFieldName);
73
-
79
+ const isOverrideStep =
80
+ (isOverrides || isCreateNewOverrides) && !!step.id;
74
81
  return (
75
82
  <Controller
76
83
  key={`step-${step._id}`}
@@ -92,9 +99,9 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
92
99
  modalLabel={t("addNewStep")}
93
100
  modalClass={ProductSetModalClasses.step}
94
101
  isNewAdded={showStepModal}
95
- edit={() => !isOverrides && edit(index)}
102
+ edit={() => edit(index)}
96
103
  cancelChanges={() => cancelChanges(index)}
97
- isOverride={isOverrides}
104
+ isOverride={isOverrideStep}
98
105
  subTitle={
99
106
  <div className="product-set-badges-container">
100
107
  <div className="product-set-subtitle-dot product-set-subtitle-step-dot" />
@@ -110,6 +117,7 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
110
117
  stepIndex={index}
111
118
  stepName={value}
112
119
  onStepNameChange={onChange}
120
+ isOverrides={isOverrideStep}
113
121
  />
114
122
  }
115
123
  onDelete={() => remove(index)}
@@ -140,6 +148,8 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
140
148
  isLoading={isLoading}
141
149
  stepIndex={index}
142
150
  isOverrides={isOverrides}
151
+ isCreateNewOverrides={isCreateNewOverrides}
152
+ isEventEditProductSet={isEventEditProductSet}
143
153
  />
144
154
  </SortableTree.Item>
145
155
  )}
@@ -149,9 +159,7 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
149
159
 
150
160
  <CreateProductSetItem
151
161
  title={t("addStep")}
152
- isOverride={isOverrides}
153
162
  onClick={() => {
154
- if (isOverrides) return;
155
163
  append(getDefaultStepsValues());
156
164
  setShowStepModal(true);
157
165
  if (errors.steps?.type === HookFormService.manualErrorType) {
@@ -7,14 +7,17 @@ import {
7
7
  QUANTITY_TYPE_LIST_DTO,
8
8
  QUANTITY_TYPE_RECHARGING,
9
9
  } from "@licklist/core/dist/DataMapper/Product/ProductCategoryDataMapper";
10
- import { ProductType } from "@licklist/core/dist/DataMapper/Product/ProductDataMapper";
10
+ import {
11
+ ProductType,
12
+ PRODUCT_DEfAULT_COLORS,
13
+ } from "@licklist/core/dist/DataMapper/Product/ProductDataMapper";
11
14
  import HookFormService from "@licklist/plugins/dist/services/Form/HookFormService";
15
+ import clsx from "clsx";
12
16
  import {
13
17
  FieldNamePrefixPath,
14
18
  FormValues,
15
19
  } from "@licklist/plugins/dist/types/services/Form/hook-form-service";
16
20
  import { useId } from "@react-aria/utils";
17
- import clsx from "clsx";
18
21
  import React, {
19
22
  ChangeEvent,
20
23
  useCallback,
@@ -36,7 +39,7 @@ import {
36
39
  } from "react-hook-form";
37
40
  import { useTranslation } from "react-i18next";
38
41
  import { useImages } from "@licklist/plugins/dist/hooks/Media/useImages";
39
- import { PRODUCT_DEfAULT_COLORS } from "@licklist/core/dist/DataMapper/Product/ProductDataMapper";
42
+
40
43
  import {
41
44
  Image,
42
45
  IMAGE_TYPE_IMAGE,
@@ -86,6 +89,7 @@ export interface ProductControlValues
86
89
  totalQuantity: number;
87
90
  isAvailable: boolean;
88
91
  isSoldOut: boolean;
92
+ originalProductId: number | null;
89
93
  isUnlimited: boolean;
90
94
  isRequired: boolean;
91
95
  quantitySelector: number;
@@ -156,7 +160,6 @@ export function ProductControl<T extends FormValues>({
156
160
  );
157
161
  const capacity = watch(`${fieldNamePrefix}.capacity` as Path<T>);
158
162
  const disabledDuration = capacity === "0" || !capacity;
159
-
160
163
  const advancedId = useId();
161
164
  const nameId = useId();
162
165
 
@@ -410,7 +413,7 @@ export function ProductControl<T extends FormValues>({
410
413
  `${fieldNamePrefix}.productGroupId` as Path<T>,
411
414
  errors
412
415
  )}
413
- disabled={isLoading}
416
+ disabled={isLoading || isOverrides}
414
417
  defaultValue=""
415
418
  >
416
419
  <option value="">{t("Design:selectProductGroup")}</option>
@@ -26,6 +26,7 @@ export interface StepControlProps extends IsDeletableEvent {
26
26
  stepIndex: number;
27
27
  stepName: string;
28
28
  onStepNameChange: (args: any) => void;
29
+ isOverrides?: boolean;
29
30
  }
30
31
 
31
32
  export function StepControl({
@@ -33,6 +34,7 @@ export function StepControl({
33
34
  stepIndex,
34
35
  stepName,
35
36
  onStepNameChange,
37
+ isOverrides = false,
36
38
  }: StepControlProps) {
37
39
  const { providerHasMap } = useContext(ProductSetLoadingContext);
38
40
  const {
@@ -42,7 +44,6 @@ export function StepControl({
42
44
  watch,
43
45
  } = useFormContext<ProductSetFormValues>();
44
46
  const { t } = useTranslation("Design");
45
-
46
47
  const fieldName = `steps.${stepIndex}.name` as const;
47
48
  const productCategoriesFieldName =
48
49
  `steps.${stepIndex}.productCategories` as const;
@@ -71,7 +72,7 @@ export function StepControl({
71
72
  fieldName,
72
73
  errors
73
74
  )}
74
- disabled={isLoading}
75
+ disabled={isLoading || isOverrides}
75
76
  />
76
77
  )}
77
78
  control={control}
@@ -114,7 +115,7 @@ export function StepControl({
114
115
  name={name}
115
116
  value={Boolean(value)}
116
117
  onChange={onChange}
117
- disabled={isLoading}
118
+ disabled={isLoading || isOverrides}
118
119
  />
119
120
  )}
120
121
  control={control}
@@ -1,9 +1,7 @@
1
- import { DateTime } from "luxon";
2
1
  import React from "react";
3
2
  import { Col, Row } from "react-bootstrap";
4
3
  import { useFormContext } from "react-hook-form";
5
4
  import { useTranslation } from "react-i18next";
6
- import { TIME_FORMAT } from "@licklist/core/dist/Config";
7
5
  import { WorkingHoursInputValues } from ".";
8
6
  import { useWeekdays } from "./utils";
9
7
 
@@ -25,22 +23,10 @@ export function WorkingHoursInputDescription() {
25
23
  <Row key={i}>
26
24
  <Col xs="auto">{weekdays[i]}:</Col>
27
25
  <Col>
28
- {weekday?.end
29
- ? weekday.start
30
- ? t("timeInterval", {
31
- start: DateTime.fromISO(weekday.start).toFormat(
32
- TIME_FORMAT
33
- ),
34
- end: DateTime.fromISO(weekday.start).toFormat(
35
- TIME_FORMAT
36
- ),
37
- })
38
- : t("timeFrom", {
39
- start: DateTime.fromISO(weekday.start).toFormat(
40
- TIME_FORMAT
41
- ),
42
- })
43
- : null}
26
+ {t("timeInterval", {
27
+ start: weekday.start,
28
+ end: weekday.end,
29
+ })}
44
30
  </Col>
45
31
  </Row>
46
32
  );
@@ -2,8 +2,18 @@ import React, { useEffect } from "react";
2
2
  import { DateTime } from "luxon";
3
3
  import { Col, Form, Row } from "react-bootstrap";
4
4
  import { useTranslation } from "react-i18next";
5
- import { RegisterOptions, useFormContext } from "react-hook-form";
6
- import { DATE_FORMAT } from "@licklist/core/dist/Config";
5
+ import {
6
+ RegisterOptions,
7
+ useFormContext,
8
+ useWatch,
9
+ Validate,
10
+ } from "react-hook-form";
11
+ import {
12
+ DATE_FORMAT,
13
+ TIME_FORMAT,
14
+ TIME_FULL_FORMAT,
15
+ } from "@licklist/core/dist/Config";
16
+ import { fromFormat } from "@licklist/plugins/dist/utils/dateTime";
7
17
  import { RecurringDatePickerInputValues } from "./RecurringDatePickerInput";
8
18
 
9
19
  interface RecurrenceIntervalAndFrequencyInputProps {
@@ -23,6 +33,8 @@ interface RecurrenceIntervalAndFrequencyInputProps {
23
33
  >;
24
34
  }
25
35
 
36
+ const fromTimeFullFormat = fromFormat(TIME_FULL_FORMAT);
37
+
26
38
  function RecurrenceIntervalAndFrequencyInput({
27
39
  disabled = false,
28
40
  minDate,
@@ -36,16 +48,20 @@ function RecurrenceIntervalAndFrequencyInput({
36
48
  const { t } = useTranslation(["Design", "Notification", "App"]);
37
49
 
38
50
  const {
39
- getValues,
40
51
  formState: { errors },
41
52
  register,
42
53
  trigger,
54
+ control,
43
55
  } = useFormContext<RecurringDatePickerInputValues>();
44
56
 
45
- const startDate = getValues("startDate");
46
- const endDate = getValues("endDate");
47
- const startTime = getValues("startTime");
48
- const endTime = getValues("endTime");
57
+ const startDate = useWatch({ control, name: "startDate" });
58
+ const endDate = useWatch({ control, name: "endDate" });
59
+
60
+ const _startTime = useWatch({ control, name: "startTime" });
61
+ const startTime = fromTimeFullFormat(_startTime).toFormat(TIME_FORMAT);
62
+
63
+ const _endTime = useWatch({ control, name: "endTime" });
64
+ const endTime = fromTimeFullFormat(_endTime).toFormat(TIME_FORMAT);
49
65
 
50
66
  useEffect(() => {
51
67
  if (!startDate || !endDate) {
@@ -149,22 +165,25 @@ function RecurrenceIntervalAndFrequencyInput({
149
165
  type="time"
150
166
  {...register("endTime", {
151
167
  required: false,
152
- validate: (time) => {
153
- if (!startTime || !time) {
154
- return true;
155
- }
156
- const currentStartTime = DateTime.fromISO(startTime);
157
- const currentEndTime = DateTime.fromISO(time);
168
+ ...endTimeRules,
169
+ validate: {
170
+ external: endTimeRules.validate as Validate<string>,
171
+ time: (time) => {
172
+ if (!startTime || !time) {
173
+ return true;
174
+ }
175
+ const currentStartTime = DateTime.fromISO(startTime);
176
+ const currentEndTime = DateTime.fromISO(time);
158
177
 
159
- return currentEndTime?.diff(currentStartTime, ["minutes"])
160
- ?.minutes >= 0
161
- ? true
162
- : `${t(`Validation:fieldLaterDate`, {
163
- attribute: t("Design:endTimeSmall"),
164
- min: t("Design:startTimeSmall"),
165
- })}`;
178
+ return currentEndTime?.diff(currentStartTime, ["minutes"])
179
+ ?.minutes >= 0
180
+ ? true
181
+ : `${t(`Validation:fieldLaterDate`, {
182
+ attribute: t("Design:endTimeSmall"),
183
+ min: t("Design:startTimeSmall"),
184
+ })}`;
185
+ },
166
186
  },
167
- ...endTimeRules,
168
187
  })}
169
188
  placeholder="hh:mm"
170
189
  defaultValue={endTime}
@@ -1,22 +1,19 @@
1
1
  import React from "react";
2
2
  import { Meta, Story } from "@storybook/react";
3
3
  import { Card } from "react-bootstrap";
4
+ import { DateTime } from "luxon";
5
+ import { DATE_FORMAT, TIME_FORMAT } from "@licklist/core/dist/Config/Date";
4
6
  import {
5
7
  RecurringDatePickerInput,
6
8
  RecurringDatePickerInputProps,
7
9
  } from "./RecurringDatePickerInput";
8
- import { DateTime } from "luxon";
9
- import { DATE_FORMAT, TIME_FORMAT } from "@licklist/core/dist/Config/Date";
10
10
 
11
11
  export default {
12
12
  title: "RecurringDatePickerInput",
13
13
  component: RecurringDatePickerInput,
14
14
  } as Meta;
15
15
 
16
- interface DefaultRecurringDatePickerInputProps
17
- extends RecurringDatePickerInputProps {}
18
-
19
- export const Default: Story<DefaultRecurringDatePickerInputProps> = (args) => {
16
+ export const Default: Story<RecurringDatePickerInputProps> = (args) => {
20
17
  return (
21
18
  <Card style={{ maxWidth: "max-content" }}>
22
19
  <Card.Body>
@@ -25,7 +22,7 @@ export const Default: Story<DefaultRecurringDatePickerInputProps> = (args) => {
25
22
  </Card>
26
23
  );
27
24
  };
28
- export const Valid: Story<DefaultRecurringDatePickerInputProps> = (args) => {
25
+ export const Valid: Story<RecurringDatePickerInputProps> = (args) => {
29
26
  return (
30
27
  <Card style={{ maxWidth: "max-content" }}>
31
28
  <Card.Body>
@@ -36,6 +33,15 @@ export const Valid: Story<DefaultRecurringDatePickerInputProps> = (args) => {
36
33
  };
37
34
  Default.args = {
38
35
  onChange: (data) => console.log("onSubmit", data),
36
+ workHours: [
37
+ { start: "20:00", end: "04:00", day: 0, description: "" },
38
+ { start: "20:00", end: "04:00", day: 1, description: "" },
39
+ { start: "20:00", end: "04:00", day: 2, description: "" },
40
+ { start: "20:00", end: "12:00", day: 3, description: "" },
41
+ { start: "20:00", end: "23:00", day: 4, description: "" },
42
+ { start: "08:00", end: "12:00", day: 5, description: "" },
43
+ { start: "10:00", end: "16:00", day: 6, description: "" },
44
+ ],
39
45
  };
40
46
  Valid.args = {
41
47
  onChange: (data) => console.log("onSubmit", data),
@@ -12,9 +12,14 @@ import {
12
12
  import { usePreviousValue } from "@licklist/plugins/dist/hooks/Value/usePreviousValue";
13
13
  import { FormProvider, useForm } from "react-hook-form";
14
14
  import { Form } from "react-bootstrap";
15
+ import { WorkHour } from "@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper";
15
16
  import RecurrenceIntervalAndFrequencyInput from "./RecurrenceIntervalAndFrequencyInput";
16
17
  import RecurrenceWeekdaysInput from "./RecurrenceWeekdaysInput";
17
- import { parseAndValidateRRule, SupportedFrequency } from "./utils";
18
+ import {
19
+ parseAndValidateRRule,
20
+ SupportedFrequency,
21
+ useWorkHoursValidation,
22
+ } from "./utils";
18
23
  import { ConfirmModal } from "../modals";
19
24
  import { DeleteFieldButton } from "../product-set/elements";
20
25
 
@@ -26,6 +31,7 @@ export interface RecurringDatePickerInputProps {
26
31
  initialFrequency?: Frequency;
27
32
  setInitialStartDateAfterSelect?: boolean;
28
33
  minDate?: string;
34
+ workHours: WorkHour[] | undefined;
29
35
  }
30
36
 
31
37
  export interface RecurringDatePickerInputValues {
@@ -51,6 +57,7 @@ export function RecurringDatePickerInput({
51
57
  setInitialStartDateAfterSelect = false,
52
58
  children,
53
59
  minDate,
60
+ workHours,
54
61
  }: PropsWithChildren<RecurringDatePickerInputProps>) {
55
62
  const { t } = useTranslation(["Design"]);
56
63
 
@@ -84,6 +91,8 @@ export function RecurringDatePickerInput({
84
91
  byWeekDay,
85
92
  });
86
93
 
94
+ const validator = useWorkHoursValidation(byWeekDay, workHours);
95
+
87
96
  const onSubmit = (nextState: RecurringDatePickerInputValues) => {
88
97
  const end = getDateTimeObject(endDate, endTime || "23:59:59");
89
98
 
@@ -188,6 +197,8 @@ export function RecurringDatePickerInput({
188
197
  <RecurrenceIntervalAndFrequencyInput
189
198
  disabled={disabled}
190
199
  minDate={minDate}
200
+ startTimeRules={validator}
201
+ endTimeRules={validator}
191
202
  />
192
203
 
193
204
  {children}