@licklist/design 0.58.9 → 0.58.11-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 (259) 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/CalendarButtons/CalendarButtons.js +1 -1
  10. package/dist/calendar/components/CalendarDates/CalendarDates.d.ts +2 -2
  11. package/dist/calendar/components/CalendarDates/CalendarDates.d.ts.map +1 -1
  12. package/dist/calendar/components/CalendarDates/CalendarDates.js +1 -1
  13. package/dist/events/edit-event-modal/component/EditEventForm/EditEventForm.js +1 -1
  14. package/dist/events/event-statistic-modal/EventStatisticModal.js +1 -1
  15. package/dist/iframe/event/event-card/IframeEventCard.d.ts +2 -1
  16. package/dist/iframe/event/event-card/IframeEventCard.d.ts.map +1 -1
  17. package/dist/iframe/event/event-card/IframeEventCard.js +1 -1
  18. package/dist/iframe/event/event-venue-map/IframeEventVenueMap.js +1 -1
  19. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts +2 -2
  20. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts.map +1 -1
  21. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.js +1 -1
  22. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.d.ts +4 -2
  23. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.d.ts.map +1 -1
  24. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.js +1 -1
  25. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.d.ts +1 -1
  26. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.d.ts.map +1 -1
  27. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.js +1 -1
  28. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.d.ts +4 -2
  29. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.d.ts.map +1 -1
  30. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.js +1 -1
  31. package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts +4 -0
  32. package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts.map +1 -1
  33. package/dist/iframe/order-process/components/CalendarStepsForm/CalendarStepsForm.js +1 -1
  34. package/dist/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.js +1 -1
  35. package/dist/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.d.ts.map +1 -1
  36. package/dist/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.js +1 -1
  37. package/dist/iframe/page/components/PageBody/constants.d.ts +1 -0
  38. package/dist/iframe/page/components/PageBody/constants.d.ts.map +1 -1
  39. package/dist/iframe/page/components/PageBody/constants.js +1 -1
  40. package/dist/iframe/page/components/PageBody/hooks/useResizePageBody.d.ts.map +1 -1
  41. package/dist/iframe/page/components/PageBody/hooks/useResizePageBody.js +1 -1
  42. package/dist/iframe/payment/order-items-table/OrderItemsTable.js +1 -1
  43. package/dist/iframe/payment/order-items-table/utils/paymentSummary.js +1 -1
  44. package/dist/iframe/payment/payment-form/PaymentForm.js +1 -1
  45. package/dist/iframe/payment/payment-page/PaymentPage.d.ts.map +1 -1
  46. package/dist/iframe/payment/payment-page/PaymentPage.js +1 -1
  47. package/dist/iframe/payment/payment-page/PaymentTimer.js +1 -1
  48. package/dist/iframe/payment/payment-status-page/PaymentStatusPage.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/index.js +1 -1
  55. package/dist/product-set/card/ProductSetCard.d.ts +2 -1
  56. package/dist/product-set/card/ProductSetCard.d.ts.map +1 -1
  57. package/dist/product-set/card/ProductSetCard.js +1 -1
  58. package/dist/product-set/control/DateAndRecurrenceInput.d.ts.map +1 -1
  59. package/dist/product-set/control/DateAndRecurrenceInput.js +1 -1
  60. package/dist/product-set/control/DateInput.d.ts +17 -0
  61. package/dist/product-set/control/DateInput.d.ts.map +1 -0
  62. package/dist/product-set/control/DateInput.js +1 -0
  63. package/dist/product-set/control/ProductSetControl.d.ts +2 -1
  64. package/dist/product-set/control/ProductSetControl.d.ts.map +1 -1
  65. package/dist/product-set/control/ProductSetControl.js +1 -1
  66. package/dist/product-set/control/ProductSetRecurrenceOverridesControl.d.ts +11 -0
  67. package/dist/product-set/control/ProductSetRecurrenceOverridesControl.d.ts.map +1 -0
  68. package/dist/product-set/control/ProductSetRecurrenceOverridesControl.js +1 -0
  69. package/dist/product-set/control/TutorialGifCard.d.ts +2 -1
  70. package/dist/product-set/control/TutorialGifCard.d.ts.map +1 -1
  71. package/dist/product-set/control/TutorialGifCard.js +1 -1
  72. package/dist/product-set/form/ProductCategoriesControl.d.ts +2 -1
  73. package/dist/product-set/form/ProductCategoriesControl.d.ts.map +1 -1
  74. package/dist/product-set/form/ProductCategoriesControl.js +1 -1
  75. package/dist/product-set/form/ProductSetForm.d.ts +7 -2
  76. package/dist/product-set/form/ProductSetForm.d.ts.map +1 -1
  77. package/dist/product-set/form/ProductSetForm.js +1 -1
  78. package/dist/product-set/form/ProductsControl.d.ts +2 -1
  79. package/dist/product-set/form/ProductsControl.d.ts.map +1 -1
  80. package/dist/product-set/form/ProductsControl.js +1 -1
  81. package/dist/product-set/form/StepsControl.d.ts +2 -1
  82. package/dist/product-set/form/StepsControl.d.ts.map +1 -1
  83. package/dist/product-set/form/StepsControl.js +1 -1
  84. package/dist/product-set/form/SubProductsControl.d.ts +2 -1
  85. package/dist/product-set/form/SubProductsControl.d.ts.map +1 -1
  86. package/dist/product-set/form/SubProductsControl.js +1 -1
  87. package/dist/product-set/form/VenueMapsControl.js +1 -1
  88. package/dist/product-set/hooks/useSortableTreeFunctions.d.ts +2 -1
  89. package/dist/product-set/hooks/useSortableTreeFunctions.d.ts.map +1 -1
  90. package/dist/product-set/hooks/useSortableTreeFunctions.js +1 -1
  91. package/dist/product-set/item/CreateProductSetItem.d.ts +2 -1
  92. package/dist/product-set/item/CreateProductSetItem.d.ts.map +1 -1
  93. package/dist/product-set/item/CreateProductSetItem.js +1 -1
  94. package/dist/product-set/product/ProductControl.d.ts +3 -1
  95. package/dist/product-set/product/ProductControl.d.ts.map +1 -1
  96. package/dist/product-set/product/ProductControl.js +1 -1
  97. package/dist/product-set/product/constants.d.ts +1 -0
  98. package/dist/product-set/product/constants.d.ts.map +1 -1
  99. package/dist/product-set/product/constants.js +1 -1
  100. package/dist/product-set/product/fixed-duration-fields/FixedDurationOptions.d.ts +4 -2
  101. package/dist/product-set/product/fixed-duration-fields/FixedDurationOptions.d.ts.map +1 -1
  102. package/dist/product-set/product/fixed-duration-fields/FixedDurationOptions.js +1 -1
  103. package/dist/product-set/product/quantity/ProductQuantityControl.d.ts +1 -0
  104. package/dist/product-set/product/quantity/ProductQuantityControl.d.ts.map +1 -1
  105. package/dist/product-set/product/quantity/ProductQuantityControl.js +1 -1
  106. package/dist/product-set/product-category/ProductCategoryControl.d.ts +3 -1
  107. package/dist/product-set/product-category/ProductCategoryControl.d.ts.map +1 -1
  108. package/dist/product-set/product-category/ProductCategoryControl.js +1 -1
  109. package/dist/provider/working-hours-input/WorkingHoursInputDescription.d.ts.map +1 -1
  110. package/dist/provider/working-hours-input/WorkingHoursInputDescription.js +1 -1
  111. package/dist/recurring-date-picker-input/DatePickerInput.d.ts +19 -0
  112. package/dist/recurring-date-picker-input/DatePickerInput.d.ts.map +1 -0
  113. package/dist/recurring-date-picker-input/DatePickerInput.js +1 -0
  114. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.d.ts +15 -0
  115. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.d.ts.map +1 -0
  116. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.js +1 -0
  117. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts +5 -1
  118. package/dist/recurring-date-picker-input/RecurringDatePickerInput.d.ts.map +1 -1
  119. package/dist/recurring-date-picker-input/RecurringDatePickerInput.js +1 -1
  120. package/dist/recurring-date-picker-input/utils.d.ts +9 -0
  121. package/dist/recurring-date-picker-input/utils.d.ts.map +1 -1
  122. package/dist/recurring-date-picker-input/utils.js +1 -1
  123. package/dist/sales/booking/results/components/ResultCard.d.ts.map +1 -1
  124. package/dist/sales/booking/results/components/ResultCard.js +1 -1
  125. package/dist/sales/notes/NotesTableRow.js +1 -1
  126. package/dist/setting/admin/AdminSettingForm.d.ts +2 -2
  127. package/dist/setting/admin/AdminSettingForm.d.ts.map +1 -1
  128. package/dist/setting/dashboard/snippets/card/SnippetCard.js +1 -1
  129. package/dist/snippet/snippet-template/control/PropertyControl.d.ts +3 -1
  130. package/dist/snippet/snippet-template/control/PropertyControl.d.ts.map +1 -1
  131. package/dist/snippet/snippet-template/control/PropertyControl.js +1 -1
  132. package/dist/snippet/snippet-template/preview/Preview.js +1 -1
  133. package/dist/sortable-list/SortableList.d.ts +2 -1
  134. package/dist/sortable-list/SortableList.d.ts.map +1 -1
  135. package/dist/sortable-list/SortableList.js +1 -1
  136. package/dist/sortable-tree/SortableTreeItem.d.ts +3 -1
  137. package/dist/sortable-tree/SortableTreeItem.d.ts.map +1 -1
  138. package/dist/sortable-tree/SortableTreeItem.js +1 -1
  139. package/dist/static/manual-date-picker/ManualDatePicker.js +1 -1
  140. package/dist/static/manual-date-picker/constants/index.d.ts +4 -1
  141. package/dist/static/manual-date-picker/constants/index.d.ts.map +1 -1
  142. package/dist/static/manual-date-picker/constants/index.js +1 -1
  143. package/dist/static/manual-date-picker/utils/index.d.ts +4 -0
  144. package/dist/static/manual-date-picker/utils/index.d.ts.map +1 -1
  145. package/dist/static/manual-date-picker/utils/index.js +1 -1
  146. package/dist/striped-static-table/StripedStaticTable.js +1 -1
  147. package/dist/styles/iframe-events/Card.scss +24 -8
  148. package/dist/styles/iframe-events/PoweredBy.scss +2 -2
  149. package/dist/styles/iframe-order-process/IframeOrderProcess.scss +57 -20
  150. package/dist/styles/iframe-page/Page.scss +1 -0
  151. package/dist/styles/iframe-page/PageBody.scss +34 -12
  152. package/dist/styles/iframe-page/PageHeader.scss +41 -39
  153. package/dist/styles/product-set/EditVenueMapSetModal.scss +1 -1
  154. package/dist/styles/ryft-payment-form/RyftPaymentForm.scss +125 -2
  155. package/dist/styles/sales/BookingResults.scss +1 -1
  156. package/dist/venue-map-sets/form/components/VenueMapImageControl.js +1 -1
  157. package/dist/zone/form/utils/dates.d.ts.map +1 -1
  158. package/package.json +10 -35
  159. package/src/assets/iframe/calendar.svg +2 -2
  160. package/src/assets/iframe/ticket.svg +2 -2
  161. package/src/calendar/Calendar.stories.tsx +23 -0
  162. package/src/calendar/Calendar.tsx +5 -5
  163. package/src/calendar/components/CalendarDates/CalendarDates.tsx +0 -5
  164. package/src/iframe/event/event-card/IframeEventCard.stories.tsx +1 -0
  165. package/src/iframe/event/event-card/IframeEventCard.tsx +7 -8
  166. package/src/iframe/order-process/components/BookingSummary/BookingSummary.stories.tsx +9 -0
  167. package/src/iframe/order-process/components/BookingSummary/BookingSummary.tsx +58 -7
  168. package/src/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.tsx +8 -0
  169. package/src/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.tsx +4 -4
  170. package/src/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.tsx +63 -10
  171. package/src/iframe/order-process/components/BookingSummary/types/index.ts +4 -0
  172. package/src/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.tsx +1 -1
  173. package/src/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.tsx +3 -1
  174. package/src/iframe/page/components/PageBody/constants.ts +2 -0
  175. package/src/iframe/page/components/PageBody/hooks/useResizePageBody.ts +10 -0
  176. package/src/iframe/payment/order-items-table/utils/paymentSummary.tsx +6 -6
  177. package/src/iframe/payment/payment-page/PaymentPage.stories.tsx +546 -6
  178. package/src/iframe/payment/payment-page/PaymentPage.tsx +38 -29
  179. package/src/iframe/ryft/RyftPaymentForm.tsx +11 -5
  180. package/src/iframe/ryft/utils/ryft-form.ts +47 -0
  181. package/src/product-set/card/ProductSetCard.tsx +12 -1
  182. package/src/product-set/control/DateAndRecurrenceInput.tsx +2 -1
  183. package/src/product-set/control/DateInput.tsx +316 -0
  184. package/src/product-set/control/ProductSetControl.tsx +46 -24
  185. package/src/product-set/control/ProductSetRecurrenceOverridesControl.tsx +63 -0
  186. package/src/product-set/control/TutorialGifCard.tsx +11 -3
  187. package/src/product-set/form/ProductCategoriesControl.tsx +12 -1
  188. package/src/product-set/form/ProductSetForm.tsx +10 -1
  189. package/src/product-set/form/ProductsControl.tsx +10 -0
  190. package/src/product-set/form/StepsControl.tsx +8 -2
  191. package/src/product-set/form/SubProductsControl.tsx +3 -0
  192. package/src/product-set/hooks/useSortableTreeFunctions.ts +6 -0
  193. package/src/product-set/item/CreateProductSetItem.tsx +3 -0
  194. package/src/product-set/product/ProductControl.tsx +48 -15
  195. package/src/product-set/product/constants.ts +1 -0
  196. package/src/product-set/product/fixed-duration-fields/FixedDurationOptions.tsx +8 -2
  197. package/src/product-set/product/quantity/ProductQuantityControl.tsx +4 -3
  198. package/src/product-set/product-category/ProductCategoryControl.tsx +116 -50
  199. package/src/provider/working-hours-input/WorkingHoursInputDescription.tsx +4 -18
  200. package/src/recurring-date-picker-input/DatePickerInput.tsx +93 -0
  201. package/src/recurring-date-picker-input/RecurrenceAndFrequencyInput.tsx +136 -0
  202. package/src/recurring-date-picker-input/RecurringDatePickerInput.tsx +15 -2
  203. package/src/recurring-date-picker-input/utils.ts +75 -0
  204. package/src/sales/booking/results/BookingResults.stories.tsx +3 -2
  205. package/src/sales/booking/results/components/ResultCard.tsx +2 -5
  206. package/src/setting/admin/AdminSettingForm.tsx +2 -2
  207. package/src/snippet/snippet-template/control/PropertyControl.tsx +6 -2
  208. package/src/sortable-list/SortableList.tsx +3 -0
  209. package/src/sortable-tree/SortableTreeItem.tsx +12 -4
  210. package/src/static/manual-date-picker/ManualDatePicker.tsx +3 -3
  211. package/src/static/manual-date-picker/constants/index.ts +6 -2
  212. package/src/static/manual-date-picker/utils/index.ts +11 -0
  213. package/src/static/switch/BooleanSwitch.tsx +1 -1
  214. package/src/styles/iframe-events/Card.scss +24 -8
  215. package/src/styles/iframe-events/PoweredBy.scss +2 -2
  216. package/src/styles/iframe-order-process/IframeOrderProcess.scss +57 -20
  217. package/src/styles/iframe-page/Page.scss +1 -0
  218. package/src/styles/iframe-page/PageBody.scss +34 -12
  219. package/src/styles/iframe-page/PageHeader.scss +41 -39
  220. package/src/styles/product-set/EditVenueMapSetModal.scss +1 -1
  221. package/src/styles/ryft-payment-form/RyftPaymentForm.scss +125 -2
  222. package/src/styles/sales/BookingResults.scss +1 -1
  223. package/src/zone/form/utils/dates.ts +9 -10
  224. package/jest.config.js +0 -29
  225. package/tests/Auth/Authorizer.test.tsx +0 -194
  226. package/tests/Auth/Layout/UserNavDropDown.test.tsx +0 -43
  227. package/tests/Auth/Layout/UserNavDropDownToggle.test.tsx +0 -33
  228. package/tests/Auth/Login/LoginComponent.test.tsx +0 -246
  229. package/tests/Auth/Login/LoginFormComponent.test.tsx +0 -182
  230. package/tests/Auth/Register/RegisterComponent.test.tsx +0 -285
  231. package/tests/Auth/Register/RegisterFormComponent.test.tsx +0 -170
  232. package/tests/Auth/Settings/Dashboard/IpInput.test.tsx +0 -130
  233. package/tests/Auth/Social/SocialCallbackComponent.test.tsx +0 -133
  234. package/tests/Auth/Social/SocialFormComponent.test.tsx +0 -118
  235. package/tests/FileUpload/FileUpload.test.tsx +0 -42
  236. package/tests/Notification/EmailTemplate.test.tsx +0 -82
  237. package/tests/ProductSet/ProductSetPopover.test.tsx +0 -40
  238. package/tests/Report/Report.test.tsx +0 -48
  239. package/tests/Sales/Coupon.test.tsx +0 -51
  240. package/tests/Sales/SalesAndVIews.test.tsx +0 -63
  241. package/tests/SnippetTemplates/SnippetTemplates.test.tsx +0 -56
  242. package/tests/Table/FilterHelperComponent.test.tsx +0 -88
  243. package/tests/Table/PaginationHelperComponent.test.tsx +0 -109
  244. package/tests/Table/PerPageHelperComponent.test.tsx +0 -34
  245. package/tests/Table/TableHelperComponent.test.tsx +0 -295
  246. package/tests/TipTapEditor/TipTapEditor.test.tsx +0 -28
  247. package/tests/__mock__/hooks/useAuthApi.ts +0 -13
  248. package/tests/__mock__/hooks/useAuthMock.ts +0 -13
  249. package/tests/__mock__/hooks/useFormMock.ts +0 -27
  250. package/tests/__mock__/hooks/useNotificationMock.ts +0 -13
  251. package/tests/__mock__/hooks/useQueryMock.ts +0 -16
  252. package/tests/__mock__/hooks/useSocialApiMock.ts +0 -20
  253. package/tests/__mock__/hooks/useTranslationMock.ts +0 -17
  254. package/tests/__mock__/hooks/useUserApiMock.ts +0 -18
  255. package/tests/__mock__/hooks/useUserMock.ts +0 -13
  256. package/tests/__mock__/styleMock.js +0 -1
  257. package/tests/__mock__/windowMock.ts +0 -5
  258. package/tests/packages/react-query.tsx +0 -28
  259. 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
