@licklist/design 0.63.0 → 0.63.1-dev.0

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 (163) 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/product-set/control/DateAndRecurrenceInput.d.ts +1 -5
  14. package/dist/product-set/control/DateAndRecurrenceInput.d.ts.map +1 -1
  15. package/dist/product-set/control/DateAndRecurrenceInput.js +1 -1
  16. package/dist/product-set/control/DateInput.d.ts.map +1 -1
  17. package/dist/product-set/control/DateInput.js +1 -1
  18. package/dist/product-set/control/ProductSetControl.d.ts +4 -3
  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/control/utils.d.ts +5 -0
  22. package/dist/product-set/control/utils.d.ts.map +1 -0
  23. package/dist/product-set/control/utils.js +1 -0
  24. package/dist/product-set/form/ProductCategoriesControl.d.ts +2 -1
  25. package/dist/product-set/form/ProductCategoriesControl.d.ts.map +1 -1
  26. package/dist/product-set/form/ProductCategoriesControl.js +1 -1
  27. package/dist/product-set/form/ProductSetForm.d.ts +4 -1
  28. package/dist/product-set/form/ProductSetForm.d.ts.map +1 -1
  29. package/dist/product-set/form/ProductsControl.d.ts +2 -1
  30. package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
  31. package/dist/product-set/form/ProductsControl.js +1 -1
  32. package/dist/product-set/form/StepsControl.d.ts +2 -1
  33. package/dist/product-set/form/StepsControl.d.ts.map +1 -1
  34. package/dist/product-set/form/StepsControl.js +1 -1
  35. package/dist/product-set/hooks/useSortableTreeFunctions.d.ts.map +1 -1
  36. package/dist/product-set/product/ProductControl.d.ts +1 -0
  37. package/dist/product-set/product/ProductControl.d.ts.map +1 -1
  38. package/dist/product-set/product/ProductControl.js +1 -1
  39. package/dist/product-set/product/fixed-duration-fields/FixedDurationOptions.d.ts.map +1 -1
  40. package/dist/product-set/step/StepControl.d.ts +2 -1
  41. package/dist/product-set/step/StepControl.d.ts.map +1 -1
  42. package/dist/product-set/step/StepControl.js +1 -1
  43. package/dist/provider/working-hours-input/WorkingHoursInputDescription.d.ts.map +1 -1
  44. package/dist/provider/working-hours-input/WorkingHoursInputDescription.js +1 -1
  45. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.d.ts.map +1 -1
  46. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts +3 -1
  47. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts.map +1 -1
  48. package/dist/recurring-date-picker-input/RecurringDatePickerInput.js +1 -1
  49. package/dist/recurring-date-picker-input/utils.d.ts +6 -0
  50. package/dist/recurring-date-picker-input/utils.d.ts.map +1 -1
  51. package/dist/recurring-date-picker-input/utils.js +1 -1
  52. package/dist/sales/booking/results/components/ResultCard.d.ts.map +1 -1
  53. package/dist/sales/booking/results/components/ResultCard.js +1 -1
  54. package/dist/sales/coupon/control/CouponFormControl.d.ts +2 -1
  55. package/dist/sales/coupon/control/CouponFormControl.d.ts.map +1 -1
  56. package/dist/sales/coupon/control/CouponFormControl.js +1 -1
  57. package/dist/sales/coupon/form/CouponFrom.d.ts +2 -2
  58. package/dist/sales/coupon/form/CouponFrom.d.ts.map +1 -1
  59. package/dist/sales/coupon/utils/index.d.ts +7 -0
  60. package/dist/sales/coupon/utils/index.d.ts.map +1 -0
  61. package/dist/sales/coupon/utils/index.js +1 -0
  62. package/dist/setting/admin/AdminSettingForm.d.ts +2 -2
  63. package/dist/setting/admin/AdminSettingForm.d.ts.map +1 -1
  64. package/dist/setting/dashboard/DashboardSettingForm.d.ts +1 -0
  65. package/dist/setting/dashboard/DashboardSettingForm.d.ts.map +1 -1
  66. package/dist/setting/dashboard/DashboardSettingForm.js +1 -1
  67. package/dist/sortable-tree/SortableTreeItem.d.ts +1 -2
  68. package/dist/sortable-tree/SortableTreeItem.d.ts.map +1 -1
  69. package/dist/sortable-tree/SortableTreeItem.js +1 -1
  70. package/dist/styles/sales/BookingResults.scss +1 -1
  71. package/dist/typeahead/Typeahead.d.ts +2 -1
  72. package/dist/typeahead/Typeahead.d.ts.map +1 -1
  73. package/dist/typeahead/Typeahead.js +1 -1
  74. package/dist/zone/form/ZoneForm.d.ts +2 -2
  75. package/dist/zone/form/ZoneForm.d.ts.map +1 -1
  76. package/dist/zone/form/ZoneForm.js +1 -1
  77. package/dist/zone/form/components/AvailableTimesControl.d.ts +0 -2
  78. package/dist/zone/form/components/AvailableTimesControl.d.ts.map +1 -1
  79. package/dist/zone/form/components/ZoneControl.d.ts +2 -2
  80. package/dist/zone/form/components/ZoneControl.d.ts.map +1 -1
  81. package/dist/zone/form/components/ZoneControl.js +1 -1
  82. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts +4 -4
  83. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts.map +1 -1
  84. package/dist/zone/form/components/ZoneRecurrencesControl.js +1 -1
  85. package/dist/zone/form/utils/dates.d.ts.map +1 -1
  86. package/package.json +10 -35
  87. package/src/date-time-button/DateTimeButton.stories.tsx +2 -1
  88. package/src/date-time-button/DateTimeButton.tsx +7 -5
  89. package/src/events/edit-event-modal/component/EditEventForm/EditEventForm.tsx +4 -0
  90. package/src/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.tsx +18 -9
  91. package/src/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.tsx +5 -0
  92. package/src/iframe/payment/order-items-table/utils/paymentSummary.tsx +6 -6
  93. package/src/product-set/control/DateAndRecurrenceInput.tsx +48 -14
  94. package/src/product-set/control/DateInput.tsx +2 -4
  95. package/src/product-set/control/ProductSetControl.stories.tsx +1 -1
  96. package/src/product-set/control/ProductSetControl.tsx +12 -11
  97. package/src/product-set/control/utils.ts +25 -0
  98. package/src/product-set/form/ProductCategoriesControl.tsx +8 -4
  99. package/src/product-set/form/ProductSetForm.stories.tsx +1 -2
  100. package/src/product-set/form/ProductSetForm.tsx +5 -1
  101. package/src/product-set/form/ProductsControl.tsx +87 -77
  102. package/src/product-set/form/StepsControl.tsx +11 -6
  103. package/src/product-set/hooks/useSortableTreeFunctions.ts +2 -0
  104. package/src/product-set/product/ProductControl.tsx +39 -39
  105. package/src/product-set/product/fixed-duration-fields/FixedDurationOptions.tsx +0 -2
  106. package/src/product-set/step/StepControl.tsx +4 -3
  107. package/src/provider/working-hours-input/WorkingHoursInputDescription.tsx +4 -18
  108. package/src/recurring-date-picker-input/RecurrenceAndFrequencyInput.tsx +0 -1
  109. package/src/recurring-date-picker-input/RecurringDatePickerInput.stories.tsx +13 -7
  110. package/src/recurring-date-picker-input/RecurringDatePickerInput.tsx +12 -1
  111. package/src/recurring-date-picker-input/utils.ts +82 -1
  112. package/src/sales/booking/results/BookingResults.stories.tsx +3 -2
  113. package/src/sales/booking/results/components/ResultCard.tsx +2 -5
  114. package/src/sales/coupon/control/CouponFormControl.tsx +28 -51
  115. package/src/sales/coupon/form/CouponFrom.tsx +5 -15
  116. package/src/sales/coupon/utils/index.ts +13 -0
  117. package/src/setting/admin/AdminSettingForm.tsx +2 -2
  118. package/src/setting/dashboard/DashboardSettingForm.tsx +13 -0
  119. package/src/sortable-tree/SortableTreeItem.tsx +1 -4
  120. package/src/static/switch/BooleanSwitch.tsx +1 -1
  121. package/src/styles/sales/BookingResults.scss +1 -1
  122. package/src/typeahead/Typeahead.tsx +16 -3
  123. package/src/zone/form/ZoneForm.tsx +3 -2
  124. package/src/zone/form/components/AvailableTimesControl.tsx +0 -2
  125. package/src/zone/form/components/ZoneControl.tsx +3 -3
  126. package/src/zone/form/components/ZoneRecurrencesControl.tsx +7 -5
  127. package/src/zone/form/utils/dates.ts +9 -10
  128. package/jest.config.js +0 -29
  129. package/tests/Auth/Authorizer.test.tsx +0 -194
  130. package/tests/Auth/Layout/UserNavDropDown.test.tsx +0 -43
  131. package/tests/Auth/Layout/UserNavDropDownToggle.test.tsx +0 -33
  132. package/tests/Auth/Login/LoginComponent.test.tsx +0 -246
  133. package/tests/Auth/Login/LoginFormComponent.test.tsx +0 -182
  134. package/tests/Auth/Register/RegisterComponent.test.tsx +0 -285
  135. package/tests/Auth/Register/RegisterFormComponent.test.tsx +0 -170
  136. package/tests/Auth/Settings/Dashboard/IpInput.test.tsx +0 -130
  137. package/tests/Auth/Social/SocialCallbackComponent.test.tsx +0 -133
  138. package/tests/Auth/Social/SocialFormComponent.test.tsx +0 -118
  139. package/tests/FileUpload/FileUpload.test.tsx +0 -42
  140. package/tests/Notification/EmailTemplate.test.tsx +0 -82
  141. package/tests/ProductSet/ProductSetPopover.test.tsx +0 -40
  142. package/tests/Report/Report.test.tsx +0 -48
  143. package/tests/Sales/Coupon.test.tsx +0 -51
  144. package/tests/Sales/SalesAndVIews.test.tsx +0 -63
  145. package/tests/SnippetTemplates/SnippetTemplates.test.tsx +0 -56
  146. package/tests/Table/FilterHelperComponent.test.tsx +0 -88
  147. package/tests/Table/PaginationHelperComponent.test.tsx +0 -109
  148. package/tests/Table/PerPageHelperComponent.test.tsx +0 -34
  149. package/tests/Table/TableHelperComponent.test.tsx +0 -295
  150. package/tests/TipTapEditor/TipTapEditor.test.tsx +0 -28
  151. package/tests/__mock__/hooks/useAuthApi.ts +0 -13
  152. package/tests/__mock__/hooks/useAuthMock.ts +0 -13
  153. package/tests/__mock__/hooks/useFormMock.ts +0 -27
  154. package/tests/__mock__/hooks/useNotificationMock.ts +0 -13
  155. package/tests/__mock__/hooks/useQueryMock.ts +0 -16
  156. package/tests/__mock__/hooks/useSocialApiMock.ts +0 -20
  157. package/tests/__mock__/hooks/useTranslationMock.ts +0 -17
  158. package/tests/__mock__/hooks/useUserApiMock.ts +0 -18
  159. package/tests/__mock__/hooks/useUserMock.ts +0 -13
  160. package/tests/__mock__/styleMock.js +0 -1
  161. package/tests/__mock__/windowMock.ts +0 -5
  162. package/tests/packages/react-query.tsx +0 -28
  163. package/tests/setupTests.ts +0 -10
