@licklist/design 0.62.3 → 0.63.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 (170) 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/EditEventForm/EditEventForm.d.ts +3 -1
  4. package/dist/events/edit-event-modal/component/EditEventForm/EditEventForm.d.ts.map +1 -1
  5. package/dist/events/edit-event-modal/component/EditEventForm/EditEventForm.js +1 -1
  6. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.d.ts +3 -1
  7. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.d.ts.map +1 -1
  8. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.js +1 -1
  9. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.d.ts +3 -1
  10. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.d.ts.map +1 -1
  11. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.js +1 -1
  12. package/dist/iframe/payment/order-items-table/utils/paymentSummary.js +1 -1
  13. package/dist/iframe/ryft/RyftPaymentForm.d.ts.map +1 -1
  14. package/dist/iframe/ryft/RyftPaymentForm.js +1 -1
  15. package/dist/iframe/ryft/utils/ryft-form.d.ts.map +1 -1
  16. package/dist/iframe/ryft/utils/ryft-form.js +1 -1
  17. package/dist/product-set/control/DateAndRecurrenceInput.d.ts +1 -5
  18. package/dist/product-set/control/DateAndRecurrenceInput.d.ts.map +1 -1
  19. package/dist/product-set/control/DateAndRecurrenceInput.js +1 -1
  20. package/dist/product-set/control/DateInput.d.ts.map +1 -1
  21. package/dist/product-set/control/DateInput.js +1 -1
  22. package/dist/product-set/control/ProductSetControl.d.ts +4 -3
  23. package/dist/product-set/control/ProductSetControl.d.ts.map +1 -1
  24. package/dist/product-set/control/ProductSetControl.js +1 -1
  25. package/dist/product-set/control/utils.d.ts +5 -0
  26. package/dist/product-set/control/utils.d.ts.map +1 -0
  27. package/dist/product-set/control/utils.js +1 -0
  28. package/dist/product-set/form/ProductCategoriesControl.d.ts +2 -1
  29. package/dist/product-set/form/ProductCategoriesControl.d.ts.map +1 -1
  30. package/dist/product-set/form/ProductCategoriesControl.js +1 -1
  31. package/dist/product-set/form/ProductSetForm.d.ts +4 -1
  32. package/dist/product-set/form/ProductSetForm.d.ts.map +1 -1
  33. package/dist/product-set/form/ProductsControl.d.ts +2 -1
  34. package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
  35. package/dist/product-set/form/ProductsControl.js +1 -1
  36. package/dist/product-set/form/StepsControl.d.ts +2 -1
  37. package/dist/product-set/form/StepsControl.d.ts.map +1 -1
  38. package/dist/product-set/form/StepsControl.js +1 -1
  39. package/dist/product-set/hooks/useSortableTreeFunctions.d.ts.map +1 -1
  40. package/dist/product-set/product/ProductControl.d.ts +1 -0
  41. package/dist/product-set/product/ProductControl.d.ts.map +1 -1
  42. package/dist/product-set/product/ProductControl.js +1 -1
  43. package/dist/product-set/product/fixed-duration-fields/FixedDurationOptions.d.ts.map +1 -1
  44. package/dist/product-set/step/StepControl.d.ts +2 -1
  45. package/dist/product-set/step/StepControl.d.ts.map +1 -1
  46. package/dist/product-set/step/StepControl.js +1 -1
  47. package/dist/provider/working-hours-input/WorkingHoursInputDescription.d.ts.map +1 -1
  48. package/dist/provider/working-hours-input/WorkingHoursInputDescription.js +1 -1
  49. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.d.ts.map +1 -1
  50. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts +3 -1
  51. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts.map +1 -1
  52. package/dist/recurring-date-picker-input/RecurringDatePickerInput.js +1 -1
  53. package/dist/recurring-date-picker-input/utils.d.ts +12 -0
  54. package/dist/recurring-date-picker-input/utils.d.ts.map +1 -1
  55. package/dist/recurring-date-picker-input/utils.js +1 -1
  56. package/dist/sales/booking/results/components/ResultCard.d.ts.map +1 -1
  57. package/dist/sales/booking/results/components/ResultCard.js +1 -1
  58. package/dist/sales/coupon/control/CouponFormControl.d.ts +2 -1
  59. package/dist/sales/coupon/control/CouponFormControl.d.ts.map +1 -1
  60. package/dist/sales/coupon/control/CouponFormControl.js +1 -1
  61. package/dist/sales/coupon/form/CouponFrom.d.ts +2 -2
  62. package/dist/sales/coupon/form/CouponFrom.d.ts.map +1 -1
  63. package/dist/sales/coupon/utils/index.d.ts +7 -0
  64. package/dist/sales/coupon/utils/index.d.ts.map +1 -0
  65. package/dist/sales/coupon/utils/index.js +1 -0
  66. package/dist/setting/admin/AdminSettingForm.d.ts +2 -2
  67. package/dist/setting/admin/AdminSettingForm.d.ts.map +1 -1
  68. package/dist/setting/dashboard/DashboardSettingForm.d.ts +1 -0
  69. package/dist/setting/dashboard/DashboardSettingForm.d.ts.map +1 -1
  70. package/dist/setting/dashboard/DashboardSettingForm.js +1 -1
  71. package/dist/sortable-tree/SortableTreeItem.d.ts +1 -2
  72. package/dist/sortable-tree/SortableTreeItem.d.ts.map +1 -1
  73. package/dist/sortable-tree/SortableTreeItem.js +1 -1
  74. package/dist/styles/ryft-payment-form/RyftPaymentForm.scss +99 -113
  75. package/dist/styles/sales/BookingResults.scss +1 -1
  76. package/dist/typeahead/Typeahead.d.ts +2 -1
  77. package/dist/typeahead/Typeahead.d.ts.map +1 -1
  78. package/dist/typeahead/Typeahead.js +1 -1
  79. package/dist/zone/form/ZoneForm.d.ts +2 -2
  80. package/dist/zone/form/ZoneForm.d.ts.map +1 -1
  81. package/dist/zone/form/ZoneForm.js +1 -1
  82. package/dist/zone/form/components/AvailableTimesControl.d.ts +0 -2
  83. package/dist/zone/form/components/AvailableTimesControl.d.ts.map +1 -1
  84. package/dist/zone/form/components/ZoneControl.d.ts +2 -2
  85. package/dist/zone/form/components/ZoneControl.d.ts.map +1 -1
  86. package/dist/zone/form/components/ZoneControl.js +1 -1
  87. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts +4 -4
  88. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts.map +1 -1
  89. package/dist/zone/form/components/ZoneRecurrencesControl.js +1 -1
  90. package/dist/zone/form/utils/dates.d.ts.map +1 -1
  91. package/package.json +10 -35
  92. package/src/date-time-button/DateTimeButton.stories.tsx +2 -1
  93. package/src/date-time-button/DateTimeButton.tsx +7 -5
  94. package/src/events/edit-event-modal/component/EditEventForm/EditEventForm.tsx +4 -0
  95. package/src/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.tsx +18 -9
  96. package/src/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.tsx +5 -0
  97. package/src/iframe/payment/order-items-table/utils/paymentSummary.tsx +6 -6
  98. package/src/iframe/ryft/RyftPaymentForm.tsx +12 -4
  99. package/src/iframe/ryft/utils/ryft-form.ts +8 -4
  100. package/src/product-set/control/DateAndRecurrenceInput.tsx +48 -14
  101. package/src/product-set/control/DateInput.tsx +2 -4
  102. package/src/product-set/control/ProductSetControl.stories.tsx +1 -1
  103. package/src/product-set/control/ProductSetControl.tsx +12 -11
  104. package/src/product-set/control/utils.ts +25 -0
  105. package/src/product-set/form/ProductCategoriesControl.tsx +8 -4
  106. package/src/product-set/form/ProductSetForm.stories.tsx +1 -2
  107. package/src/product-set/form/ProductSetForm.tsx +5 -1
  108. package/src/product-set/form/ProductsControl.tsx +87 -77
  109. package/src/product-set/form/StepsControl.tsx +11 -6
  110. package/src/product-set/hooks/useSortableTreeFunctions.ts +2 -0
  111. package/src/product-set/product/ProductControl.tsx +39 -39
  112. package/src/product-set/product/fixed-duration-fields/FixedDurationOptions.tsx +0 -2
  113. package/src/product-set/step/StepControl.tsx +4 -3
  114. package/src/provider/working-hours-input/WorkingHoursInputDescription.tsx +4 -18
  115. package/src/recurring-date-picker-input/RecurrenceAndFrequencyInput.tsx +0 -1
  116. package/src/recurring-date-picker-input/RecurringDatePickerInput.tsx +11 -1
  117. package/src/recurring-date-picker-input/utils.ts +77 -0
  118. package/src/sales/booking/results/BookingResults.stories.tsx +3 -2
  119. package/src/sales/booking/results/components/ResultCard.tsx +2 -5
  120. package/src/sales/coupon/control/CouponFormControl.tsx +28 -51
  121. package/src/sales/coupon/form/CouponFrom.tsx +5 -15
  122. package/src/sales/coupon/utils/index.ts +13 -0
  123. package/src/setting/admin/AdminSettingForm.tsx +2 -2
  124. package/src/setting/dashboard/DashboardSettingForm.tsx +13 -0
  125. package/src/sortable-tree/SortableTreeItem.tsx +1 -4
  126. package/src/static/switch/BooleanSwitch.tsx +1 -1
  127. package/src/styles/ryft-payment-form/RyftPaymentForm.scss +99 -113
  128. package/src/styles/sales/BookingResults.scss +1 -1
  129. package/src/typeahead/Typeahead.tsx +16 -3
  130. package/src/zone/form/ZoneForm.tsx +3 -2
  131. package/src/zone/form/components/AvailableTimesControl.tsx +0 -2
  132. package/src/zone/form/components/ZoneControl.tsx +3 -3
  133. package/src/zone/form/components/ZoneRecurrencesControl.tsx +7 -5
  134. package/src/zone/form/utils/dates.ts +9 -10
  135. package/jest.config.js +0 -29
  136. package/tests/Auth/Authorizer.test.tsx +0 -194
  137. package/tests/Auth/Layout/UserNavDropDown.test.tsx +0 -43
  138. package/tests/Auth/Layout/UserNavDropDownToggle.test.tsx +0 -33
  139. package/tests/Auth/Login/LoginComponent.test.tsx +0 -246
  140. package/tests/Auth/Login/LoginFormComponent.test.tsx +0 -182
  141. package/tests/Auth/Register/RegisterComponent.test.tsx +0 -285
  142. package/tests/Auth/Register/RegisterFormComponent.test.tsx +0 -170
  143. package/tests/Auth/Settings/Dashboard/IpInput.test.tsx +0 -130
  144. package/tests/Auth/Social/SocialCallbackComponent.test.tsx +0 -133
  145. package/tests/Auth/Social/SocialFormComponent.test.tsx +0 -118
  146. package/tests/FileUpload/FileUpload.test.tsx +0 -42
  147. package/tests/Notification/EmailTemplate.test.tsx +0 -82
  148. package/tests/ProductSet/ProductSetPopover.test.tsx +0 -40
  149. package/tests/Report/Report.test.tsx +0 -48
  150. package/tests/Sales/Coupon.test.tsx +0 -51
  151. package/tests/Sales/SalesAndVIews.test.tsx +0 -63
  152. package/tests/SnippetTemplates/SnippetTemplates.test.tsx +0 -56
  153. package/tests/Table/FilterHelperComponent.test.tsx +0 -88
  154. package/tests/Table/PaginationHelperComponent.test.tsx +0 -109
  155. package/tests/Table/PerPageHelperComponent.test.tsx +0 -34
  156. package/tests/Table/TableHelperComponent.test.tsx +0 -295
  157. package/tests/TipTapEditor/TipTapEditor.test.tsx +0 -28
  158. package/tests/__mock__/hooks/useAuthApi.ts +0 -13
  159. package/tests/__mock__/hooks/useAuthMock.ts +0 -13
  160. package/tests/__mock__/hooks/useFormMock.ts +0 -27
  161. package/tests/__mock__/hooks/useNotificationMock.ts +0 -13
  162. package/tests/__mock__/hooks/useQueryMock.ts +0 -16
  163. package/tests/__mock__/hooks/useSocialApiMock.ts +0 -20
  164. package/tests/__mock__/hooks/useTranslationMock.ts +0 -17
  165. package/tests/__mock__/hooks/useUserApiMock.ts +0 -18
  166. package/tests/__mock__/hooks/useUserMock.ts +0 -13
  167. package/tests/__mock__/styleMock.js +0 -1
  168. package/tests/__mock__/windowMock.ts +0 -5
  169. package/tests/packages/react-query.tsx +0 -28
  170. package/tests/setupTests.ts +0 -10
