@licklist/design 0.58.6-dev.1 → 0.58.6-dev.11

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 (108) hide show
  1. package/dist/assets/iframe/calendar.svg +2 -2
  2. package/dist/assets/iframe/calendar.svg.js +1 -1
  3. package/dist/assets/iframe/ticket.svg +2 -2
  4. package/dist/assets/iframe/ticket.svg.js +1 -1
  5. package/dist/calendar/Calendar.d.ts +1 -1
  6. package/dist/calendar/Calendar.d.ts.map +1 -1
  7. package/dist/calendar/Calendar.js +1 -1
  8. package/dist/calendar/components/CalendarButtons/CalendarButtons.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.js +1 -1
  13. package/dist/events/event-statistic-modal/EventStatisticModal.js +1 -1
  14. package/dist/iframe/event/event-venue-map/IframeEventVenueMap.js +1 -1
  15. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts +2 -2
  16. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts.map +1 -1
  17. package/dist/iframe/order-process/components/BookingSummary/BookingSummary.js +1 -1
  18. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.d.ts +4 -2
  19. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.d.ts.map +1 -1
  20. package/dist/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.js +1 -1
  21. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.d.ts +1 -1
  22. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.d.ts.map +1 -1
  23. package/dist/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.js +1 -1
  24. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.d.ts +4 -2
  25. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.d.ts.map +1 -1
  26. package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.js +1 -1
  27. package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts +4 -0
  28. package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts.map +1 -1
  29. package/dist/iframe/order-process/components/CalendarStepsForm/CalendarStepsForm.js +1 -1
  30. package/dist/iframe/page/components/PageBody/components/LeftBlock/LeftBlock.js +1 -1
  31. package/dist/iframe/page/components/PageBody/constants.d.ts +1 -0
  32. package/dist/iframe/page/components/PageBody/constants.d.ts.map +1 -1
  33. package/dist/iframe/page/components/PageBody/constants.js +1 -1
  34. package/dist/iframe/page/components/PageBody/hooks/useResizePageBody.d.ts.map +1 -1
  35. package/dist/iframe/page/components/PageBody/hooks/useResizePageBody.js +1 -1
  36. package/dist/iframe/payment/order-items-table/OrderItemsTable.js +1 -1
  37. package/dist/iframe/payment/payment-form/PaymentForm.js +1 -1
  38. package/dist/iframe/payment/payment-page/PaymentPage.d.ts.map +1 -1
  39. package/dist/iframe/payment/payment-page/PaymentPage.js +1 -1
  40. package/dist/iframe/payment/payment-page/PaymentTimer.js +1 -1
  41. package/dist/iframe/payment/payment-status-page/PaymentStatusPage.js +1 -1
  42. package/dist/iframe/ryft/RyftPaymentForm.d.ts.map +1 -1
  43. package/dist/iframe/ryft/RyftPaymentForm.js +1 -1
  44. package/dist/iframe/ryft/utils/ryft-form.d.ts +5 -0
  45. package/dist/iframe/ryft/utils/ryft-form.d.ts.map +1 -0
  46. package/dist/iframe/ryft/utils/ryft-form.js +1 -0
  47. package/dist/index.js +1 -1
  48. package/dist/product-set/card/ProductSetCard.d.ts.map +1 -1
  49. package/dist/product-set/card/ProductSetCard.js +1 -1
  50. package/dist/product-set/control/DateInput.d.ts.map +1 -1
  51. package/dist/product-set/control/DateInput.js +1 -1
  52. package/dist/product-set/form/VenueMapsControl.js +1 -1
  53. package/dist/product-set/product/ProductControl.d.ts +1 -0
  54. package/dist/product-set/product/ProductControl.d.ts.map +1 -1
  55. package/dist/product-set/product/ProductControl.js +1 -1
  56. package/dist/product-set/product/constants.d.ts +1 -0
  57. package/dist/product-set/product/constants.d.ts.map +1 -1
  58. package/dist/product-set/product/constants.js +1 -1
  59. package/dist/product-set/product-category/ProductCategoryControl.d.ts +1 -0
  60. package/dist/product-set/product-category/ProductCategoryControl.d.ts.map +1 -1
  61. package/dist/product-set/product-category/ProductCategoryControl.js +1 -1
  62. package/dist/provider/working-hours-input/WorkingHoursInputDescription.d.ts.map +1 -1
  63. package/dist/provider/working-hours-input/WorkingHoursInputDescription.js +1 -1
  64. package/dist/recurring-date-picker-input/RecurrenceAndFrequencyInput.js +1 -1
  65. package/dist/sales/booking/results/components/ResultCard.js +1 -1
  66. package/dist/sales/notes/NotesTableRow.js +1 -1
  67. package/dist/setting/dashboard/snippets/card/SnippetCard.js +1 -1
  68. package/dist/snippet/snippet-template/control/PropertyControl.d.ts +3 -1
  69. package/dist/snippet/snippet-template/control/PropertyControl.d.ts.map +1 -1
  70. package/dist/snippet/snippet-template/control/PropertyControl.js +1 -1
  71. package/dist/snippet/snippet-template/preview/Preview.js +1 -1
  72. package/dist/sortable-tree/SortableTreeItem.d.ts.map +1 -1
  73. package/dist/sortable-tree/SortableTreeItem.js +1 -1
  74. package/dist/striped-static-table/StripedStaticTable.js +1 -1
  75. package/dist/styles/iframe-order-process/IframeOrderProcess.scss +57 -18
  76. package/dist/styles/iframe-page/PageBody.scss +2 -1
  77. package/dist/styles/ryft-payment-form/RyftPaymentForm.scss +125 -2
  78. package/dist/venue-map-sets/form/components/VenueMapImageControl.js +1 -1
  79. package/package.json +3 -5
  80. package/src/assets/iframe/calendar.svg +2 -2
  81. package/src/assets/iframe/ticket.svg +2 -2
  82. package/src/calendar/Calendar.stories.tsx +23 -0
  83. package/src/calendar/Calendar.tsx +5 -5
  84. package/src/calendar/components/CalendarDates/CalendarDates.tsx +0 -5
  85. package/src/iframe/order-process/components/BookingSummary/BookingSummary.stories.tsx +9 -0
  86. package/src/iframe/order-process/components/BookingSummary/BookingSummary.tsx +58 -7
  87. package/src/iframe/order-process/components/BookingSummary/components/BookingSummaryAccordion/BookingSummaryAccordion.tsx +8 -0
  88. package/src/iframe/order-process/components/BookingSummary/components/SummaryTotal/components/SummaryTotalBlock.tsx +4 -4
  89. package/src/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.tsx +63 -10
  90. package/src/iframe/order-process/components/BookingSummary/types/index.ts +4 -0
  91. package/src/iframe/page/components/PageBody/constants.ts +2 -0
  92. package/src/iframe/page/components/PageBody/hooks/useResizePageBody.ts +10 -0
  93. package/src/iframe/payment/payment-page/PaymentPage.stories.tsx +546 -6
  94. package/src/iframe/payment/payment-page/PaymentPage.tsx +38 -29
  95. package/src/iframe/ryft/RyftPaymentForm.tsx +11 -5
  96. package/src/iframe/ryft/utils/ryft-form.ts +47 -0
  97. package/src/product-set/card/ProductSetCard.tsx +5 -3
  98. package/src/product-set/control/DateInput.tsx +24 -17
  99. package/src/product-set/product/ProductControl.tsx +25 -3
  100. package/src/product-set/product/constants.ts +1 -0
  101. package/src/product-set/product-category/ProductCategoryControl.tsx +105 -43
  102. package/src/provider/working-hours-input/WorkingHoursInputDescription.tsx +4 -18
  103. package/src/recurring-date-picker-input/RecurrenceAndFrequencyInput.tsx +1 -1
  104. package/src/snippet/snippet-template/control/PropertyControl.tsx +6 -2
  105. package/src/sortable-tree/SortableTreeItem.tsx +6 -4
  106. package/src/styles/iframe-order-process/IframeOrderProcess.scss +57 -18
  107. package/src/styles/iframe-page/PageBody.scss +2 -1
  108. package/src/styles/ryft-payment-form/RyftPaymentForm.scss +125 -2
