@licklist/design 0.58.11 → 0.59.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 (200) hide show
  1. package/bitbucket-pipelines.yml +0 -8
  2. package/dist/assets/iframe/calendar.svg +2 -2
  3. package/dist/assets/iframe/calendar.svg.js +1 -1
  4. package/dist/assets/iframe/ticket.svg +2 -2
  5. package/dist/assets/iframe/ticket.svg.js +1 -1
  6. package/dist/calendar/Calendar.d.ts +1 -1
  7. package/dist/calendar/Calendar.d.ts.map +1 -1
  8. package/dist/calendar/Calendar.js +1 -1
  9. package/dist/calendar/components/CalendarDates/CalendarDates.d.ts +2 -2
  10. package/dist/calendar/components/CalendarDates/CalendarDates.d.ts.map +1 -1
  11. package/dist/calendar/components/CalendarDates/CalendarDates.js +1 -1
  12. package/dist/events/edit-event-modal/component/EditEventForm/EditEventForm.d.ts +3 -1
  13. package/dist/events/edit-event-modal/component/EditEventForm/EditEventForm.d.ts.map +1 -1
  14. package/dist/events/edit-event-modal/component/EditEventForm/EditEventForm.js +1 -1
  15. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.d.ts +3 -1
  16. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.d.ts.map +1 -1
  17. package/dist/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.js +1 -1
  18. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.d.ts +3 -1
  19. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.d.ts.map +1 -1
  20. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.js +1 -1
  21. package/dist/iframe/event/event-card/IframeEventCard.d.ts +2 -1
  22. package/dist/iframe/event/event-card/IframeEventCard.d.ts.map +1 -1
  23. package/dist/iframe/event/event-card/IframeEventCard.js +1 -1
  24. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts +2 -2
  25. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts.map +1 -1
  26. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.js +1 -1
  27. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.d.ts +4 -2
  28. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.d.ts.map +1 -1
  29. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.js +1 -1
  30. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.d.ts +1 -1
  31. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.d.ts.map +1 -1
  32. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.js +1 -1
  33. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.d.ts +4 -2
  34. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.d.ts.map +1 -1
  35. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.js +1 -1
  36. package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts +4 -0
  37. package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts.map +1 -1
  38. package/dist/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.js +1 -1
  39. package/dist/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.d.ts.map +1 -1
  40. package/dist/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.js +1 -1
  41. package/dist/iframe/page/components/PageBody/constants.d.ts +1 -0
  42. package/dist/iframe/page/components/PageBody/constants.d.ts.map +1 -1
  43. package/dist/iframe/page/components/PageBody/constants.js +1 -1
  44. package/dist/iframe/page/components/PageBody/hooks/useResizePageBody.d.ts.map +1 -1
  45. package/dist/iframe/page/components/PageBody/hooks/useResizePageBody.js +1 -1
  46. package/dist/iframe/payment/order-items-table/utils/paymentSummary.js +1 -1
  47. package/dist/iframe/payment/payment-page/PaymentPage.d.ts.map +1 -1
  48. package/dist/iframe/payment/payment-page/PaymentPage.js +1 -1
  49. package/dist/iframe/ryft/RyftPaymentForm.d.ts.map +1 -1
  50. package/dist/iframe/ryft/RyftPaymentForm.js +1 -1
  51. package/dist/iframe/ryft/utils/ryft-form.d.ts +5 -0
  52. package/dist/iframe/ryft/utils/ryft-form.d.ts.map +1 -0
  53. package/dist/iframe/ryft/utils/ryft-form.js +1 -0
  54. package/dist/product-set/control/DateAndRecurrenceInput.d.ts +1 -1
  55. package/dist/product-set/control/DateAndRecurrenceInput.d.ts.map +1 -1
  56. package/dist/product-set/control/DateAndRecurrenceInput.js +1 -1
  57. package/dist/product-set/control/DateInput.d.ts.map +1 -1
  58. package/dist/product-set/control/ProductSetControl.d.ts +1 -1
  59. package/dist/product-set/control/ProductSetControl.d.ts.map +1 -1
  60. package/dist/product-set/form/ProductSetForm.d.ts +4 -1
  61. package/dist/product-set/form/ProductSetForm.d.ts.map +1 -1
  62. package/dist/product-set/hooks/useSortableTreeFunctions.d.ts.map +1 -1
  63. package/dist/product-set/product/ProductControl.d.ts.map +1 -1
  64. package/dist/product-set/product/fixed-duration-fields/FixedDurationOptions.d.ts.map +1 -1
  65. package/dist/product-set/product-category/ProductCategoryControl.d.ts +1 -0
  66. package/dist/product-set/product-category/ProductCategoryControl.d.ts.map +1 -1
  67. package/dist/product-set/product-category/ProductCategoryControl.js +1 -1
  68. package/dist/provider/working-hours-input/WorkingHoursInputDescription.d.ts.map +1 -1
  69. package/dist/provider/working-hours-input/WorkingHoursInputDescription.js +1 -1
  70. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.d.ts.map +1 -1
  71. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts +3 -1
  72. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts.map +1 -1
  73. package/dist/recurring-date-picker-input/RecurringDatePickerInput.js +1 -1
  74. package/dist/recurring-date-picker-input/utils.d.ts +12 -0
  75. package/dist/recurring-date-picker-input/utils.d.ts.map +1 -1
  76. package/dist/recurring-date-picker-input/utils.js +1 -1
  77. package/dist/sales/booking/results/components/ResultCard.d.ts.map +1 -1
  78. package/dist/sales/booking/results/components/ResultCard.js +1 -1
  79. package/dist/setting/admin/AdminSettingForm.d.ts +2 -2
  80. package/dist/setting/admin/AdminSettingForm.d.ts.map +1 -1
  81. package/dist/static/manual-date-picker/ManualDatePicker.js +1 -1
  82. package/dist/static/manual-date-picker/constants/index.d.ts +4 -1
  83. package/dist/static/manual-date-picker/constants/index.d.ts.map +1 -1
  84. package/dist/static/manual-date-picker/constants/index.js +1 -1
  85. package/dist/static/manual-date-picker/utils/index.d.ts +4 -0
  86. package/dist/static/manual-date-picker/utils/index.d.ts.map +1 -1
  87. package/dist/static/manual-date-picker/utils/index.js +1 -1
  88. package/dist/styles/iframe-events/Card.scss +24 -8
  89. package/dist/styles/iframe-events/PoweredBy.scss +2 -2
  90. package/dist/styles/iframe-order-process/IframeOrderProcess.scss +57 -20
  91. package/dist/styles/iframe-page/Page.scss +1 -0
  92. package/dist/styles/iframe-page/PageBody.scss +34 -12
  93. package/dist/styles/iframe-page/PageHeader.scss +41 -39
  94. package/dist/styles/ryft-payment-form/RyftPaymentForm.scss +125 -2
  95. package/dist/styles/sales/BookingResults.scss +1 -1
  96. package/dist/zone/form/ZoneForm.d.ts +2 -2
  97. package/dist/zone/form/ZoneForm.d.ts.map +1 -1
  98. package/dist/zone/form/ZoneForm.js +1 -1
  99. package/dist/zone/form/components/ZoneControl.d.ts +2 -2
  100. package/dist/zone/form/components/ZoneControl.d.ts.map +1 -1
  101. package/dist/zone/form/components/ZoneControl.js +1 -1
  102. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts +4 -4
  103. package/dist/zone/form/components/ZoneRecurrencesControl.d.ts.map +1 -1
  104. package/dist/zone/form/components/ZoneRecurrencesControl.js +1 -1
  105. package/dist/zone/form/utils/dates.d.ts.map +1 -1
  106. package/package.json +10 -35
  107. package/src/assets/iframe/calendar.svg +2 -2
  108. package/src/assets/iframe/ticket.svg +2 -2
  109. package/src/calendar/Calendar.stories.tsx +23 -0
  110. package/src/calendar/Calendar.tsx +5 -5
  111. package/src/calendar/components/CalendarDates/CalendarDates.tsx +0 -5
  112. package/src/events/edit-event-modal/component/EditEventForm/EditEventForm.tsx +4 -0
  113. package/src/events/edit-event-modal/component/SelectEventProductSet/SelectEventProductSet.tsx +10 -8
  114. package/src/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.tsx +4 -0
  115. package/src/iframe/event/event-card/IframeEventCard.stories.tsx +1 -0
  116. package/src/iframe/event/event-card/IframeEventCard.tsx +7 -8
  117. package/src/iframe/order-process/components/BookingSummary/BookingSummary.stories.tsx +9 -0
  118. package/src/iframe/order-process/components/BookingSummary/BookingSummary.tsx +58 -7
  119. package/src/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.tsx +8 -0
  120. package/src/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.tsx +4 -4
  121. package/src/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.tsx +63 -10
  122. package/src/iframe/order-process/components/BookingSummary/types/index.ts +4 -0
  123. package/src/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.tsx +1 -1
  124. package/src/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.tsx +3 -1
  125. package/src/iframe/page/components/PageBody/constants.ts +2 -0
  126. package/src/iframe/page/components/PageBody/hooks/useResizePageBody.ts +10 -0
  127. package/src/iframe/payment/order-items-table/utils/paymentSummary.tsx +6 -6
  128. package/src/iframe/payment/payment-page/PaymentPage.stories.tsx +546 -6
  129. package/src/iframe/payment/payment-page/PaymentPage.tsx +38 -29
  130. package/src/iframe/ryft/RyftPaymentForm.tsx +11 -5
  131. package/src/iframe/ryft/utils/ryft-form.ts +47 -0
  132. package/src/product-set/control/DateAndRecurrenceInput.tsx +3 -2
  133. package/src/product-set/control/DateInput.tsx +1 -3
  134. package/src/product-set/control/ProductSetControl.tsx +1 -1
  135. package/src/product-set/form/ProductCategoriesControl.tsx +1 -1
  136. package/src/product-set/form/ProductSetForm.tsx +5 -1
  137. package/src/product-set/hooks/useSortableTreeFunctions.ts +2 -0
  138. package/src/product-set/product/ProductControl.tsx +6 -3
  139. package/src/product-set/product/fixed-duration-fields/FixedDurationOptions.tsx +0 -2
  140. package/src/product-set/product-category/ProductCategoryControl.tsx +89 -27
  141. package/src/provider/working-hours-input/WorkingHoursInputDescription.tsx +4 -18
  142. package/src/recurring-date-picker-input/RecurrenceAndFrequencyInput.tsx +0 -1
  143. package/src/recurring-date-picker-input/RecurringDatePickerInput.tsx +11 -1
  144. package/src/recurring-date-picker-input/utils.ts +77 -0
  145. package/src/sales/booking/results/BookingResults.stories.tsx +3 -2
  146. package/src/sales/booking/results/components/ResultCard.tsx +2 -5
  147. package/src/setting/admin/AdminSettingForm.tsx +2 -2
  148. package/src/sortable-tree/SortableTreeItem.tsx +1 -1
  149. package/src/static/manual-date-picker/ManualDatePicker.tsx +3 -3
  150. package/src/static/manual-date-picker/constants/index.ts +6 -2
  151. package/src/static/manual-date-picker/utils/index.ts +11 -0
  152. package/src/static/switch/BooleanSwitch.tsx +1 -1
  153. package/src/styles/iframe-events/Card.scss +24 -8
  154. package/src/styles/iframe-events/PoweredBy.scss +2 -2
  155. package/src/styles/iframe-order-process/IframeOrderProcess.scss +57 -20
  156. package/src/styles/iframe-page/Page.scss +1 -0
  157. package/src/styles/iframe-page/PageBody.scss +34 -12
  158. package/src/styles/iframe-page/PageHeader.scss +41 -39
  159. package/src/styles/ryft-payment-form/RyftPaymentForm.scss +125 -2
  160. package/src/styles/sales/BookingResults.scss +1 -1
  161. package/src/zone/form/ZoneForm.tsx +3 -2
  162. package/src/zone/form/components/ZoneControl.tsx +3 -3
  163. package/src/zone/form/components/ZoneRecurrencesControl.tsx +7 -5
  164. package/src/zone/form/utils/dates.ts +9 -10
  165. package/jest.config.js +0 -29
  166. package/tests/Auth/Authorizer.test.tsx +0 -194
  167. package/tests/Auth/Layout/UserNavDropDown.test.tsx +0 -43
  168. package/tests/Auth/Layout/UserNavDropDownToggle.test.tsx +0 -33
  169. package/tests/Auth/Login/LoginComponent.test.tsx +0 -246
  170. package/tests/Auth/Login/LoginFormComponent.test.tsx +0 -182
  171. package/tests/Auth/Register/RegisterComponent.test.tsx +0 -285
  172. package/tests/Auth/Register/RegisterFormComponent.test.tsx +0 -170
  173. package/tests/Auth/Settings/Dashboard/IpInput.test.tsx +0 -130
  174. package/tests/Auth/Social/SocialCallbackComponent.test.tsx +0 -133
  175. package/tests/Auth/Social/SocialFormComponent.test.tsx +0 -118
  176. package/tests/FileUpload/FileUpload.test.tsx +0 -42
  177. package/tests/Notification/EmailTemplate.test.tsx +0 -82
  178. package/tests/ProductSet/ProductSetPopover.test.tsx +0 -40
  179. package/tests/Report/Report.test.tsx +0 -48
  180. package/tests/Sales/Coupon.test.tsx +0 -51
  181. package/tests/Sales/SalesAndVIews.test.tsx +0 -63
  182. package/tests/SnippetTemplates/SnippetTemplates.test.tsx +0 -56
  183. package/tests/Table/FilterHelperComponent.test.tsx +0 -88
  184. package/tests/Table/PaginationHelperComponent.test.tsx +0 -109
  185. package/tests/Table/PerPageHelperComponent.test.tsx +0 -34
  186. package/tests/Table/TableHelperComponent.test.tsx +0 -295
  187. package/tests/TipTapEditor/TipTapEditor.test.tsx +0 -28
  188. package/tests/__mock__/hooks/useAuthApi.ts +0 -13
  189. package/tests/__mock__/hooks/useAuthMock.ts +0 -13
  190. package/tests/__mock__/hooks/useFormMock.ts +0 -27
  191. package/tests/__mock__/hooks/useNotificationMock.ts +0 -13
  192. package/tests/__mock__/hooks/useQueryMock.ts +0 -16
  193. package/tests/__mock__/hooks/useSocialApiMock.ts +0 -20
  194. package/tests/__mock__/hooks/useTranslationMock.ts +0 -17
  195. package/tests/__mock__/hooks/useUserApiMock.ts +0 -18
  196. package/tests/__mock__/hooks/useUserMock.ts +0 -13
  197. package/tests/__mock__/styleMock.js +0 -1
  198. package/tests/__mock__/windowMock.ts +0 -5
  199. package/tests/packages/react-query.tsx +0 -28
  200. package/tests/setupTests.ts +0 -10