@@ -22,14 +22,10 @@ import { SmsTemplate } from "@licklist/core/dist/DataMapper/Notification/SmsTemp
22
22
  import HookFormService from "@licklist/plugins/dist/services/Form/HookFormService";
23
23
  import { ruleForUrlWithProtocol } from "@licklist/plugins/dist/validation/Rules/urlRule";
24
24
  import { WorkHour } from "@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper";
25
+ import { ProductSetRecurrence } from "@licklist/core/dist/DataMapper/Product/ProductSetRecurrenceDataMapper";
25
26
  import { WarningMessage } from "../../static";
26
27
  import { SelectItem } from "../../types/generic/SelectItem";
27
- import {
28
- DateAndRecurrenceInput,
29
- // TODO: Show Date Component, when reccurent date bugs are fixed
30
- // DateAndRecurrenceInput,
31
- DateAndRecurrenceInputValues,
32
- } from "./DateAndRecurrenceInput";
28
+ import { DateAndRecurrenceInput } from "./DateAndRecurrenceInput";
33
29
  import TutorialGifCard from "./TutorialGifCard";
34
30
  import { Step } from "../types";
35
31
  import { StepsControl } from "../form/StepsControl";
@@ -53,7 +49,7 @@ export interface TemplateItem {
53
49
  label: string;
54
50
  }