@@ -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}
@@ -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
  );
@@ -72,7 +72,6 @@ function RecurrenceAndFrequencyInput({
72
72
  </Form.Control.Feedback>
73
73
  </Form.Group>
74
74
  </Col>
75
-
76
75
  </Row>
77
76
 
78
77
  <Row>
@@ -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}
@@ -1,4 +1,8 @@
1
- import { DateTime } from "luxon";
1
+ import { TIME_FORMAT } from "@licklist/core/dist/Config";
2
+ import { WorkHour } from "@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper";
3
+ import { fromFormat } from "@licklist/plugins/dist/utils/dateTime";
4
+ import { DateTime, Interval } from "luxon";
5
+ import { useTranslation } from "react-i18next";
2
6
  import RRule, { Frequency, Weekday } from "rrule";
3
7
 
4
8
  export const getWeekdayForFrequency = ({
@@ -11,6 +15,7 @@ export const getWeekdayForFrequency = ({
11
15
  const parsedDate = DateTime.fromISO(date);
12
16
  return new Weekday(
13
17
  parsedDate.weekday - 1,
18
+ // eslint-disable-next-line no-nested-ternary
14
19
  frequency !== Frequency.MONTHLY
15
20
  ? undefined
16
21
  : parsedDate.day + 7 > parsedDate.daysInMonth
@@ -109,3 +114,79 @@ export const parseAndValidateRRule = ({
109
114
  until: options.until,
110
115
  } as ParsedRRuleOptions;
111
116
  };
117
+
118
+ export const useWorkHoursValidation = (
119
+ byWeekDay: Weekday[] = [],
120
+ workHours: WorkHour[] | undefined
121
+ ) => {
122
+ const { t } = useTranslation("Validation");
123
+ if (!workHours) return {};
124
+
125
+ const fromTimeFormat = fromFormat(TIME_FORMAT);
126
+
127
+ // map every day to array of intervals describing workhours for that day
128
+ let intervalsByDay = workHours.map((workhour, index, self) => {
129
+ const res: Interval[] = [];
130
+
131
+ const startTime = fromTimeFormat(workhour.start);
132
+ const endTime = fromTimeFormat(workhour.end);
133
+
134
+ if (endTime > startTime) {
135
+ res.push(Interval.fromDateTimes(startTime, endTime));
136
+ } else {
137
+ // if end is before start, then it means that end is on the next day
138
+ // so count only to the end of current day
139
+ res.push(Interval.fromDateTimes(startTime, startTime.endOf("day")));
140
+ }
141
+
142
+ const prevIndex = index === 0 ? self.length - 1 : index - 1;
143
+
144
+ const prevStartTime = fromTimeFormat(self[prevIndex].start);
145
+ const prevEndTime = fromTimeFormat(self[prevIndex].end);
146
+
147
+ // if prevStartTime > prevEndTime then it means that prevEndTime is on the current day
148
+ // so we need to add interval from start of current day to prevEndTime
149
+ if (prevStartTime > prevEndTime) {
150
+ res.push(Interval.fromDateTimes(prevEndTime.startOf("day"), prevEndTime));
151
+ }
152
+
153
+ return res;
154
+ });
155
+
156
+ // if length === 0 or length === 7 then all workhours are selected, no need to filter
157
+ if (![0, 7].includes(byWeekDay.length)) {
158
+ intervalsByDay = intervalsByDay.filter((_, index) =>
159
+ byWeekDay.find(({ weekday }) => weekday === index)
160
+ );
161
+ }
162
+
163
+ return {
164
+ validate: (_time: string) => {
165
+ const time = fromTimeFormat(_time);
166
+
167
+ const notFittingIntervalsByDay = intervalsByDay.reduce<Interval[][]>(
168
+ (acc, intervalsByDay) => {
169
+ if (!intervalsByDay.some((interval) => interval.contains(time))) {
170
+ acc.push(intervalsByDay);
171
+ }
172
+ return acc;
173
+ },
174
+ []
175
+ );
176
+
177
+ const notFittingIntervals = notFittingIntervalsByDay
178
+ .flat()
179
+ .filter((interval) => !interval.contains(time));
180
+
181
+ if (notFittingIntervalsByDay.length !== 0) {
182
+ return t("outsideWorkingHours", {
183
+ attribute: notFittingIntervals
184
+ .map((interval) => interval.toFormat("HH:mm"))
185
+ .join(", "),
186
+ });
187
+ }
188
+
189
+ return true;
190
+ },
191
+ };
192
+ };
@@ -3,11 +3,12 @@ import { Meta } from "@storybook/react";
3
3
  import { Event } from "@licklist/core/dist/DataMapper/Provider/EventDataMapper";
4
4
  import { User } from "@licklist/core/dist/DataMapper/User/UserDataMapper";
5
5
  import { Product } from "@licklist/core/dist/DataMapper/Product/ProductDataMapper";
6
- import { Order } from "@licklist/core/dist/DataMapper/Order/OrderDataMapper";
7
6
  import {
7
+ Order,
8
8
  ORDER_SOURCE_IFRAME,
9
9
  ORDER_SOURCE_MANUAL,
10
- } from "@licklist/core/src/DataMapper/Order/OrderDataMapper";
10
+ } from "@licklist/core/dist/DataMapper/Order/OrderDataMapper";
11
+
11
12
  import { BookingResults } from "./BookingResults";
12
13
 
13
14
  export default {
@@ -12,7 +12,6 @@ import { TIME_FORMAT } from "@licklist/core/dist/Config";
12
12
  import * as Config from "@licklist/core/dist/Config";
13
13
  import { formatDateStringForEvent } from "@licklist/plugins/dist/utils/formatDate";
14
14
  import { getOrderSourceTitle } from "@licklist/plugins/dist/utils/sourceTitle";
15
-
16
15
  import Icon from "../../../../static/Icon";
17
16
 
18
17
  export type ResultCardProps = {
@@ -22,8 +21,6 @@ export type ResultCardProps = {
22
21
  onCardClick?: (id: number) => void;
23
22
  };
24
23
 
25
- // @TODO integrate when API will be available
26
- // activity and staff keys
27
24
  export const ResultCard = ({
28
25
  order,
29
26
  className,
@@ -41,10 +38,10 @@ export const ResultCard = ({
41
38
  startDate,
42
39
  products,
43
40
  source,
44
- totalAmount,
45
41
  event,
46
42
  menu,
47
43
  remainingToPay,
44
+ paidAmount,
48
45
  } = order;
49
46
 
50
47
  const productList = products.map((product) => product.name)?.join(", ") || "";
@@ -108,7 +105,7 @@ export const ResultCard = ({
108
105
  )}
109
106
  <p>
110
107
  {t("paidAmount")}:{" "}
111
- {formatNumber(totalAmount, {
108
+ {formatNumber(paidAmount, {
112
109
  style: "currency",
113
110
  currency: Config.Currency.GBP,
114
111
  })}
@@ -21,12 +21,14 @@ import couponCodeRules from "@licklist/plugins/dist/validation/Rules/couponCodeR
21
21
  // import { useId } from "@react-aria/utils";
22
22
 
23
23
  import HTMLInputDateElement from "../../../types/static/HTMLInputDateElement";
24
+ import { Typeahead, TypeaheadOptions } from "../../../typeahead";
25
+ import { convertToTypeaheadOptions } from "../utils";
24
26
 
25
27
  export interface CouponFormValues {
26
28
  name?: string;
27
29
  code: string;
28
30
  discountType: CouponType;
29
- productGroupIds: string[];
31
+ productGroupIds: Array<TypeaheadOptions | ProductGroup>;
30
32
  discount: number;
31
33
  totalType: CouponTotalType;
32
34
  startFrom: string;
@@ -58,9 +60,9 @@ export const CouponFormControl = ({
58
60
  watch,
59
61
  } = useFormContext<CouponFormValues>();
60
62
  const { t } = useTranslation(["Design", "Notification", "App"]);
61
- const [selectedProductGroups, setSelectedProductGroups] = useState<string[]>(
62
- []
63
- );
63
+ const [selectedProductGroups, setSelectedProductGroups] = useState<
64
+ TypeaheadOptions[]
65
+ >([]);
64
66
  /* TODO: Show Recurrent date, when reccurent date bugs are fixed */
65
67
  // const rrule = watch("rrule");
66
68
  // const [recurrent, setRecurrent] = useState(Boolean(rrule));
@@ -85,15 +87,20 @@ export const CouponFormControl = ({
85
87
  [COUPON_TOTAL_TYPE_TOTAL]: t("Design:depositTotal"),
86
88
  };
87
89
 
88
- // Set pre-selected Product Groups
89
90
  useEffect(() => {
90
- setSelectedProductGroups(getValues("productGroupIds"));
91
+ const defaultProductGroup = getValues("productGroupIds");
92
+
93
+ setSelectedProductGroups(
94
+ convertToTypeaheadOptions(defaultProductGroup as ProductGroup[])
95
+ );
91
96
  }, [getValues]);
92
97
 
93
98
  useEffect(() => {
94
99
  setValue("productGroupIds", selectedProductGroups);
95
100
  }, [getValues, setValue, selectedProductGroups]);
96
101
 
102
+ const productGroupList = convertToTypeaheadOptions(productGroups);
103
+
97
104
  /* TODO: Show Recurrent date, when reccurent date bugs are fixed */
98
105
  // useEffect(() => {
99
106
  // if (!recurrent && rrule) {
@@ -251,51 +258,21 @@ export const CouponFormControl = ({
251
258
  </Form.Group>
252
259
  </Col>
253
260
  </Row>
254
- {productGroups && productGroups?.length > 0 && (
255
- <Row>
256
- <Col md={12}>
257
- <h5 className="mt-4">{t("Design:productGroups")}</h5>
258
- <Form.Group className="d-flex flex-wrap justify-content-between mt-4 mb-5">
259
- {productGroups?.map((productGroup) => {
260
- const isGroupSelected =
261
- getValues("productGroupIds")?.includes(
262
- String(productGroup.id)
263
- ) ?? false;
264
-
265
- return (
266
- <Form.Check
267
- key={productGroup.id}
268
- label={productGroup.name}
269
- defaultChecked={isGroupSelected}
270
- disabled={isLoading}
271
- onChange={(e) => {
272
- if (e.target.checked) {
273
- setSelectedProductGroups((prevGroups) =>
274
- Array.from(
275
- new Set([...prevGroups, String(productGroup.id)])
276
- )
277
- );
278
- } else {
279
- setSelectedProductGroups((prevGroups) => {
280
- return prevGroups.filter(
281
- (id) => String(productGroup.id) !== id
282
- );
283
- });
284
- }
285
- }}
286
- />
287
- );
288
- })}
289
- <Form.Control
290
- {...register("productGroupIds")}
291
- hidden
292
- value={selectedProductGroups}
293
- disabled={isLoading}
294
- />
295
- </Form.Group>
296
- </Col>
297
- </Row>
298
- )}
261
+ <Row>
262
+ <Col>
263
+ <Form.Group className="mb-3">
264
+ <Form.Label>{t("Design:productGroups")}</Form.Label>
265
+ <Typeahead
266
+ name="productGroupIds"
267
+ options={productGroupList}
268
+ isMultipleChoise
269
+ isCouponForm
270
+ placeholder={t("Design:choose")}
271
+ noOptionsMessage={t("Design:noSelectedProductGroups")}
272
+ />
273
+ </Form.Group>
274
+ </Col>
275
+ </Row>
299
276
 
300
277
  {/* TODO: Show Recurrent date, when reccurent date bugs are fixed */}
301
278
  {/* {startFromValue && (
@@ -1,5 +1,8 @@
1
1
  import React, { useEffect } from "react";
2
- import { ProductGroup } from "@licklist/core/dist/DataMapper/Product/ProductGroupDataMapper";
2
+ import {
3
+ ProductGroup,
4
+ ProductGroupDTO,
5
+ } from "@licklist/core/dist/DataMapper/Product/ProductGroupDataMapper";
3
6
  import {
4
7
  CouponTotalType,
5
8
  CouponType,
@@ -16,7 +19,7 @@ export interface CouponFormValues {
16
19
  name?: string;
17
20
  code: string;
18
21
  discountType: CouponType;
19
- productGroupIds: string[];
22
+ productGroupIds: ProductGroupDTO[];
20
23
  discount: number;
21
24
  totalType: CouponTotalType;
22
25
  startFrom: string;
@@ -54,19 +57,6 @@ export const CouponForm = ({
54
57
  const { setError } = form;
55
58
  const { t } = useTranslation(["Design", "Notification", "App"]);
56
59
 
57
- // @TODO: dont need for v1 release
58
- // const [selectedProductGroups, setSelectedProductGroups] = useState<string[]>(
59
- // []
60
- // );
61
- // Set pre-selected Product Groups
62
- // useEffect(() => {
63
- // setSelectedProductGroups(getValues("productGroupIds"));
64
- // }, [getValues]);
65
-
66
- // useEffect(() => {
67
- // setValue("productGroupIds", selectedProductGroups);
68
- // }, [getValues, setValue, selectedProductGroups]);
69
-
70
60
  useEffect(() => {
71
61
  FormErrorService.handleServerErrors(serverErrors, setError);
72
62
  }, [serverErrors, setError]);
@@ -0,0 +1,13 @@
1
+ import { ProductGroup } from "@licklist/core/dist/DataMapper/Product/ProductGroupDataMapper";
2
+
3
+ export const convertToTypeaheadOptions = (productGroups?: ProductGroup[]) => {
4
+ if (!productGroups || !productGroups.length) {
5
+ return [];
6
+ }
7
+
8
+ return productGroups.map(({ id, name }: ProductGroup) => ({
9
+ id: Number(id),
10
+ value: name,
11
+ label: name,
12
+ }));
13
+ };
@@ -11,7 +11,7 @@ import Row from "react-bootstrap/Row";
11
11
  import Col from "react-bootstrap/Col";
12
12
  import { Link } from "react-router-dom";
13
13
  import HookFormService from "@licklist/plugins/dist/services/Form/HookFormService";
14
- import { ProviderType } from "@licklist/core/dist/DataMapper/Provider/ProvidableDataMapper";
14
+ import { ProvidableType } from "@licklist/core/dist/DataMapper/Provider/ProvidableDataMapper";
15
15
  import Icon from "../../static/Icon";
16
16
  import { PaymentFeeForm, PaymentFeeFormFieldValues } from "./PaymentFeeForm";
17
17
  import { Currency } from "../../types/currency";
@@ -33,7 +33,7 @@ export interface AdminSettingFormProps extends HasPermissionProp {
33
33
  providerMetadata: {
34
34
  country?: string;
35
35
  providableId?: number;
36
- providerType?: ProviderType;
36
+ providerType?: ProvidableType;
37
37
  };
38
38
  }
39
39