+ };
@@ -18,6 +18,7 @@ export interface ProductSetCardProps extends HasPermissionProp {
18
18
  onCopy: () => void;
19
19
  onRemove: () => void;
20
20
  className?: string;
21
+ override?: number;
21
22
  }
22
23
 
23
24
  export function ProductSetCard({
@@ -28,6 +29,7 @@ export function ProductSetCard({
28
29
  onRemove,
29
30
  className = "",
30
31
  hasPermission = true,
32
+ override = 0,
31
33
  }: ProductSetCardProps) {
32
34
  const { t } = useTranslation("Design");
33
35
  const popoverId = useId();
@@ -44,7 +46,16 @@ export function ProductSetCard({
44
46
  >
45
47
  <div className={productSetCardClasses}>
46
48
  <div className="product-set-card-link">
47
- {name} {rrule && `(${RRule.fromString(rrule).toText()})`}
49
+ <div className="d-flex flex-column">
50
+ <div>
51
+ {name} {rrule && `(${RRule.fromString(rrule).toText()})`}
52
+ </div>
53
+ {!!override && (
54
+ <div className="h6 bold ml-1">
55
+ {`${override} ${t(override > 1 ? "overrides" : "override")}`}
56
+ </div>
57
+ )}
58
+ </div>
48
59
  </div>
49
60
  <div className="d-flex">
50
61
  <div className="product-set-card-menu-eye-container">
@@ -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
@@ -0,0 +1,316 @@
1
+ import React, { useRef, useState } from "react";
2
+ import { Modifier } from "@popperjs/core";
3
+ import { useId } from "@react-aria/utils";
4
+ import { Form, OverlayTrigger, Popover } from "react-bootstrap";
5
+ import { useFieldArray, useFormContext } from "react-hook-form";
6
+ import { useTranslation } from "react-i18next";
7
+ import { useClickAway } from "react-use";
8
+ import { TIMEZONE, TIME_FORMAT } from "@licklist/core/dist/Config/Date";
9
+ import { ProductSetRecurrence } from "@licklist/core/dist/DataMapper/Product/ProductSetRecurrenceDataMapper";
10
+ import { DateTime } from "luxon";
11
+ import RRule, { Frequency } from "rrule";
12
+ import { WorkHour } from "@licklist/core/dist/DataMapper/Provider/WorkHourDataMapper";
13
+
14
+ import { DatePickerInput } from "../../recurring-date-picker-input/DatePickerInput";
15
+ import { CONFIRM_MODAL_ACTIONS } from "../../modals/confirmation/ConfirmModal";
16
+ import { Icon } from "../../static";
17
+
18
+ import {
19
+ AvailableTimesControl,
20
+ AvailableTimesControlRef,
21
+ } from "../../zone/form/components/AvailableTimesControl";
22
+ import {
23
+ RecurringDatePickerInputValues,
24
+ getDateTimeObject,
25
+ } from "../../recurring-date-picker-input/RecurringDatePickerInput";
26
+ import { ProductSetRecurrenceOverridesControl } from "./ProductSetRecurrenceOverridesControl";
27
+ import { MAX_QUANTITY_RECURRENCE_DATE_IN_OVERRIDE } from "../product/constants";
28
+
29
+ export interface DateAndRecurrenceInputValues {
30
+ menuRecurrences?: Partial<ProductSetRecurrence>[];
31
+ }
32
+
33
+ interface DateAndRecurrenceInputProps {
34
+ isEventEditProductSet?: boolean;
35
+ workHours?: WorkHour[];
36
+ providerHasBookingManagement: boolean;
37
+ isLoading?: boolean;
38
+ }
39
+
40
+ export const DateInput = ({
41
+ isEventEditProductSet,
42
+ isLoading,
43
+ workHours,
44
+ providerHasBookingManagement,
45
+ }: DateAndRecurrenceInputProps) => {
46
+ const {
47
+ control,
48
+ register,
49
+ formState: { errors },
50
+ getValues,
51
+ setValue,
52
+ clearErrors,
53
+ } = useFormContext<DateAndRecurrenceInputValues>();
54
+
55
+ const { fields, append, update } = useFieldArray({
56
+ name: "menuRecurrences",
57
+ control,
58
+ keyName: "_id",
59
+ });
60
+
61
+ const [isDatePopoverVisible, setIsDatePopoverVisible] = useState(false);
62
+ const availableTimesFormRef = useRef<AvailableTimesControlRef>();
63
+ const [editState, setEditState] = useState<{
64
+ index: number;
65
+ values: Partial<ProductSetRecurrence>;
66
+ }>({
67
+ index: null,
68
+ values: null,
69
+ });
70
+ const clearEditState = () => setEditState({ index: null, values: null });
71
+
72
+ const popoverRef = useRef<HTMLDivElement>();
73
+
74
+ useClickAway(popoverRef, (event) => {
75
+ const isModal = CONFIRM_MODAL_ACTIONS.includes(
76
+ (event.target as HTMLElement)?.attributes?.getNamedItem("data-id")?.value
77
+ );
78
+
79
+ if (isModal) {
80
+ return;
81
+ }
82
+
83
+ setIsDatePopoverVisible(false);
84
+ clearEditState();
85
+ });
86
+
87
+ const popoverId = useId()!;
88
+
89
+ const handleOnEdit = (next: Partial<ProductSetRecurrence>, index) => {
90
+ clearEditState();
91
+
92
+ // Hotfix for an issue with Popover close & open actions
93
+ setTimeout(() => {
94
+ setEditState({ index, values: next });
95
+ setIsDatePopoverVisible(() => true);
96
+ }, 100);
97
+ };
98
+
99
+ const { t } = useTranslation("Design");
100
+
101
+ // in this method we should fulfill the form with a proper data
102
+ const handleRecurringDateChange = async (
103
+ next: RecurringDatePickerInputValues
104
+ ) => {
105
+ const isAvailableTimesFormValid =
106
+ await availableTimesFormRef.current?.trigger();
107
+
108
+ if (next?.startTime && next?.endTime && isAvailableTimesFormValid) {
109
+ const startTime = DateTime.fromISO(next.startTime);
110
+ const endTime = DateTime.fromISO(next.endTime);
111
+ const { availableTimes } = availableTimesFormRef.current.getValues();
112
+ const validAvalilableTimes = availableTimes.every((time) => {
113
+ const currentAvailableTime = DateTime.fromFormat(time, TIME_FORMAT);
114
+
115
+ return (
116
+ currentAvailableTime.diff(startTime, "minutes").minutes >= 0 &&
117
+ currentAvailableTime.diff(endTime, "minutes").minutes <= 0
118
+ );
119
+ });
120
+ if (!validAvalilableTimes) {
121
+ availableTimesFormRef.current.setError("availableTimes", {
122
+ message: t("Validation:fieldTimeBetween", {
123
+ attribute: t("Design:startTimesSmall"),
124
+ min: startTime.toFormat(TIME_FORMAT),
125
+ max: endTime.toFormat(TIME_FORMAT),
126
+ }),
127
+ });
128
+
129
+ return;
130
+ }
131
+ }
132
+ const start = getDateTimeObject(next.startDate, next.endTime || "23:59:59");
133
+
134
+ const rrule = RRule.optionsToString({
135
+ until: (start as DateTime).toJSDate(),
136
+ byweekday: [],
137
+ freq: Frequency.DAILY,
138
+ tzid: TIMEZONE,
139
+ interval: 1,
140
+ }).replace("RRULE:", "");
141
+
142
+ const availableTime =
143
+ availableTimesFormRef?.current?.getValues()?.availableTimes || null;
144
+ const values = {
145
+ rrule,
146
+ startDate: next.startDate,
147
+ endDate: next.startDate,
148
+ startTime: next.startTime,
149
+ endTime: next.endTime,
150
+ availableTimes: availableTime,
151
+ } as Partial<ProductSetRecurrence>;
152
+
153
+ if (editState.values?.id) {
154
+ values.id = editState.values?.id;
155
+ }
156
+
157
+ if (editState.index !== null) {
158
+ update(editState.index, values);
159
+ } else {
160
+ append(values);
161
+ }
162
+
163
+ setIsDatePopoverVisible(() => false);
164
+ clearEditState();
165
+ };
166
+
167
+ const handleOnAdd = () => {
168
+ if (fields.length >= 1) return;
169
+ clearEditState();
170
+ setIsDatePopoverVisible((prevValue) => !prevValue);
171
+ };
172
+
173
+ const handleDelete = () => {
174
+ const removeIndex = editState.index;
175
+
176
+ setIsDatePopoverVisible(false);
177
+ clearEditState();
178
+
179
+ setTimeout(() => {
180
+ const { menuRecurrences = [] } = getValues();
181
+
182
+ // @TODO looks like workaround
183
+ // Need recheck other places with remove method.
184
+ // or update react-hook-form version.
185
+ // Remove method from useFormFieldArray throw
186
+ // errors while try to remove element by index.
187
+ // So we remove them manually
188
+ setValue(
189
+ "menuRecurrences",
190
+ menuRecurrences.filter(
191
+ (_currentMenuRecurrence, index) => index !== removeIndex
192
+ )
193
+ );
194
+ }, 100);
195
+ };
196
+
197
+ return (
198
+ <Form.Group>
199
+ <Form.Label>
200
+ {t(
201
+ isEventEditProductSet
202
+ ? "whenOverridesAvailable"
203
+ : "productSetAvailable"
204
+ )}
205
+ </Form.Label>
206
+
207
+ <OverlayTrigger
208
+ show={isDatePopoverVisible}
209
+ overlay={
210
+ <Popover id={popoverId} className="rounded">
211
+ <Popover.Content className="shadow-lg rounded" ref={popoverRef}>
212
+ <DatePickerInput
213
+ defaultValues={editState.values}
214
+ onChange={handleRecurringDateChange}
215
+ onDelete={handleDelete}
216
+ >
217
+ {providerHasBookingManagement && (
218
+ <AvailableTimesControl
219
+ workHours={workHours}
220
+ isLoading={isLoading}
221
+ ref={availableTimesFormRef}
222
+ defaultValues={[]}
223
+ errorMessage={
224
+ errors?.menuRecurrences?.[`${editState?.index}`]
225
+ ?.availableTimes?.message
226
+ }
227
+ clearErrorMessage={() =>
228
+ clearErrors(
229
+ `menuRecurrences.${editState?.index}.availableTimes`
230
+ )
231
+ }
232
+ />
233
+ )}
234
+ </DatePickerInput>
235
+ </Popover.Content>
236
+ </Popover>
237
+ }
238
+ trigger="click"
239
+ placement="bottom"
240
+ popperConfig={{ modifiers: [sameWidthPopperModifier] }}
241
+ >
242
+ <div className="product-set-recurrences">
243
+ {fields.map((menuRecurrence, index) => (
244
+ <ProductSetRecurrenceOverridesControl
245
+ key={menuRecurrence._id}
246
+ menuRecurrence={menuRecurrence}
247
+ onEdit={() => handleOnEdit(menuRecurrence, index)}
248
+ errorMessage={
249
+ errors?.menuRecurrences?.[`${index}`]?.availableTimes?.message
250
+ }
251
+ />
252
+ ))}
253
+ {fields.length < MAX_QUANTITY_RECURRENCE_DATE_IN_OVERRIDE && (
254
+ <div
255
+ className="product-set-recurrence-icon-wrapper"
256
+ role="button"
257
+ tabIndex={0}
258
+ onClick={handleOnAdd}
259
+ onKeyDown={handleOnAdd}
260
+ >
261
+ <Icon
262
+ type="plus-circle"
263
+ height="1rem"
264
+ className="product-set-recurrence-icon-add mr-2"
265
+ />
266
+ {t("addDates")}
267
+ </div>
268
+ )}
269
+
270
+ <Form.Control
271
+ type="hidden"
272
+ {...register("menuRecurrences", {
273
+ required: {
274
+ value: true,
275
+ message: t("Validation:fieldMinNumber", {
276
+ attribute: t("dates"),
277
+ min: 1,
278
+ }),
279
+ },
280
+ })}
281
+ />
282
+
283
+ <div className="manual-form-error">
284
+ {errors.menuRecurrences?.message}
285
+ </div>
286
+ </div>
287
+ </OverlayTrigger>
288
+ </Form.Group>
289
+ );
290
+ };
291
+
292
+ export const sameWidthPopperModifier: Modifier<
293
+ "sameWidth",
294
+ Record<string, unknown>
295
+ > = {
296
+ name: "sameWidth",
297
+ enabled: true,
298
+ phase: "beforeWrite",
299
+ requires: ["computeStyles"],
300
+ fn({ state }) {
301
+ const style = {
302
+ width: `${state.rects.reference.width + 4}px`,
303
+ marginLeft: "-2px",
304
+ maxWidth: "unset",
305
+ };
306
+ Object.assign(state.styles.popper, style);
307
+ },
308
+ effect({ state }) {
309
+ const { width } = state.elements.reference.getBoundingClientRect();
310
+ const style = {
311
+ width: `${width}px`,
312
+ maxWidth: "unset",
313
+ };
314
+ Object.assign(state.elements.popper.style, style);
315
+ },
316
+ };
@@ -34,6 +34,7 @@ import TutorialGifCard from "./TutorialGifCard";
34
34
  import { Step } from "../types";
35
35
  import { StepsControl } from "../form/StepsControl";
36
36
  import { Typeahead } from "../../typeahead";
37
+ import { DateInput } from "./DateInput";
37
38
 
38
39
  const OPERATIONAL_COST_TITLES = {
39
40
  [OPERATIONAL_COST_PROVIDER]: "operationalCostProvider",
@@ -86,6 +87,7 @@ export interface ProductSetControlProps {
86
87
  showSmsTemplate?: boolean;
87
88
  workHours?: WorkHour[];
88
89
  providerHasBookingManagement?: boolean;
90
+ isOverrides?: boolean;
89
91
  }
90
92
 
91
93
  export function ProductSetControl({
@@ -101,6 +103,7 @@ export function ProductSetControl({
101
103
  showSmsTemplate,
102
104
  workHours,
103
105
  providerHasBookingManagement = false,
106
+ isOverrides = false,
104
107
  }: ProductSetControlProps) {
105
108
  const { t } = useTranslation(["Design", "Validation", "Notification"]);
106
109
  const {
@@ -118,6 +121,9 @@ export function ProductSetControl({
118
121
  const termsAndConditionsId = useId();
119
122
  const relyOnPeopleTypeId = useId();
120
123
 
124
+ const showSmsTemplateSelector = showSmsTemplate && !isOverrides;
125
+ const showEmailTemplateSelector = showEmailTemplate && !isOverrides;
126
+
121
127
  return (
122
128
  <Row
123
129
  className={`product-set-form ${
@@ -159,20 +165,30 @@ export function ProductSetControl({
159
165
  </Form.Control.Feedback>
160
166
  </Form.Group>
161
167
 
162
- {isCreateAction && (
163
- <DateAndRecurrenceInput
164
- isEventEditProductSet={isEventEditProductSet}
168
+ {isOverrides ? (
169
+ <DateInput
165
170
  workHours={workHours}
166
171
  isLoading={isLoading}
167
172
  providerHasBookingManagement={providerHasBookingManagement}
168
173
  />
174
+ ) : (
175
+ <>
176
+ {isCreateAction && (
177
+ <DateAndRecurrenceInput
178
+ isEventEditProductSet={isEventEditProductSet}
179
+ workHours={workHours}
180
+ isLoading={isLoading}
181
+ providerHasBookingManagement={providerHasBookingManagement}
182
+ />
183
+ )}
184
+ </>
169
185
  )}
170
186
 
171
187
  <div className="divider" />
172
188
 
173
- <TutorialGifCard />
189
+ <TutorialGifCard isOverrides={isOverrides} />
174
190
 
175
- <StepsControl isLoading={isLoading} />
191
+ <StepsControl isLoading={isLoading} isOverrides={isOverrides} />
176
192
  </Col>
177
193
  <Col md={6} sm={12}>
178
194
  <div className="second-column">
@@ -212,6 +228,7 @@ export function ProductSetControl({
212
228
  {...register("operationalCost", { required: true })}
213
229
  as="select"
214
230
  defaultValue={OPERATIONAL_COST_PROVIDER}
231
+ disabled={isOverrides}
215
232
  isInvalid={HookFormService.isInvalid("operationalCost", errors)}
216
233
  >
217
234
  {Object.keys(OPERATIONAL_COST_TYPES).map((operationalCost) => (
@@ -241,6 +258,7 @@ export function ProductSetControl({
241
258
  {...register("relyOnPeopleType")}
242
259
  as="select"
243
260
  defaultValue={null}
261
+ disabled={isOverrides}
244
262
  isInvalid={HookFormService.isInvalid("relyOnPeopleType", errors)}
245
263
  >
246
264
  <option value="">{t("notRequired")} </option>
@@ -268,7 +286,7 @@ export function ProductSetControl({
268
286
  {...register("termsAndConditions")}
269
287
  as="textarea"
270
288
  rows={2}
271
- disabled={isLoading}
289
+ disabled={isLoading || isOverrides}
272
290
  isInvalid={HookFormService.isInvalid(
273
291
  "termsAndConditions",
274
292
  errors
@@ -283,30 +301,32 @@ export function ProductSetControl({
283
301
  <Form.Label className="mt-4">
284
302
  {t("Design:emailTemplate")}
285
303
  </Form.Label>
286
- {showEmailTemplate ? (
287
- <Typeahead
288
- name="emailTemplates"
289
- options={emailTemplates}
290
- isMultipleChoise
291
- placeholder={t("Design:choose")}
292
- noOptionsMessage={t("Design:noActiveTemplates", {
293
- notification: t("Design:email"),
294
- })}
295
- />
296
- ) : (
297
- <WarningMessage
298
- message={t("Design:noActiveTemplates", {
299
- notification: t("Design:email"),
300
- })}
301
- />
302
- )}
304
+ <>
305
+ {showEmailTemplateSelector ? (
306
+ <Typeahead
307
+ name="emailTemplates"
308
+ options={emailTemplates}
309
+ isMultipleChoise
310
+ placeholder={t("Design:choose")}
311
+ noOptionsMessage={t("Design:noActiveTemplates", {
312
+ notification: t("Design:email"),
313
+ })}
314
+ />
315
+ ) : (
316
+ <WarningMessage
317
+ message={t("Design:noActiveTemplates", {
318
+ notification: t("Design:email"),
319
+ })}
320
+ />
321
+ )}
322
+ </>
303
323
 
304
324
  <Form.Label
305
325
  className={clsx(emailTemplates.length > 0 ? "mt-4" : "mt-1")}
306
326
  >
307
327
  {t("Design:smsTemplate")}
308
328
  </Form.Label>
309
- {showSmsTemplate ? (
329
+ {showSmsTemplateSelector ? (
310
330
  <Typeahead
311
331
  name="smsTemplates"
312
332
  options={smsTemplates}
@@ -339,6 +359,7 @@ export function ProductSetControl({
339
359
  onChange={field.onChange}
340
360
  value={fieldValue}
341
361
  as="select"
362
+ disabled={isOverrides}
342
363
  isInvalid={HookFormService.isInvalid(
343
364
  "fieldSetId",
344
365
  errors
@@ -375,6 +396,7 @@ export function ProductSetControl({
375
396
  }) as string;
376
397
  },
377
398
  })}
399
+ disabled={isOverrides}
378
400
  isInvalid={HookFormService.isInvalid("thankYouPageUrl", errors)}
379
401
  />
380
402
 
@@ -0,0 +1,63 @@
1
+ import React from "react";
2
+ import { useIntl } from "react-intl";
3
+ import { ProductSetRecurrence } from "@licklist/core/dist/DataMapper/Product/ProductSetRecurrenceDataMapper";
4
+
5
+ import { Icon } from "../../static";
6
+
7
+ export interface ProductSetRecurrenceControlProps {
8
+ menuRecurrence?: { _id: string } & Partial<ProductSetRecurrence>;
9
+ onEdit?: (onEdit: Partial<ProductSetRecurrence>) => void;
10
+ errorMessage?: string;
11
+ }
12
+
13
+ export const ProductSetRecurrenceOverridesControl = ({
14
+ menuRecurrence,
15
+ onEdit,
16
+ errorMessage,
17
+ }: ProductSetRecurrenceControlProps) => {
18
+ const { formatDate } = useIntl();
19
+
20
+ return (
21
+ <div className="sortable-tree-root flex-column" role="button" tabIndex={0}>
22
+ <div
23
+ key={menuRecurrence.rrule}
24
+ className="product-set-recurrence d-flex flex-column mr-0 mb-3 p-3 px-4 flex-grow-1"
25
+ >
26
+ <span className="d-flex flex-row align-items-center">
27
+ <Icon
28
+ type="calendar"
29
+ height="1rem"
30
+ className="product-set-recurrence-icon-calendar"
31
+ />
32
+ <span className="product-set-recurrence-title d-flex flex-grow-1">
33
+ {formatDate(menuRecurrence.startDate, {
34
+ dateStyle: "medium",
35
+ })}{" "}
36
+ </span>
37
+
38
+ <div
39
+ className="d-inline-flex"
40
+ role="button"
41
+ tabIndex={0}
42
+ onClick={() => onEdit(menuRecurrence)}
43
+ onKeyDown={() => onEdit(menuRecurrence)}
44
+ >
45
+ <Icon
46
+ type="ellipsis-h"
47
+ height="1rem"
48
+ className="product-set-recurrence-icon-more"
49
+ />
50
+ </div>
51
+ </span>
52
+ <span className="product-set-recurrence-description">
53
+ {formatDate(menuRecurrence.startDate, {
54
+ dateStyle: "medium",
55
+ })}{" "}
56
+ </span>
57
+ </div>
58
+ <div className={`manual-form-error ${!errorMessage && "d-none"}`}>
59
+ {errorMessage}
60
+ </div>
61
+ </div>
62
+ );
63
+ };