55
51
 
56
- export interface ProductSetControlValues extends DateAndRecurrenceInputValues {
52
+ export interface ProductSetControlValues {
57
53
  name: string;
58
54
  type: ProductSetType;
59
55
  termsAndConditions: string;
@@ -65,6 +61,7 @@ export interface ProductSetControlValues extends DateAndRecurrenceInputValues {
65
61
  steps: Step[];
66
62
  emailTemplates?: TemplateItem[];
67
63
  smsTemplates?: TemplateItem[];
64
+ menuRecurrences?: Partial<ProductSetRecurrence>[];
68
65
  }
69
66
 
70
67
  export interface ProductSetControlShared {
@@ -85,7 +82,7 @@ export interface ProductSetControlProps {
85
82
  fieldSets?: FieldSet[];
86
83
  showEmailTemplate?: boolean;
87
84
  showSmsTemplate?: boolean;
88
- workHours?: WorkHour[];
85
+ workHours: WorkHour[] | undefined;
89
86
  providerHasBookingManagement?: boolean;
90
87
  isOverrides?: boolean;
91
88
  }
@@ -123,7 +120,7 @@ export function ProductSetControl({
123
120
 
124
121
  const showSmsTemplateSelector = showSmsTemplate && !isOverrides;
125
122
  const showEmailTemplateSelector = showEmailTemplate && !isOverrides;
126
-
123
+ const showDateSelector = !isEventEditProductSet && isOverrides;
127
124
  return (
128
125
  <Row
129
126
  className={`product-set-form ${
@@ -165,7 +162,7 @@ export function ProductSetControl({
165
162
  </Form.Control.Feedback>
166
163
  </Form.Group>
167
164
 
168
- {isOverrides ? (
165
+ {showDateSelector ? (
169
166
  <DateInput
170
167
  workHours={workHours}
171
168
  isLoading={isLoading}
@@ -188,7 +185,11 @@ export function ProductSetControl({
188
185
 
189
186
  <TutorialGifCard isOverrides={isOverrides} />
190
187
 
191
- <StepsControl isLoading={isLoading} isOverrides={isOverrides} />
188
+ <StepsControl
189
+ isLoading={isLoading}
190
+ isEventEditProductSet={isEventEditProductSet}
191
+ isOverrides={isOverrides}
192
+ />
192
193
  </Col>
193
194
  <Col md={6} sm={12}>
194
195
  <div className="second-column">
@@ -0,0 +1,25 @@
1
+ import { TIME_FORMAT } from "@licklist/core/dist/Config";
2
+ import { dateTimesSortFn } from "@licklist/plugins/dist/utils/dateTime";
3
+ import { extractObjectWithLowestKey } from "@licklist/plugins/dist/utils/extractObjectWithLowestKey";
4
+ import { DateTime } from "luxon";
5
+ import { Product, Step } from "../types";
6
+
7
+ const getProductsFromSteps = (steps: Step[]): Product[] =>
8
+ steps.reduce(
9
+ (acc, step) =>
10
+ acc.concat(
11
+ step.productCategories.reduce(
12
+ (acc, productCategory) => acc.concat(productCategory.products),
13
+ []
14
+ )
15
+ ),
16
+ []
17
+ );
18
+
19
+ export const getProductWithSmallestDuration = (steps: Step[]): Product =>
20
+ extractObjectWithLowestKey(getProductsFromSteps(steps), "duration");
21
+
22
+ export const getLatestAvailableDateTime = (array: string[]): DateTime =>
23
+ array
24
+ .map((time) => DateTime.fromFormat(time, TIME_FORMAT))
25
+ .sort(dateTimesSortFn("desc"))[0];
@@ -36,6 +36,7 @@ import { useSortableTreeFunctions } from "../hooks/useSortableTreeFunctions";
36
36
  interface ProductCategoriesControlProps extends WithIsLoading {
37
37
  stepIndex: number;
38
38
  isOverrides?: boolean;
39
+ isEventEditProductSet?: boolean;
39
40
  }
40
41
 
41
42
  const getCategoryDefaultValue = (
@@ -67,6 +68,7 @@ export function ProductCategoriesControl({
67
68
  isLoading,
68
69
  stepIndex,
69
70
  isOverrides,
71
+ isEventEditProductSet,
70
72
  }: ProductCategoriesControlProps) {
71
73
  const { t } = useTranslation("Design");
72
74
  const {
@@ -214,6 +216,10 @@ export function ProductCategoriesControl({
214
216
  ? String(productCategory.id)
215
217
  : productCategory.uniqueId;
216
218
 
219
+ const isOverridesCategory = productCategory.products.some((product) =>
220
+ isEventEditProductSet ? !!product.id : !!product.originalProductId
221
+ );
222
+
217
223
  const onSetIsExpanded = () => {
218
224
  setIsExpanded(productCategoryId);
219
225
  };
@@ -269,7 +275,7 @@ export function ProductCategoriesControl({
269
275
  categoryName={value}
270
276
  stepIndex={stepIndex}
271
277
  productCategoryIndex={index}
272
- isOverride={isOverrides}
278
+ isOverride={isOverrides && isOverridesCategory}
273
279
  />
274
280
  }
275
281
  isOverride={isOverrides}
@@ -296,6 +302,7 @@ export function ProductCategoriesControl({
296
302
  productCategoryIndex={index}
297
303
  categoryType={productCategory.type}
298
304
  isOverrides={isOverrides}
305
+ isEventEditProductSet={isEventEditProductSet}
299
306
  />
300
307
  </SortableTree.Item>
301
308
  )}
@@ -305,9 +312,7 @@ export function ProductCategoriesControl({
305
312
  </SortableTree>
306
313
  <CreateProductSetItem
307
314
  title={t("addCategory")}
308
- isOverride={isOverrides}
309
315
  onClick={() => {
310
- if (isOverrides) return;
311
316
  setIsSelectCategoryVisible(true);
312
317
  }}
313
318
  />
@@ -316,7 +321,6 @@ export function ProductCategoriesControl({
316
321
  isVisible={isSelectCategoryVisible}
317
322
  onHide={() => setIsSelectCategoryVisible(false)}
318
323
  onCategorySelect={(categoryType) => {
319
- if (isOverrides) return;
320
324
  append(getCategoryDefaultValue(categoryType, fields.length));
321
325
  setShowCategoryModal(true);
322
326
  if (
@@ -63,9 +63,9 @@ Default.args = {
63
63
  sort: 100,
64
64
  type: "standard",
65
65
  updatedAt: "2023-05-08T15:55:28.000+03:00",
66
+ defaultDuration: 30,
66
67
  zoneRecurrences: [
67
68
  {
68
- availableTimes: ["10:05", "10:25", "10:45"],
69
69
  endDate: "2022-02-22",
70
70
  endTime: "22:00:00",
71
71
  id: 1,
@@ -90,7 +90,6 @@ Default.args = {
90
90
  updatedAt: "2023-05-08T15:55:28.000+03:00",
91
91
  zoneRecurrences: [
92
92
  {
93
- availableTimes: ["10:05", "10:25", "10:45"],
94
93
  endDate: "2022-02-22",
95
94
  endTime: "22:00:00",
96
95
  id: 1,
@@ -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;
@@ -35,6 +35,7 @@ interface ProductsControlProps extends WithIsLoading {
35
35
  categoryType: CategoryType;
36
36
  zones?: Zone[];
37
37
  isOverrides?: boolean;
38
+ isEventEditProductSet?: boolean;
38
39
  }
39
40
 
40
41
  const getDefaultProductValue = (sort: number): Product => ({
@@ -57,6 +58,7 @@ const getDefaultProductValue = (sort: number): Product => ({
57
58
  quantitySelector: 1,
58
59
  hasSpecialNotes: false,
59
60
  weight: 0,
61
+ originalProductId: null,
60
62
  type: DEFAULT_PRODUCT_TYPE,
61
63
  tierId: Number(uniqueId()),
62
64
  zoneId: null,
@@ -79,6 +81,7 @@ export function ProductsControl({
79
81
  categoryType,
80
82
  zones,
81
83
  isOverrides,
84
+ isEventEditProductSet,
82
85
  }: ProductsControlProps) {
83
86
  const { t } = useTranslation("Design");
84
87
  const form = useFormContext<ProductSetFormValues>();
@@ -203,90 +206,97 @@ export function ProductsControl({
203
206
  onDragEnd={handleDragEnd}
204
207
  sensors={[mouseSensor]}
205
208
  >
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>
209
+ {fields.map((product, index) => {
210
+ const isOverridesProductSet = isEventEditProductSet
211
+ ? !!product.id
212
+ : isOverrides && !!product.originalProductId;
213
+
214
+ return (
215
+ <Controller
216
+ key={product._id}
217
+ control={control}
218
+ name={`${productControlFieldName}.${index}.name` as const}
219
+ rules={{
220
+ required: t("Validation:fieldRequired", {
221
+ attribute: t("name"),
222
+ }) as string,
223
+ }}
224
+ render={({ field: { value, onChange } }) => (
225
+ <SortableTree.Item
226
+ key={`product-${product._id}`}
227
+ id={String(product._id)}
228
+ isExpanded={isFirstProductAdded}
229
+ isInvalid={!!categoryProductErrors}
230
+ title={value}
231
+ isOverride={isOverrides}
232
+ badge={
233
+ <Badge className="product-badge">{t("product")}</Badge>
234
+ }
235
+ isIconInHeader={false}
236
+ cancelChanges={() => cancelChanges(index)}
237
+ edit={() => edit(index)}
238
+ secondaryBadge={getBadgeConfig(categoryType, t(categoryType))}
239
+ subTitle={
240
+ <div className="product-set-badges-container">
241
+ <div className="product-set-subtitle-dot product-set-subtitle-product-dot" />
242
+ <span>
243
+ {`£${prices[index]} ${t("each")} - ${t("qty")}:${
244
+ !isUnlimitedQuantities[index]
245
+ ? ` ${quantities[index]}`
246
+ : t(" unlimited")
247
+ } ${
248
+ !isUnlimitedQuantities[index]
249
+ ? ` - ${t("possibleRevenue")} £${
250
+ prices[index] * quantities[index]
251
+ }`
252
+ : ""
253
+ } `}
254
+ </span>
255
+ </div>
256
+ }
257
+ modalLabel={t("addNewProduct")}
258
+ modalClass={ProductSetModalClasses.product}
259
+ isNewAdded={showProductModal}
260
+ body={
261
+ <ProductControl<ProductSetFormValues>
262
+ isLoading={isLoading}
263
+ quantityType={quantityType}
264
+ allowDeposits={allowDeposits}
265
+ hasBookingManagement={false}
266
+ fieldNamePrefix={
267
+ `${productControlFieldName}.${index}` as const
268
+ }
269
+ productName={value}
270
+ onProductNameChange={onChange}
271
+ hasTicket={hasTicket}
272
+ categoryType={categoryType}
273
+ zoneDuration={catergoryZone?.defaultDuration}
274
+ isOverrides={isOverridesProductSet}
275
+ />
276
+ }
277
+ onDelete={() => onProductRemove(index)}
278
+ validate={() =>
279
+ trigger(`${productControlFieldName}.${index}`)
280
+ }
281
+ saveValidField={saveValidField}
282
+ // preItem={<Popover className="d-none d-sm-block" />}
283
+ >
284
+ <SubProductsControl
253
285
  isLoading={isLoading}
254
286
  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}
287
+ stepIndex={stepIndex}
288
+ productCategoryIndex={productCategoryIndex}
289
+ productIndex={index}
266
290
  />
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
- ))}
291
+ </SortableTree.Item>
292
+ )}
293
+ />
294
+ );
295
+ })}
284
296
  </SortableTree>
285
297
  <CreateProductSetItem
286
298
  title={t("addProduct")}
287
- isOverride={isOverrides}
288
299
  onClick={() => {
289
- if (isOverrides) return;
290
300
  append(getDefaultProductValue(fields.length));
291
301
  setShowProductModal(true);
292
302
 
@@ -19,9 +19,14 @@ import { ProductSetFormValues } from "./ProductSetForm";
19
19
  interface StepsControlProps {
20
20
  isLoading: boolean;
21
21
  isOverrides?: boolean;
22
+ isEventEditProductSet?: boolean;
22
23
  }
23
24
 
24
- export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
25
+ export function StepsControl({
26
+ isLoading,
27
+ isOverrides,
28
+ isEventEditProductSet,
29
+ }: StepsControlProps) {
25
30
  const form = useFormContext<ProductSetFormValues>();
26
31
  const { t } = useTranslation("Design");
27
32
  const [showStepModal, setShowStepModal] = useState(false);
@@ -68,8 +73,8 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
68
73
  <>
69
74
  {fields.map((step, index) => {
70
75
  const stepFieldName = `steps.${index}` as const;
71
-
72
76
  const stepData = getValues(stepFieldName);
77
+ const isOverrideStep = !!step.id;
73
78
 
74
79
  return (
75
80
  <Controller
@@ -92,9 +97,9 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
92
97
  modalLabel={t("addNewStep")}
93
98
  modalClass={ProductSetModalClasses.step}
94
99
  isNewAdded={showStepModal}
95
- edit={() => !isOverrides && edit(index)}
100
+ edit={() => edit(index)}
96
101
  cancelChanges={() => cancelChanges(index)}
97
- isOverride={isOverrides}
102
+ isOverride={isOverrideStep}
98
103
  subTitle={
99
104
  <div className="product-set-badges-container">
100
105
  <div className="product-set-subtitle-dot product-set-subtitle-step-dot" />
@@ -110,6 +115,7 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
110
115
  stepIndex={index}
111
116
  stepName={value}
112
117
  onStepNameChange={onChange}
118
+ isOverrides={isOverrideStep}
113
119
  />
114
120
  }
115
121
  onDelete={() => remove(index)}
@@ -140,6 +146,7 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
140
146
  isLoading={isLoading}
141
147
  stepIndex={index}
142
148
  isOverrides={isOverrides}
149
+ isEventEditProductSet={isEventEditProductSet}
143
150
  />
144
151
  </SortableTree.Item>
145
152
  )}
@@ -149,9 +156,7 @@ export function StepsControl({ isLoading, isOverrides }: StepsControlProps) {
149
156
 
150
157
  <CreateProductSetItem
151
158
  title={t("addStep")}
152
- isOverride={isOverrides}
153
159
  onClick={() => {
154
- if (isOverrides) return;
155
160
  append(getDefaultStepsValues());
156
161
  setShowStepModal(true);
157
162
  if (errors.steps?.type === HookFormService.manualErrorType) {
@@ -24,8 +24,10 @@ export const useSortableTreeFunctions = ({
24
24
  const cancelChanges = (index: number) => {
25
25
  if (isOverrides) return;
26
26
  if (!previousValue) {
27
+ // eslint-disable-next-line consistent-return
27
28
  return remove(index);
28
29
  }
30
+ // eslint-disable-next-line consistent-return
29
31
  return setValue(`${fieldName}.${index}` as const, previousValue);
30
32
  };
31
33
 
@@ -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;
@@ -146,7 +150,7 @@ export function ProductControl<T extends FormValues>({
146
150
  clearErrors,
147
151
  } = useFormContext<T>();
148
152
 
149
- const { setLoading } = useContext(ProductSetLoadingContext);
153
+ const { setLoading, productGroupList } = useContext(ProductSetLoadingContext);
150
154
  const { t } = useTranslation(["Design", "Validation", "ProductSet"]);
151
155
  const [expanded, setExpanded] = useState(false);
152
156
  const [initialImages, setInitialImages] = useState<Image[] | null>(null);
@@ -156,11 +160,10 @@ 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
- // @TODO: no need for v1 release
163
- // const productGroupId = useId();
165
+
166
+ const productGroupId = useId();
164
167
  const descriptionId = useId();
165
168
  const termsAndConditionsId = useId();
166
169
  const isAvailableId = useId();
@@ -400,6 +403,35 @@ export function ProductControl<T extends FormValues>({
400
403
  isRequired={false}
401
404
  defaultColors={PRODUCT_DEfAULT_COLORS}
402
405
  />
406
+
407
+ <Form.Group controlId={productGroupId}>
408
+ <Form.Label>{t("productGroup")}</Form.Label>
409
+ <Form.Control
410
+ as="select"
411
+ {...register(`${fieldNamePrefix}.productGroupId` as Path<T>)}
412
+ isInvalid={HookFormService.isInvalid<T>(
413
+ `${fieldNamePrefix}.productGroupId` as Path<T>,
414
+ errors
415
+ )}
416
+ disabled={isLoading || isOverrides}
417
+ defaultValue=""
418
+ >
419
+ <option value="">{t("Design:selectProductGroup")}</option>
420
+ {productGroupList.map((productGroup) => {
421
+ return (
422
+ <option value={productGroup.id} key={productGroup.id}>
423
+ {productGroup.value}
424
+ </option>
425
+ );
426
+ })}
427
+ </Form.Control>
428
+ <Form.Control.Feedback type="invalid">
429
+ {HookFormService.getErrors<T>(
430
+ `${fieldNamePrefix}.productGroupId` as Path<T>,
431
+ errors
432
+ )}
433
+ </Form.Control.Feedback>
434
+ </Form.Group>
403
435
  </Col>
404
436
  </Row>
405
437
 
@@ -672,38 +704,6 @@ export function ProductControl<T extends FormValues>({
672
704
  </Collapse>
673
705
 
674
706
  <Row>
675
- {/* @TODO: no need for v1 release
676
- <Col xs={12} sm={6}>
677
- <Form.Group controlId={productGroupId}>
678
- <Form.Label>{t("productGroup")}</Form.Label>
679
- <Form.Control
680
- as="select"
681
- {...register(`${fieldNamePrefix}.productGroupId` as Path<T>)}
682
- isInvalid={HookFormService.isInvalid<T>(
683
- `${fieldNamePrefix}.productGroupId` as Path<T>,
684
- errors
685
- )}
686
- disabled={isLoading}
687
- defaultValue=""
688
- >
689
- <option value="">{t("Design:selectProductGroup")}</option>
690
- {productGroupList.map((productGroup) => {
691
- return (
692
- <option value={productGroup.id} key={productGroup.id}>
693
- {productGroup.value}
694
- </option>
695
- );
696
- })}
697
- </Form.Control>
698
- <Form.Control.Feedback type="invalid">
699
- {HookFormService.getErrors<T>(
700
- `${fieldNamePrefix}.productGroupId` as Path<T>,
701
- errors
702
- )}
703
- </Form.Control.Feedback>
704
- </Form.Group>
705
- </Col> */}
706
-
707
707
  <Col xs={12}>
708
708
  {hasBookingManagement && (
709
709
  <ProductBookingManagementControl<T>
@@ -5,8 +5,6 @@ import { FieldNamePrefixPath } from "@licklist/plugins/dist/types/services/Form/
5
5
  import { useWatch } from "react-hook-form";
6
6
  import { FormNumberInput } from "../../../static";
7
7
 
8
-
9
-
10
8
  interface FixedDurationOptionsProps<T> extends FieldNamePrefixPath<T> {
11
9
  isOverrides?: boolean;
12
10
  }
@@ -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}