@@ -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
+ };
@@ -50,9 +50,11 @@ export function ProductSetCard({
50
50
  <div>
51
51
  {name} {rrule && `(${RRule.fromString(rrule).toText()})`}
52
52
  </div>
53
- <div className="h6 bold ml-1">
54
- {!!override && t("overridesAmount", { amount: override })}
55
- </div>
53
+ {!!override && (
54
+ <div className="h6 bold ml-1">
55
+ {`${override} ${t(override > 1 ? "overrides" : "override")}`}
56
+ </div>
57
+ )}
56
58
  </div>
57
59
  </div>
58
60
  <div className="d-flex">
@@ -19,8 +19,12 @@ import {
19
19
  AvailableTimesControl,
20
20
  AvailableTimesControlRef,
21
21
  } from "../../zone/form/components/AvailableTimesControl";
22
- import { RecurringDatePickerInputValues } from "../../recurring-date-picker-input/RecurringDatePickerInput";
22
+ import {
23
+ RecurringDatePickerInputValues,
24
+ getDateTimeObject,
25
+ } from "../../recurring-date-picker-input/RecurringDatePickerInput";
23
26
  import { ProductSetRecurrenceOverridesControl } from "./ProductSetRecurrenceOverridesControl";
27
+ import { MAX_QUANTITY_RECURRENCE_DATE_IN_OVERRIDE } from "../product/constants";
24
28
 
25
29
  export interface DateAndRecurrenceInputValues {
26
30
  menuRecurrences?: Partial<ProductSetRecurrence>[];
@@ -125,13 +129,14 @@ export const DateInput = ({
125
129
  return;
126
130
  }
127
131
  }
132
+ const start = getDateTimeObject(next.startDate, next.endTime || "23:59:59");
128
133
 
129
134
  const rrule = RRule.optionsToString({
130
- dtstart: DateTime.fromISO(next.startDate).toJSDate(),
131
- until: DateTime.fromISO(next.startDate).toJSDate(),
135
+ until: (start as DateTime).toJSDate(),
132
136
  byweekday: [],
133
137
  freq: Frequency.DAILY,
134
138
  tzid: TIMEZONE,
139
+ interval: 1,
135
140
  }).replace("RRULE:", "");
136
141
 
137
142
  const availableTime =
@@ -245,20 +250,22 @@ export const DateInput = ({
245
250
  }
246
251
  />
247
252
  ))}
248
- <div
249
- className="product-set-recurrence-icon-wrapper"
250
- role="button"
251
- tabIndex={0}
252
- onClick={handleOnAdd}
253
- onKeyDown={handleOnAdd}
254
- >
255
- <Icon
256
- type="plus-circle"
257
- height="1rem"
258
- className="product-set-recurrence-icon-add mr-2"
259
- />
260
- {t("addDates")}
261
- </div>
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
+ )}
262
269
 