@@ -1,7 +1,6 @@
1
- import React, { useEffect, useState } from "react";
1
+ import React, { useEffect, useRef, useState } from "react";
2
2
  import { useTranslation } from "react-i18next";
3
3
  import { useForm } from "react-hook-form";
4
- import Form from "react-bootstrap/Form";
5
4
 
6
5
  import Button from "react-bootstrap/Button";
7
6
  import { useHistory } from "react-router-dom";
@@ -14,6 +13,7 @@ import {
14
13
  AttemptPaymentResponse,
15
14
  } from "@licklist/plugins/dist/hooks/Ryft/useRyftPayment";
16
15
  import { BlockLoader, ButtonLoader } from "../../static";
16
+ import { injectComponentsInRyftForm } from "./utils/ryft-form";
17
17
 
18
18
  export const ryftErrorMap: Record<string, string> = {
19
19
  insufficient_funds: "insufficientFunds",
@@ -50,6 +50,7 @@ export const RyftPaymentForm = ({
50
50
  onSubmit,
51
51
  }: RyftPaymentFormProps) => {
52
52
  const { t } = useTranslation(["Design", "Validation", "Ryft"]);
53
+ const formRef = useRef<HTMLFormElement | null>(null);
53
54
  const history = useHistory();
54
55
 
55
56
  const [isValid, setIsValid] = useState(false);
@@ -117,6 +118,12 @@ export const RyftPaymentForm = ({
117
118
  }
118
119
  };
119
120
 
121
+ useEffect(
122
+ () => injectComponentsInRyftForm({ t }),
123
+ // eslint-disable-next-line react-hooks/exhaustive-deps
124
+ [formRef.current?.childNodes?.length]
125
+ );
126
+
120
127
  useEffect(() => {
121
128
  if (!accountId.data || accountId.isError) return;
122
129
 
@@ -175,15 +182,14 @@ export const RyftPaymentForm = ({
175
182
 
176
183
  return (
177
184
  <>
178
- <Form.Label>{t("Design:paymentDetails")}</Form.Label>
179
- {/* For unknown reasons ryft doesn't work with bootstrap form */}
180
185
  <form
186
+ ref={formRef}
181
187
  id="ryft-pay-form"
182
188
  noValidate
183
189
  onSubmit={methods.handleSubmit(handleSubmit)}
184
190
  className="ryft-payment-form"
185
191
  >
186
- <div className="submit-button-wrapper mt-3 p-1">
192
+ <div className="submit-button-wrapper mt-4 p-1">
187
193
  <Button type="submit" disabled={isBtnDisabled || !isValid}>
188
194
  {isBtnDisabled && <ButtonLoader />}
189
195
  {t("Design:buyNow")}
@@ -0,0 +1,47 @@
1
+ import { TFunction } from "react-i18next";
2
+
3
+ export const injectComponentsInRyftForm = ({
4
+ t,
5
+ }: {
6
+ t: TFunction<string[]>;
7
+ }) => {
8
+ const cardContainer = document.getElementById("ryft-pay-iframe");
9
+ const oldCardDividerContainer = document.getElementById(
10
+ "card-title-container"
11
+ );
12
+
13
+ if (!cardContainer || oldCardDividerContainer) {
14
+ return;
15
+ }
16
+
17
+ const cardTitle = document.createElement("div");
18
+ const cardText = document.createElement("div");
19
+ const cardTitleContainer = document.createElement("div");
20
+ cardTitleContainer.id = "card-title-container";
21
+ cardTitle.textContent = t("Design:enterCardDetails");
22
+ cardText.className = "bold-text form-label";
23
+ cardText.innerText = t("Design:paymentDetails");
24
+ cardTitleContainer.append(cardTitle, cardText);
25
+ cardContainer?.before(cardTitleContainer);
26
+
27
+ const payGrid = document.getElementById("ryft-pay-grid");
28
+
29
+ if (!payGrid) {
30
+ return;
31
+ }
32
+
33
+ // Adding title and divider for apple and google pay button
34
+ const mobilePayTitle = document.createElement("div");
35
+ const dividerText = document.createElement("div");
36
+ const divider = document.createElement("div");
37
+ const container = document.createElement("div");
38
+ mobilePayTitle.className = "mobile-pay-title";
39
+ mobilePayTitle.innerText = t("Design:expressCheckoutWith");
40
+ dividerText.id = "mobile-pay-divider-text";
41
+ dividerText.innerText = "or";
42
+ divider.id = "mobile-pay-divider";
43
+ container.id = "mobile-pay-divider-container";
44
+ container.append(dividerText, divider);
45
+ payGrid.before(mobilePayTitle);
46
+ payGrid.after(container);
47
+ };
@@ -36,7 +36,7 @@ export interface DateAndRecurrenceInputValues {
36
36
 
37
37
  interface DateAndRecurrenceInputProps {
38
38
  isEventEditProductSet?: boolean;
39
- workHours?: WorkHour[];
39
+ workHours: WorkHour[] | undefined;
40
40
  providerHasBookingManagement: boolean;
41
41
  isLoading?: boolean;
42
42
  }
@@ -90,7 +90,7 @@ export const DateAndRecurrenceInput = ({
90
90
  clearEditState();
91
91
  });
92
92
 
93
- const popoverId = useId()!;
93
+ const popoverId = useId();
94
94
 
95
95
  const { t } = useTranslation("Design");
96
96
 
@@ -228,6 +228,7 @@ export const DateAndRecurrenceInput = ({
228
228
  defaultValues={editState.values}
229
229
  onChange={handleRecurringDateChange}
230
230
  onDelete={handleDelete}
231
+ workHours={workHours}
231
232
  >
232
233
  {providerHasBookingManagement && (
233
234
  <AvailableTimesControl
@@ -5,9 +5,8 @@ import { Form, OverlayTrigger, Popover } from "react-bootstrap";
5
5
  import { useFieldArray, useFormContext } from "react-hook-form";
6
6
  import { useTranslation } from "react-i18next";
7
7
  import { useClickAway } from "react-use";
8
- import { TIMEZONE } from "@licklist/core/dist/Config/Date";
8
+ import { TIMEZONE, TIME_FORMAT } from "@licklist/core/dist/Config/Date";
9
9
  import { ProductSetRecurrence } from "@licklist/core/dist/DataMapper/Product/ProductSetRecurrenceDataMapper";
10
- import { TIME_FORMAT } from "@licklist/core/dist/Config/Date";
11
10
  import { DateTime } from "luxon";
12
11
  import RRule, { Frequency } from "rrule";
13
12
  import { WorkHour } from "@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper";
@@ -27,7 +26,6 @@ import {
27
26
  import { ProductSetRecurrenceOverridesControl } from "./ProductSetRecurrenceOverridesControl";
28
27
  import { MAX_QUANTITY_RECURRENCE_DATE_IN_OVERRIDE } from "../product/constants";
29
28
 
30
-
31
29
  export interface DateAndRecurrenceInputValues {
32
30
  menuRecurrences?: Partial<ProductSetRecurrence>[];
33
31
  }
@@ -85,7 +85,7 @@ export interface ProductSetControlProps {
85
85
  fieldSets?: FieldSet[];
86
86
  showEmailTemplate?: boolean;
87
87
  showSmsTemplate?: boolean;
88
- workHours?: WorkHour[];
88
+ workHours: WorkHour[] | undefined;
89
89
  providerHasBookingManagement?: boolean;
90
90
  isOverrides?: boolean;
91
91
  }
@@ -307,7 +307,7 @@ export function ProductCategoriesControl({
307
307
  title={t("addCategory")}
308
308
  isOverride={isOverrides}
309
309
  onClick={() => {
310
- if (isOverrides) return;
310
+ if (isOverrides) return;
311
311
  setIsSelectCategoryVisible(true);
312
312
  }}
313
313
  />
@@ -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;
@@ -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,
@@ -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 ProductCategoryControlValues extends FormValues {
26
26
  name: string;
27
27
  minSubItems: number | null;
28
28
  maxSubItems: number | null;
29
+ overallQuantity?: number | null;
29
30
  quantityType: QuantityType;
30
31
  type: CategoryType;
31
32
  isTimeRelated: boolean;
@@ -102,6 +103,7 @@ export function ProductCategoryControl({
102
103
  const collectUserInfoId = useId();
103
104
  const hasTicketId = useId();
104
105
  const zoneId = useId();
106
+ const overallQuantityId = useId();
105
107
 
106
108
  const allowDepositsId = useId();
107
109
  const remainderExpireAfterId = useId();
@@ -127,7 +129,7 @@ export function ProductCategoryControl({
127
129
  // eslint-disable-next-line react-hooks/exhaustive-deps
128
130
  }, [maxSubItems, fieldNamePrefix]);
129
131
 
130
- const shouldShowZoneSelect =
132
+ const isZoneCategory =
131
133
  category.type === CATEGORY_TYPE_FIXED_DURATION ||
132
134
  category.type === CATEGORY_TYPE_GAME;
133
135
 
@@ -327,51 +329,111 @@ export function ProductCategoryControl({
327
329
  </Form.Group>
328
330
  </Col>
329
331
  </Row>
330
-
331
- {shouldShowZoneSelect && (
332
- <Row>
333
- <Col>
334
- <Form.Group controlId={zoneId}>
335
- <Form.Label>{t("Design:zone")}</Form.Label>
332
+ <Row>
333
+ <Col md={6} sm={6} xs={6}>
334
+ <Form.Group controlId={overallQuantityId}>
335
+ <Form.Label>{t("Design:overallQuantity")}</Form.Label>
336
+ <InputGroup hasValidation>
337
+ <InputGroup.Prepend
338
+ className="arrow-up-btn"
339
+ onClick={() => {
340
+ const currentOverallCapacity = Number(
341
+ getValues(`${fieldNamePrefix}.overallQuantity`) || 0
342
+ );
343
+ setValue(
344
+ `${fieldNamePrefix}.overallQuantity`,
345
+ currentOverallCapacity + 1,
346
+ { shouldValidate: true }
347
+ );
348
+ }}
349
+ >
350
+ <InputGroup.Text className="py-0 px-3">
351
+ <IncrementIcon />
352
+ </InputGroup.Text>
353
+ </InputGroup.Prepend>
336
354
  <Controller
337
355
  control={control}
338
- name={`${fieldNamePrefix}.zoneId`}
356
+ name={`${fieldNamePrefix}.overallQuantity`}
339
357
  render={({ field }) => (
340
358
  <Form.Control
341
- as="select"
359
+ min={0}
360
+ step={1}
361
+ type="number"
342
362
  disabled={isOverride}
343
363
  isInvalid={HookFormService.isInvalid<ProductSetFormValues>(
344
- `${fieldNamePrefix}.zoneId`,
364
+ `${fieldNamePrefix}.overallQuantity`,
345
365
  errors
346
366
  )}
347
367
  {...field}
348
- >
349
- <option value={null}>{t("Design:choose")}</option>
350
- {zones.map((zone) => (
351
- <option key={zone.id} value={zone.id}>
352
- {zone.name}
353
- </option>
354
- ))}
355
- </Form.Control>
368
+ />
356
369
  )}
357
370
  rules={{
358
- required: {
359
- value: providerHasBookingManagement,
360
- message: t("Validation:fieldRequired", {
361
- attribute: t("zone"),
362
- }),
371
+ min: {
372
+ value: 0,
373
+ message: t("Validation:fieldMinNumber", {
374
+ attribute: t("overallQuantity"),
375
+ min: 0,
376
+ }) as string,
363
377
  },
364
378
  }}
365
379
  />
366
380
  <Form.Control.Feedback type="invalid">
367
381
  {HookFormService.getErrors<ProductSetFormValues>(
368
- `${fieldNamePrefix}.zoneId`,
382
+ `${fieldNamePrefix}.overallQuantity`,
369
383
  errors
370
384
  )}
371
385
  </Form.Control.Feedback>
372
- </Form.Group>
373
- </Col>
374
- </Row>
386
+ </InputGroup>
387
+ </Form.Group>
388
+ </Col>
389
+ </Row>
390
+
391
+ {isZoneCategory && (
392
+ <>
393
+ <Row>
394
+ <Col>
395
+ <Form.Group controlId={zoneId}>
396
+ <Form.Label>{t("Design:zone")}</Form.Label>
397
+ <Controller
398
+ control={control}
399
+ name={`${fieldNamePrefix}.zoneId`}
400
+ render={({ field }) => (
401
+ <Form.Control
402
+ as="select"
403
+ disabled={isOverride}
404
+ isInvalid={HookFormService.isInvalid<ProductSetFormValues>(
405
+ `${fieldNamePrefix}.zoneId`,
406
+ errors
407
+ )}
408
+ {...field}
409
+ >
410
+ <option value={null}>{t("Design:choose")}</option>
411
+ {zones.map((zone) => (
412
+ <option key={zone.id} value={zone.id}>
413
+ {zone.name}
414
+ </option>
415
+ ))}
416
+ </Form.Control>
417
+ )}
418
+ rules={{
419
+ required: {
420
+ value: providerHasBookingManagement,
421
+ message: t("Validation:fieldRequired", {
422
+ attribute: t("zone"),
423
+ }),
424
+ },
425
+ }}
426
+ />
427
+ <Form.Control.Feedback type="invalid">
428
+ {HookFormService.getErrors<ProductSetFormValues>(
429
+ `${fieldNamePrefix}.zoneId`,
430
+ errors
431
+ )}
432
+ </Form.Control.Feedback>
433
+ </Form.Group>
434
+ </Col>
435
+ </Row>
436
+ </>
375
437
  )}
376
438
  </Col>
377
439
 
@@ -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>
@@ -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
+ useWorkHoursValidationRules,
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 validationRules = useWorkHoursValidationRules(byWeekDay, workHours);
95
+
87
96
  const onSubmit = (nextState: RecurringDatePickerInputValues) => {
88
97
  const end = getDateTimeObject(endDate, endTime || "23:59:59");
89
98
 
@@ -188,6 +197,7 @@ export function RecurringDatePickerInput({
188
197
  <RecurrenceIntervalAndFrequencyInput
189
198
  disabled={disabled}
190
199
  minDate={minDate}
200
+ {...validationRules}
191
201
  />
192
202
 
193
203
  {children}
@@ -1,4 +1,8 @@
1
+ import { TIME_FORMAT } from "@licklist/core/dist/Config";
2
+ import { WorkHour } from "@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper";
3
+ import { dateTimesSortFn } from "@licklist/plugins/dist/utils/dateTime";
1
4
  import { DateTime } 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,75 @@ export const parseAndValidateRRule = ({
109
114
  until: options.until,
110
115
  } as ParsedRRuleOptions;
111
116
  };
117
+
118
+ export const useWorkHoursValidationRules = (
119
+ byWeekDay: Weekday[] = [],
120
+ workHours: WorkHour[] | undefined
121
+ ) => {
122
+ const { t } = useTranslation("Validation");
123
+ if (!workHours) return {};
124
+
125
+ // workhours of selected days, all if no days selected
126
+ const selectedWorkHours = byWeekDay.length
127
+ ? byWeekDay.map(({ weekday }) =>
128
+ workHours.find(({ day }) => day === weekday)
129
+ )
130
+ : workHours;
131
+
132
+ /**
133
+ * start time
134
+ */
135
+ const startTimes = selectedWorkHours
136
+ .map((workhour) => DateTime.fromFormat(workhour.start, TIME_FORMAT))
137
+ .sort(dateTimesSortFn("desc"));
138
+
139
+ const latestStartTime = startTimes[0];
140
+
141
+ const startTimeRules = {
142
+ validate: (date: string) => {
143
+ const selectedDate = DateTime.fromFormat(date, TIME_FORMAT);
144
+ if (selectedDate >= latestStartTime) return true;
145
+
146
+ return t("fieldTimeAfter", {
147
+ attribute: t("Design:startTimeSmall"),
148
+ time: latestStartTime.toFormat(TIME_FORMAT),
149
+ });
150
+ },
151
+ };
152
+
153
+ /**
154
+ * end time
155
+ */
156
+ const endTimes = selectedWorkHours
157
+ .map<string>(({ start, end }) => {
158
+ const startDateTime = DateTime.fromFormat(start, TIME_FORMAT);
159
+ const endDateTime = DateTime.fromFormat(end, TIME_FORMAT);
160
+
161
+ if (startDateTime <= endDateTime) return end;
162
+
163
+ // if end is before start, then it means that end is on the next day
164
+ // so count only to the end of current day
165
+ return "23:59";
166
+ })
167
+ .map((workhour) => DateTime.fromFormat(workhour, TIME_FORMAT))
168
+ .sort(dateTimesSortFn("asc"));
169
+
170
+ const earliestEndTime = endTimes[0];
171
+
172
+ const endTimeRules = {
173
+ validate: (date: string) => {
174
+ const selectedDate = DateTime.fromFormat(date, TIME_FORMAT);
175
+ if (selectedDate <= earliestEndTime) return true;
176
+
177
+ return t("fieldTimeBefore", {
178
+ attribute: t("Design:endTimeSmall"),
179
+ time: earliestEndTime.toFormat(TIME_FORMAT),
180
+ });
181
+ },
182
+ };
183
+
184
+ return {
185
+ startTimeRules,
186
+ endTimeRules,
187
+ };
188
+ };
@@ -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
  })}
@@ -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
 
@@ -374,7 +374,7 @@ export function SortableTreeItem({
374
374
  items={sortableItems}
375
375
  strategy={verticalListSortingStrategy}
376
376
  >
377
- <Collapse in={expanded}>
377
+ <Collapse in={expanded}>
378
378
  <div className="ml-0">{children}</div>
379
379
  </Collapse>
380
380
  </SortableContext>