263
270
  <Form.Control
264
271
  type="hidden"
@@ -7,8 +7,12 @@ 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,
@@ -35,6 +39,7 @@ import {
35
39
  } from "react-hook-form";
36
40
  import { useTranslation } from "react-i18next";
37
41
  import { useImages } from "@licklist/plugins/dist/hooks/Media/useImages";
42
+
38
43
  import {
39
44
  Image,
40
45
  IMAGE_TYPE_IMAGE,
@@ -59,6 +64,7 @@ import {
59
64
  ProductQuantityControl,
60
65
  ProductQuantityRechargingControl,
61
66
  } from "./quantity";
67
+ import { PropertyControl } from "../../snippet";
62
68
  import { TipTapEditor } from "../../tiptap-editor";
63
69
  import { IsDeletableEvent } from "../types";
64
70
  import { FixedDurationOptions } from "./fixed-duration-fields";
@@ -98,6 +104,7 @@ export interface ProductControlValues
98
104
  offset: number;
99
105
  serviceTime: number;
100
106
  sort: number | null;
107
+ color?: string;
101
108
  }
102
109
 
103
110
  export interface ProductControlProps<T>
@@ -143,7 +150,7 @@ export function ProductControl<T extends FormValues>({
143
150
  } = useFormContext<T>();
144
151
 
145
152
  const { setLoading } = useContext(ProductSetLoadingContext);
146
- const { t } = useTranslation(["Design", "Validation"]);
153
+ const { t } = useTranslation(["Design", "Validation", "ProductSet"]);
147
154
  const [expanded, setExpanded] = useState(false);
148
155
  const [initialImages, setInitialImages] = useState<Image[] | null>(null);
149
156
  // @TODO: After checking "isUnlimited" checkbox need to reset field totalQuantity
@@ -388,6 +395,14 @@ export function ProductControl<T extends FormValues>({
388
395
  )}
389
396
  </Form.Control.Feedback>
390
397
  </Form.Group>
398
+
399
+ <PropertyControl<T>
400
+ item={`${fieldNamePrefix}.color` as Path<T>}
401
+ label={t("ProductSet:selectColor")}
402
+ isDisabled={isOverrides}
403
+ isRequired={false}
404
+ defaultColors={PRODUCT_DEfAULT_COLORS}
405
+ />
391
406
  </Col>
392
407
  </Row>
393
408
 
@@ -509,7 +524,14 @@ export function ProductControl<T extends FormValues>({
509
524
  </Form.Group>
510
525
  </Col>
511
526
 
512
- <Col lg={4} md={4} className="licklist-file-upload-wrapper">
527
+ <Col
528
+ lg={4}
529
+ md={4}
530
+ className={clsx(
531
+ "licklist-file-upload-wrapper",
532
+ isOverrides && "opacity-50"
533
+ )}
534
+ >
513
535
  <FileUpload
514
536
  onFilesChange={onFilesChange}
515
537
  allowedExtensions={["jpeg", "jpg", "png"]}
@@ -1 +1,2 @@
1
1
  export const MAX_PRODUCT_DESCRIPTION_CHARACTERS_LENGTH = 1000;
2
+ export const MAX_QUANTITY_RECURRENCE_DATE_IN_OVERRIDE = 1;
@@ -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 overallCapacityId = 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
 
@@ -328,50 +330,110 @@ export function ProductCategoryControl({
328
330
  </Col>
329
331
  </Row>
330
332
 
331
- {shouldShowZoneSelect && (
332
- <Row>
333
- <Col>
334
- <Form.Group controlId={zoneId}>
335
- <Form.Label>{t("Design:zone")}</Form.Label>
336
- <Controller
337
- control={control}
338
- name={`${fieldNamePrefix}.zoneId`}
339
- render={({ field }) => (
340
- <Form.Control
341
- as="select"
342
- disabled={isOverride}
343
- isInvalid={HookFormService.isInvalid<ProductSetFormValues>(
344
- `${fieldNamePrefix}.zoneId`,
333
+ {isZoneCategory && (
334
+ <>
335
+ <Row>
336
+ <Col md={6} sm={6} xs={6}>
337
+ <Form.Group controlId={overallCapacityId}>
338
+ <Form.Label>{t("Design:overallQuantity")}</Form.Label>
339
+ <InputGroup hasValidation>
340
+ <InputGroup.Prepend
341
+ className="arrow-up-btn"
342
+ onClick={() => {
343
+ const currentOverallCapacity = Number(
344
+ getValues(`${fieldNamePrefix}.overallQuantity`) || 0
345
+ );
346
+ setValue(
347
+ `${fieldNamePrefix}.overallQuantity`,
348
+ currentOverallCapacity + 1,
349
+ { shouldValidate: true }
350
+ );
351
+ }}
352
+ >
353
+ <InputGroup.Text className="py-0 px-3">
354
+ <IncrementIcon />
355
+ </InputGroup.Text>
356
+ </InputGroup.Prepend>
357
+ <Controller
358
+ control={control}
359
+ name={`${fieldNamePrefix}.overallQuantity`}
360
+ render={({ field }) => (
361
+ <Form.Control
362
+ min={0}
363
+ step={1}
364
+ type="number"
365
+ disabled={isOverride}
366
+ isInvalid={HookFormService.isInvalid<ProductSetFormValues>(
367
+ `${fieldNamePrefix}.overallQuantity`,
368
+ errors
369
+ )}
370
+ {...field}
371
+ />
372
+ )}
373
+ rules={{
374
+ min: {
375
+ value: 0,
376
+ message: t("Validation:fieldMinNumber", {
377
+ attribute: t("overallQuantity"),
378
+ min: 0,
379
+ }) as string,
380
+ },
381
+ }}
382
+ />
383
+ <Form.Control.Feedback type="invalid">
384
+ {HookFormService.getErrors<ProductSetFormValues>(
385
+ `${fieldNamePrefix}.overallQuantity`,
345
386
  errors
346
387
  )}
347
- {...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>
356
- )}
357
- rules={{
358
- required: {
359
- value: providerHasBookingManagement,
360
- message: t("Validation:fieldRequired", {
361
- attribute: t("zone"),
362
- }),
363
- },
364
- }}
365
- />
366
- <Form.Control.Feedback type="invalid">
367
- {HookFormService.getErrors<ProductSetFormValues>(
368
- `${fieldNamePrefix}.zoneId`,
369
- errors
370
- )}
371
- </Form.Control.Feedback>
372
- </Form.Group>
373
- </Col>
374
- </Row>
388
+ </Form.Control.Feedback>
389
+ </InputGroup>
390
+ </Form.Group>
391
+ </Col>
392
+ </Row>
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
  );
@@ -57,7 +57,7 @@ function RecurrenceAndFrequencyInput({
57
57
  <Row>
58
58
  <Col xs={12} sm={6}>
59
59
  <Form.Group>
60
- <Form.Label>{startDateLabel ?? t("Design:fromDate")}</Form.Label>
60
+ <Form.Label>{startDateLabel ?? t("Design:date")}</Form.Label>
61
61
  <Form.Control
62
62
  type="date"
63
63
  {...register("startDate", { required: true })}
@@ -24,12 +24,16 @@ export interface PropertyControlProps<T> {
24
24
  item: Path<T>;
25
25
  label: string;
26
26
  isDisabled?: boolean;
27
+ defaultColors?: Array<string>;
28
+ isRequired?: boolean;
27
29
  }
28
30
 
29
31
  export function PropertyControl<T>({
30
32
  item,
31
33
  label,
32
34
  isDisabled = false,
35
+ defaultColors,
36
+ isRequired = true,
33
37
  }: PropertyControlProps<T>) {
34
38
  const { t } = useTranslation(["Validation"]);
35
39
 
@@ -62,7 +66,7 @@ export function PropertyControl<T>({
62
66
  <Form.Control
63
67
  {...register(item, {
64
68
  required: {
65
- value: true,
69
+ value: isRequired,
66
70
  message: t("Validation:fieldRequired", {
67
71
  attribute: label,
68
72
  }),
@@ -95,7 +99,7 @@ export function PropertyControl<T>({
95
99
  setValue(item, color.hex);
96
100
  toggleIsActive();
97
101
  }}
98
- colors={DEFAULT_COLORS}
102
+ colors={defaultColors || DEFAULT_COLORS}
99
103
  />
100
104
  </div>
101
105
  )}
@@ -125,6 +125,8 @@ export function SortableTreeItem({
125
125
  [position, setIsExpanded]
126
126
  );
127
127
 
128
+ const isVisibleDeleteButton = Boolean(onDelete) && !isOverride;
129
+
128
130
  const onButtonMouseDown = useCallback((event) => {
129
131
  setPosition({ pageX: event.pageX, pageY: event.pageY });
130
132
  }, []);
@@ -346,8 +348,8 @@ export function SortableTreeItem({
346
348
  >
347
349
  {t("saveAndAdd")}
348
350
  </Button>
349
- <div className="d-flex justify-content-end mt-4 delete-btn">
350
- {Boolean(onDelete) && (
351
+ {isVisibleDeleteButton && (
352
+ <div className="d-flex justify-content-end mt-4 delete-btn">
351
353
  <ConfirmModal>
352
354
  {(confirm) => (
353
355
  <DeleteFieldButton
@@ -355,8 +357,8 @@ export function SortableTreeItem({
355
357
  />
356
358
  )}
357
359
  </ConfirmModal>
358
- )}
359
- </div>
360
+ </div>
361
+ )}
360
362
  </div>
361
363
  </Modal.Body>
362
364
  </Modal>