@licklist/design 0.50.1-dev.9 → 0.51.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.
- package/dist/assets/dashboard/addImage.svg.js +1 -1
- package/dist/assets/dashboard/chartBar.svg.js +1 -1
- package/dist/assets/dashboard/genderFemale.svg.js +1 -1
- package/dist/assets/dashboard/genderMale.svg.js +1 -1
- package/dist/assets/dashboard/increment.svg.js +1 -1
- package/dist/assets/dashboard/info.svg.js +1 -1
- package/dist/assets/dashboard/managerRole.svg.js +1 -1
- package/dist/assets/dashboard/subManagerRole.svg.js +1 -1
- package/dist/assets/dashboard/viewerRole.svg.js +1 -1
- package/dist/assets/dashboard/visitedProviderLink.svg.js +1 -1
- package/dist/assets/dashboard/warning.svg.js +1 -1
- package/dist/assets/editor/bold.svg.js +1 -1
- package/dist/assets/editor/double-quotes-l.svg.js +1 -1
- package/dist/assets/editor/format-clear.svg.js +1 -1
- package/dist/assets/editor/h1.svg.js +1 -1
- package/dist/assets/editor/h2.svg.js +1 -1
- package/dist/assets/editor/italic.svg.js +1 -1
- package/dist/assets/editor/paragraph.svg.js +1 -1
- package/dist/assets/editor/separator.svg.js +1 -1
- package/dist/assets/editor/strikethrough.svg.js +1 -1
- package/dist/assets/editor/text-wrap.svg.js +1 -1
- package/dist/assets/iframe/available.svg.js +1 -1
- package/dist/assets/iframe/calendar.svg.js +1 -1
- package/dist/assets/iframe/clock.svg.js +1 -1
- package/dist/assets/iframe/close.svg.js +1 -1
- package/dist/assets/iframe/limited.svg.js +1 -1
- package/dist/assets/iframe/selectArrow.svg.js +1 -1
- package/dist/assets/iframe/soldOut.svg.js +1 -1
- package/dist/assets/iframe/success.svg.js +1 -1
- package/dist/assets/iframe/ticket.svg.js +1 -1
- package/dist/assets/logo/bookedit.svg.js +1 -1
- package/dist/assets/logo/licklist.sm.svg.js +1 -1
- package/dist/assets/logo/licklist.svg.js +1 -1
- package/dist/calendar/Calendar.d.ts +0 -3
- package/dist/calendar/Calendar.d.ts.map +1 -1
- package/dist/calendar/components/CalendarButtons/CalendarButtons.js +1 -1
- package/dist/calendar/components/CalendarDates/CalendarDates.d.ts +1 -1
- package/dist/calendar/components/CalendarDates/CalendarDates.d.ts.map +1 -1
- package/dist/calendar/components/CalendarDates/CalendarDates.js +1 -1
- package/dist/calendar/utils/index.d.ts +1 -2
- package/dist/calendar/utils/index.d.ts.map +1 -1
- package/dist/calendar/utils/index.js +1 -1
- package/dist/date-time-button/DateTimeButton.d.ts +2 -3
- package/dist/date-time-button/DateTimeButton.d.ts.map +1 -1
- package/dist/date-time-button/DateTimeButton.js +1 -1
- package/dist/events/edit-event-modal/IntervalInput.d.ts.map +1 -1
- package/dist/events/edit-event-modal/IntervalInput.js +1 -1
- package/dist/events/event-card/EventCard.d.ts +1 -2
- package/dist/events/event-card/EventCard.d.ts.map +1 -1
- package/dist/events/event-card/EventCard.js +1 -1
- package/dist/events/event-venue-map/components/Scrollbars/Scrollbars.js +1 -1
- package/dist/iframe/event/event-booking-products/EventBookingProducts.js +1 -1
- package/dist/iframe/event/event-booking-products/components/AccordionItem/AccordionItem.d.ts +2 -2
- package/dist/iframe/event/event-booking-products/components/AccordionItem/AccordionItem.d.ts.map +1 -1
- package/dist/iframe/event/event-booking-products/components/AccordionItem/AccordionItem.js +1 -1
- package/dist/iframe/event/event-card/IframeEventCard.d.ts +1 -2
- package/dist/iframe/event/event-card/IframeEventCard.d.ts.map +1 -1
- package/dist/iframe/event/event-card/IframeEventCard.js +1 -1
- package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts +1 -1
- package/dist/iframe/order-process/components/BookingSummary/BookingSummary.d.ts.map +1 -1
- package/dist/iframe/order-process/components/BookingSummary/BookingSummary.js +1 -1
- package/dist/iframe/order-process/components/BookingSummary/components/ProductSummary/ProductSummary.d.ts +1 -2
- package/dist/iframe/order-process/components/BookingSummary/components/ProductSummary/ProductSummary.d.ts.map +1 -1
- package/dist/iframe/order-process/components/BookingSummary/components/ProductSummary/ProductSummary.js +1 -1
- package/dist/iframe/order-process/components/BookingSummary/components/ProductsByMenuStep/ProductsByMenuStep.d.ts +1 -2
- package/dist/iframe/order-process/components/BookingSummary/components/ProductsByMenuStep/ProductsByMenuStep.d.ts.map +1 -1
- package/dist/iframe/order-process/components/BookingSummary/components/ProductsByMenuStep/ProductsByMenuStep.js +1 -1
- package/dist/iframe/order-process/components/BookingSummary/components/ToggleHeader/ToggleHeader.js +1 -1
- package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts +0 -1
- package/dist/iframe/order-process/components/BookingSummary/types/index.d.ts.map +1 -1
- package/dist/iframe/order-process/components/BookingSummary/utils/index.d.ts.map +1 -1
- package/dist/iframe/order-process/components/BookingSummary/utils/index.js +1 -1
- package/dist/iframe/order-process/components/CategoryProduct/CategoryProduct.d.ts.map +1 -1
- package/dist/iframe/order-process/components/CategoryProduct/CategoryProduct.js +1 -1
- package/dist/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.js +1 -1
- package/dist/iframe/order-process/components/CategoryProduct/components/ProductQuantityInput/ProductQuantityInput.d.ts +2 -3
- package/dist/iframe/order-process/components/CategoryProduct/components/ProductQuantityInput/ProductQuantityInput.d.ts.map +1 -1
- package/dist/iframe/order-process/components/CategoryProduct/components/ProductQuantityInput/ProductQuantityInput.js +1 -1
- package/dist/iframe/order-process/components/utils/useCategoryVerification.js +1 -1
- package/dist/index.js +1 -1
- package/dist/notification/email-template/control/EmailTemplateControl.d.ts.map +1 -1
- package/dist/notification/email-template/control/EmailTemplateControl.js +1 -1
- package/dist/sales/booking/results/components/ResultCard.d.ts.map +1 -1
- package/dist/sales/booking/results/components/ResultCard.js +1 -1
- package/dist/sales/manual-booking/select-event/SelectEvent.d.ts.map +1 -1
- package/dist/sales/manual-booking/select-event/SelectEvent.js +1 -1
- package/dist/sales/manual-booking/summary/ManualBookingSummary.d.ts +1 -2
- package/dist/sales/manual-booking/summary/ManualBookingSummary.d.ts.map +1 -1
- package/dist/sales/manual-booking/summary/ManualBookingSummary.js +1 -1
- package/dist/static/date-range-input/DateRangeInput.d.ts.map +1 -1
- package/dist/static/date-range-input/DateRangeInput.js +1 -1
- package/dist/styles/affiliate/AffiliateCard.scss +6 -26
- package/dist/styles/events/EventCard.scss +6 -3
- package/dist/styles/product-set/ProductSetCard.scss +0 -4
- package/dist/styles/resources-blocking/_index.scss +0 -6
- package/dist/styles/sales/BookingFilter.scss +0 -18
- package/dist/styles/sales/BookingResults.scss +1 -1
- package/dist/styles/sales/BookingTabs.scss +5 -63
- package/dist/styles/sales/LifeTimeSales.scss +0 -1
- package/dist/styles/sales/ManualBooking.scss +3 -62
- package/dist/styles/sales/SourceOfSales.scss +0 -3
- package/dist/styles/snippet-templates/SnippetTemplateCard.scss +2 -3
- package/dist/styles/static/Tabs.scss +0 -6
- package/dist/styles/themes/bookedit/_index.scss +8 -9
- package/dist/table/TableHelperComponent.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/calendar/Calendar.tsx +0 -5
- package/src/calendar/components/CalendarButtons/CalendarButtons.tsx +3 -3
- package/src/calendar/components/CalendarDates/CalendarDates.tsx +2 -5
- package/src/calendar/utils/index.ts +6 -15
- package/src/date-time-button/DateTimeButton.tsx +3 -16
- package/src/events/edit-event-modal/IntervalInput.tsx +80 -8
- package/src/events/event-card/EventCard.stories.tsx +0 -1
- package/src/events/event-card/EventCard.tsx +2 -27
- package/src/iframe/event/event-booking-products/EventBookingProducts.tsx +1 -1
- package/src/iframe/event/event-booking-products/components/AccordionItem/AccordionItem.tsx +8 -8
- package/src/iframe/event/event-card/IframeEventCard.tsx +1 -3
- package/src/iframe/order-process/components/BookingSummary/BookingSummary.stories.tsx +5 -5
- package/src/iframe/order-process/components/BookingSummary/BookingSummary.tsx +0 -2
- package/src/iframe/order-process/components/BookingSummary/components/ProductSummary/ProductSummary.tsx +6 -12
- package/src/iframe/order-process/components/BookingSummary/components/ProductsByMenuStep/ProductsByMenuStep.tsx +2 -5
- package/src/iframe/order-process/components/BookingSummary/types/index.ts +0 -1
- package/src/iframe/order-process/components/BookingSummary/utils/index.ts +4 -2
- package/src/iframe/order-process/components/CategoryProduct/CategoryProduct.tsx +23 -13
- package/src/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.tsx +1 -1
- package/src/iframe/order-process/components/CategoryProduct/components/ProductQuantityInput/ProductQuantityInput.tsx +5 -11
- package/src/iframe/order-process/components/utils/useCategoryVerification.ts +1 -1
- package/src/iframe/payment/payment-page/PaymentPage.stories.tsx +1 -1
- package/src/notification/email-template/control/EmailTemplateControl.tsx +15 -5
- package/src/sales/booking/results/components/ResultCard.tsx +4 -6
- package/src/sales/manual-booking/select-event/SelectEvent.tsx +1 -4
- package/src/sales/manual-booking/summary/ManualBookingSummary.tsx +1 -9
- package/src/static/date-range-input/DateRangeInput.tsx +2 -23
- package/src/static/switch/BooleanSwitch.tsx +1 -1
- package/src/styles/affiliate/AffiliateCard.scss +6 -26
- package/src/styles/events/EventCard.scss +6 -3
- package/src/styles/product-set/ProductSetCard.scss +0 -4
- package/src/styles/resources-blocking/_index.scss +0 -6
- package/src/styles/sales/BookingFilter.scss +0 -18
- package/src/styles/sales/BookingResults.scss +1 -1
- package/src/styles/sales/BookingTabs.scss +5 -63
- package/src/styles/sales/LifeTimeSales.scss +0 -1
- package/src/styles/sales/ManualBooking.scss +3 -62
- package/src/styles/sales/SourceOfSales.scss +0 -3
- package/src/styles/snippet-templates/SnippetTemplateCard.scss +2 -3
- package/src/styles/static/Tabs.scss +0 -6
- package/src/styles/themes/bookedit/_index.scss +8 -9
- package/src/table/TableHelperComponent.tsx +13 -11
- package/dist/events/edit-event-modal/hooks/index.d.ts +0 -3
- package/dist/events/edit-event-modal/hooks/index.d.ts.map +0 -1
- package/dist/events/edit-event-modal/hooks/useFormattedDuration.d.ts +0 -2
- package/dist/events/edit-event-modal/hooks/useFormattedDuration.d.ts.map +0 -1
- package/dist/events/edit-event-modal/hooks/useFormattedDuration.js +0 -1
- package/dist/events/edit-event-modal/hooks/useValidationOptions.d.ts +0 -11
- package/dist/events/edit-event-modal/hooks/useValidationOptions.d.ts.map +0 -1
- package/dist/events/edit-event-modal/hooks/useValidationOptions.js +0 -1
- package/src/events/edit-event-modal/hooks/index.ts +0 -2
- package/src/events/edit-event-modal/hooks/useFormattedDuration.tsx +0 -40
- package/src/events/edit-event-modal/hooks/useValidationOptions.tsx +0 -36
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
import { DateTime, Interval } from "luxon";
|
|
2
2
|
import isEqual from "lodash/isEqual";
|
|
3
|
-
import { DATE_FORMAT } from "@licklist/core/dist/Config";
|
|
4
|
-
import { AvailableTimes } from "../Calendar";
|
|
5
3
|
|
|
6
|
-
export const
|
|
7
|
-
|
|
8
|
-
disabledDates: DateTime[] = []
|
|
9
|
-
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
isEqual(disabledDate.toObject(), date.toObject())
|
|
4
|
+
export const isSelectedDateDisabled = (
|
|
5
|
+
selectedDate: DateTime,
|
|
6
|
+
disabledDates: DateTime[] = []
|
|
7
|
+
) => {
|
|
8
|
+
return !!disabledDates.find((disabledDate) =>
|
|
9
|
+
isEqual(disabledDate.toObject(), selectedDate.toObject())
|
|
13
10
|
);
|
|
14
|
-
|
|
15
|
-
const noAvailableTimes = availableTimes
|
|
16
|
-
? !availableTimes?.[date.toFormat(DATE_FORMAT)]
|
|
17
|
-
: false;
|
|
18
|
-
|
|
19
|
-
return disabledByDates || noAvailableTimes;
|
|
20
11
|
};
|
|
21
12
|
|
|
22
13
|
export const getMonthCalendarDates = (initialDate: DateTime): DateTime[] => {
|
|
@@ -2,7 +2,6 @@ import React, { ReactElement } from "react";
|
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { DateTime } from "luxon";
|
|
4
4
|
import { ZoneResourcesAvailability } from "@licklist/core/dist/DataMapper/Order/ZoneResourcesAvailabilityDataMapper";
|
|
5
|
-
import { has } from "lodash";
|
|
6
5
|
import { AvailabilityIndicator } from "../availability-indicator";
|
|
7
6
|
import { DateContent } from "./DateContent";
|
|
8
7
|
|
|
@@ -19,9 +18,8 @@ export type DateTimeButtonProps = {
|
|
|
19
18
|
isSoldOut?: boolean;
|
|
20
19
|
onSelect: (date: DateTime) => void;
|
|
21
20
|
price?: string | number | ReactElement | null;
|
|
22
|
-
resources
|
|
21
|
+
resources?: ZoneResourcesAvailability | null;
|
|
23
22
|
showResources?: boolean;
|
|
24
|
-
shouldCalculateResources?: boolean;
|
|
25
23
|
variant: Variant;
|
|
26
24
|
};
|
|
27
25
|
|
|
@@ -34,28 +32,17 @@ export const DateTimeButton = ({
|
|
|
34
32
|
price,
|
|
35
33
|
resources,
|
|
36
34
|
showResources,
|
|
37
|
-
shouldCalculateResources = true,
|
|
38
35
|
variant = Variant.week,
|
|
39
36
|
}: DateTimeButtonProps) => {
|
|
40
37
|
const isSoldOut =
|
|
41
38
|
_isSoldOut ||
|
|
42
|
-
|
|
43
|
-
(shouldCalculateResources &&
|
|
44
|
-
resources &&
|
|
45
|
-
resources.bookedResources >= resources.totalResources);
|
|
39
|
+
(resources && resources.bookedResources >= resources.totalResources);
|
|
46
40
|
|
|
47
41
|
const isTimeVariant = variant === Variant.time;
|
|
48
42
|
|
|
49
43
|
const isTimeInPast = isTimeVariant && isDateInPast(date);
|
|
50
44
|
|
|
51
|
-
const
|
|
52
|
-
shouldCalculateResources &&
|
|
53
|
-
// only consider resources if shouldCalculateResources is true
|
|
54
|
-
(!resources ||
|
|
55
|
-
!has(resources, "bookedResources") ||
|
|
56
|
-
!has(resources, "totalResources"));
|
|
57
|
-
|
|
58
|
-
const isDisabled = _isDisabled || isSoldOut || isTimeInPast || noResources;
|
|
45
|
+
const isDisabled = _isDisabled || isSoldOut || isTimeInPast;
|
|
59
46
|
|
|
60
47
|
return (
|
|
61
48
|
<button
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from "react";
|
|
2
|
-
import { DateTime } from "luxon";
|
|
1
|
+
import React, { useMemo, useState, useRef, useEffect } from "react";
|
|
2
|
+
import { DateTime, Interval } from "luxon";
|
|
3
3
|
import { Col, Form } from "react-bootstrap";
|
|
4
|
-
import { Controller,
|
|
4
|
+
import { Controller, RegisterOptions, useFormContext } from "react-hook-form";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
|
+
import { useIntl } from "react-intl";
|
|
6
7
|
|
|
7
8
|
import { useId } from "@react-aria/utils";
|
|
8
9
|
import { ProductSet } from "@licklist/core/dist/DataMapper/Product/ProductSetDataMapper";
|
|
@@ -10,7 +11,6 @@ import HTMLInputDateElement from "../../types/static/HTMLInputDateElement";
|
|
|
10
11
|
import { RecurrenceInput } from "../../recurrence-input";
|
|
11
12
|
import { WarningMessage } from "../../static";
|
|
12
13
|
import { ProductSetFormValues } from "../../product-set/form";
|
|
13
|
-
import { useFormattedDuration, useValidationOptions } from "./hooks";
|
|
14
14
|
|
|
15
15
|
interface IntervalInputProps {
|
|
16
16
|
editedProductSet?: ProductSetFormValues;
|
|
@@ -35,6 +35,7 @@ export function IntervalInput({
|
|
|
35
35
|
const {
|
|
36
36
|
register,
|
|
37
37
|
formState: { errors },
|
|
38
|
+
watch,
|
|
38
39
|
control,
|
|
39
40
|
trigger,
|
|
40
41
|
setValue,
|
|
@@ -43,9 +44,9 @@ export function IntervalInput({
|
|
|
43
44
|
const formattedDuration = useFormattedDuration();
|
|
44
45
|
const validationOptions = useValidationOptions();
|
|
45
46
|
|
|
46
|
-
const rrule =
|
|
47
|
-
const start =
|
|
48
|
-
const end =
|
|
47
|
+
const rrule = watch("rrule");
|
|
48
|
+
const start = watch("start");
|
|
49
|
+
const end = watch("end");
|
|
49
50
|
const [recurrent, setRecurrent] = useState(Boolean(rrule));
|
|
50
51
|
const [isOverriden, setIsOverriden] = useState(false);
|
|
51
52
|
const recurrentId = useId();
|
|
@@ -122,7 +123,6 @@ export function IntervalInput({
|
|
|
122
123
|
onChangeEndDate(nextEndtDate)
|
|
123
124
|
}
|
|
124
125
|
min={start}
|
|
125
|
-
required
|
|
126
126
|
isInvalid={Boolean(errors.end)}
|
|
127
127
|
onClick={() => endDateInput?.current?.showPicker()}
|
|
128
128
|
ref={endDateInput}
|
|
@@ -180,3 +180,75 @@ export function IntervalInput({
|
|
|
180
180
|
</>
|
|
181
181
|
);
|
|
182
182
|
}
|
|
183
|
+
|
|
184
|
+
const useFormattedDuration = () => {
|
|
185
|
+
const { watch } = useFormContext<IntervalInputValues>();
|
|
186
|
+
const start = watch("start");
|
|
187
|
+
const end = watch("end");
|
|
188
|
+
const { formatList, formatNumber } = useIntl();
|
|
189
|
+
|
|
190
|
+
return useMemo(() => {
|
|
191
|
+
const interval = Interval.fromDateTimes(
|
|
192
|
+
DateTime.fromISO(start),
|
|
193
|
+
DateTime.fromISO(end)
|
|
194
|
+
).toDuration(["days", "hours", "minutes"]);
|
|
195
|
+
|
|
196
|
+
if (!interval.isValid) return undefined;
|
|
197
|
+
|
|
198
|
+
const formatUnit = (value: number, unit: string) =>
|
|
199
|
+
formatNumber(value, { style: "unit", unit, unitDisplay: "long" });
|
|
200
|
+
|
|
201
|
+
const units = (
|
|
202
|
+
[
|
|
203
|
+
[interval.days, "day"],
|
|
204
|
+
[interval.hours, "hour"],
|
|
205
|
+
[interval.minutes, "minute"],
|
|
206
|
+
] as Parameters<typeof formatUnit>[]
|
|
207
|
+
).filter(([value]) => value);
|
|
208
|
+
|
|
209
|
+
return formatList(
|
|
210
|
+
units.map((args) => formatUnit(...args)),
|
|
211
|
+
{ style: "long", type: "unit" }
|
|
212
|
+
);
|
|
213
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
214
|
+
}, [start, end]);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const useValidationOptions = () => {
|
|
218
|
+
const { watch } = useFormContext();
|
|
219
|
+
const { t } = useTranslation(["Design", "Validation"]);
|
|
220
|
+
const start = watch("start");
|
|
221
|
+
const end = watch("end");
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
start: useMemo<RegisterOptions>(
|
|
225
|
+
() => ({
|
|
226
|
+
required: t("Validation:fieldRequired", {
|
|
227
|
+
attribute: t("start"),
|
|
228
|
+
}) as string,
|
|
229
|
+
// TODO: uncomment when event splitting is implemented
|
|
230
|
+
// and extract into plugins
|
|
231
|
+
validate: (value) =>
|
|
232
|
+
DateTime.fromISO(value).diffNow().toMillis() > 0 ||
|
|
233
|
+
(t("Validation:fieldValidEventStart") as string),
|
|
234
|
+
}),
|
|
235
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
236
|
+
[]
|
|
237
|
+
),
|
|
238
|
+
|
|
239
|
+
end: useMemo<RegisterOptions>(
|
|
240
|
+
() => ({
|
|
241
|
+
// TODO: uncomment when event splitting is implemented
|
|
242
|
+
// and extract into plugins
|
|
243
|
+
validate: (value) =>
|
|
244
|
+
// endAt not required
|
|
245
|
+
value
|
|
246
|
+
? DateTime.fromISO(value).diff(DateTime.fromISO(start)).toMillis() >
|
|
247
|
+
0 || (t("Validation:fieldValidEventEnd") as string)
|
|
248
|
+
: true,
|
|
249
|
+
}),
|
|
250
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
251
|
+
[start, end]
|
|
252
|
+
),
|
|
253
|
+
};
|
|
254
|
+
};
|
|
@@ -33,7 +33,6 @@ export const Default: Story<EventCardProps> = () => {
|
|
|
33
33
|
RuPaul's Drag Race UK to VINYL Cambridge! So get excited because
|
|
34
34
|
the...`}
|
|
35
35
|
date="2023-08-31T09:35:00.000+03:00"
|
|
36
|
-
productSetName="New product set"
|
|
37
36
|
imageUrl={showImage ? `https://source.unsplash.com/random` : null}
|
|
38
37
|
hasPermission={hasPermission}
|
|
39
38
|
onPreview={() => undefined}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
|
-
import {
|
|
3
|
-
Badge,
|
|
4
|
-
Card,
|
|
5
|
-
OverlayTrigger,
|
|
6
|
-
Popover,
|
|
7
|
-
ProgressBar,
|
|
8
|
-
} from "react-bootstrap";
|
|
2
|
+
import { Badge, Card, ProgressBar } from "react-bootstrap";
|
|
9
3
|
import { useIntl } from "react-intl";
|
|
10
4
|
import clsx from "clsx";
|
|
11
5
|
import { useTranslation } from "react-i18next";
|
|
@@ -36,7 +30,6 @@ export interface EventCardProps extends HasPermissionProp {
|
|
|
36
30
|
onStatistic: () => void;
|
|
37
31
|
titleId?: string;
|
|
38
32
|
descriptionId?: string;
|
|
39
|
-
productSetName?: string;
|
|
40
33
|
}
|
|
41
34
|
|
|
42
35
|
export function EventCard({
|
|
@@ -50,7 +43,6 @@ export function EventCard({
|
|
|
50
43
|
onCopy,
|
|
51
44
|
onRemove,
|
|
52
45
|
hasPermission = true,
|
|
53
|
-
productSetName,
|
|
54
46
|
onStatistic,
|
|
55
47
|
eventStatistic,
|
|
56
48
|
titleId,
|
|
@@ -131,24 +123,7 @@ export function EventCard({
|
|
|
131
123
|
))}
|
|
132
124
|
</div>
|
|
133
125
|
</Card.Body>
|
|
134
|
-
<Card.Footer
|
|
135
|
-
{productSetName && (
|
|
136
|
-
<OverlayTrigger
|
|
137
|
-
// Workaround for bootstrap error with "hover trigger"
|
|
138
|
-
trigger={["hover", "hover"]}
|
|
139
|
-
overlay={
|
|
140
|
-
<Popover id="event-product-set-popover">
|
|
141
|
-
<Popover.Content className="event-product-set-card">
|
|
142
|
-
{productSetName}
|
|
143
|
-
</Popover.Content>
|
|
144
|
-
</Popover>
|
|
145
|
-
}
|
|
146
|
-
>
|
|
147
|
-
<div className="pl-3 text-truncate">
|
|
148
|
-
{t("Design:productSet")}: {productSetName}
|
|
149
|
-
</div>
|
|
150
|
-
</OverlayTrigger>
|
|
151
|
-
)}
|
|
126
|
+
<Card.Footer>
|
|
152
127
|
<div className="d-flex w-100 justify-content-between">
|
|
153
128
|
<div className="d-flex">
|
|
154
129
|
<button
|
|
@@ -27,7 +27,7 @@ export function EventBookingProducts({
|
|
|
27
27
|
<AccordionItem
|
|
28
28
|
key={productsCategory.id}
|
|
29
29
|
eventKey={`${productsCategory.id}`}
|
|
30
|
-
|
|
30
|
+
productsCategoryId={productsCategory.id}
|
|
31
31
|
name={productsCategory.name}
|
|
32
32
|
products={productsCategory.products}
|
|
33
33
|
order={order}
|
|
@@ -24,7 +24,7 @@ interface AccordionItemProps {
|
|
|
24
24
|
products: Product[];
|
|
25
25
|
setOrder: SetOrderFn;
|
|
26
26
|
order: Record<number, OrderItem>;
|
|
27
|
-
|
|
27
|
+
productsCategoryId: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function CustomToggle({
|
|
@@ -60,7 +60,7 @@ export function AccordionItem({
|
|
|
60
60
|
order,
|
|
61
61
|
setOrder,
|
|
62
62
|
products,
|
|
63
|
-
|
|
63
|
+
productsCategoryId,
|
|
64
64
|
}: AccordionItemProps) {
|
|
65
65
|
return (
|
|
66
66
|
<Card className="event-booking-products__card">
|
|
@@ -71,7 +71,7 @@ export function AccordionItem({
|
|
|
71
71
|
<ProductItem
|
|
72
72
|
key={product.id}
|
|
73
73
|
id={product.id}
|
|
74
|
-
|
|
74
|
+
productsCategoryId={productsCategoryId}
|
|
75
75
|
price={product.price}
|
|
76
76
|
name={product.name}
|
|
77
77
|
description={product.description}
|
|
@@ -92,7 +92,7 @@ interface ProductItemProps {
|
|
|
92
92
|
description: string;
|
|
93
93
|
order: OrderItems;
|
|
94
94
|
setOrder: SetOrderFn;
|
|
95
|
-
|
|
95
|
+
productsCategoryId: number;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function ProductItem({
|
|
@@ -102,7 +102,7 @@ function ProductItem({
|
|
|
102
102
|
description,
|
|
103
103
|
order,
|
|
104
104
|
setOrder,
|
|
105
|
-
|
|
105
|
+
productsCategoryId,
|
|
106
106
|
}: ProductItemProps) {
|
|
107
107
|
const { formatNumber } = useIntl();
|
|
108
108
|
|
|
@@ -120,7 +120,7 @@ function ProductItem({
|
|
|
120
120
|
quantity: val,
|
|
121
121
|
name,
|
|
122
122
|
price,
|
|
123
|
-
|
|
123
|
+
productsCategoryId,
|
|
124
124
|
},
|
|
125
125
|
}));
|
|
126
126
|
}}
|
|
@@ -132,7 +132,7 @@ function ProductItem({
|
|
|
132
132
|
quantity: prev[id]?.quantity - 1 || 0,
|
|
133
133
|
name,
|
|
134
134
|
price,
|
|
135
|
-
|
|
135
|
+
productsCategoryId,
|
|
136
136
|
},
|
|
137
137
|
}))
|
|
138
138
|
}
|
|
@@ -144,7 +144,7 @@ function ProductItem({
|
|
|
144
144
|
quantity: prev[id]?.quantity + 1 || 1,
|
|
145
145
|
name,
|
|
146
146
|
price,
|
|
147
|
-
|
|
147
|
+
productsCategoryId,
|
|
148
148
|
},
|
|
149
149
|
}))
|
|
150
150
|
}
|
|
@@ -28,7 +28,6 @@ interface IframeEventCardProps {
|
|
|
28
28
|
shortDate: string;
|
|
29
29
|
titleId?: string;
|
|
30
30
|
descriptionId?: string;
|
|
31
|
-
imageClassName?: string;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export function IframeEventCard({
|
|
@@ -45,7 +44,6 @@ export function IframeEventCard({
|
|
|
45
44
|
shortDate,
|
|
46
45
|
titleId,
|
|
47
46
|
descriptionId,
|
|
48
|
-
imageClassName,
|
|
49
47
|
}: IframeEventCardProps) {
|
|
50
48
|
const { formatNumber } = useIntl();
|
|
51
49
|
const { t } = useTranslation("Design");
|
|
@@ -72,7 +70,7 @@ export function IframeEventCard({
|
|
|
72
70
|
>
|
|
73
71
|
{imageSrc && (
|
|
74
72
|
<Card.Img
|
|
75
|
-
className=
|
|
73
|
+
className="card-image"
|
|
76
74
|
variant="top"
|
|
77
75
|
as="div"
|
|
78
76
|
style={{ backgroundImage: `url("${imageSrc}")` }}
|
|
@@ -147,35 +147,35 @@ export function Default() {
|
|
|
147
147
|
quantity: 1,
|
|
148
148
|
name: "cat 1 prod 1",
|
|
149
149
|
price: 0,
|
|
150
|
-
|
|
150
|
+
productsCategoryId: 1,
|
|
151
151
|
},
|
|
152
152
|
"21": {
|
|
153
153
|
id: 21,
|
|
154
154
|
quantity: 2,
|
|
155
155
|
name: "cat 2 prod 1",
|
|
156
156
|
price: 1,
|
|
157
|
-
|
|
157
|
+
productsCategoryId: 2,
|
|
158
158
|
},
|
|
159
159
|
"31": {
|
|
160
160
|
id: 31,
|
|
161
161
|
quantity: 4,
|
|
162
162
|
name: "cat 3 prod 1",
|
|
163
163
|
price: 1,
|
|
164
|
-
|
|
164
|
+
productsCategoryId: 3,
|
|
165
165
|
},
|
|
166
166
|
"32": {
|
|
167
167
|
id: 32,
|
|
168
168
|
quantity: 4,
|
|
169
169
|
name: "cat 3 prod 2",
|
|
170
170
|
price: 1,
|
|
171
|
-
|
|
171
|
+
productsCategoryId: 3,
|
|
172
172
|
},
|
|
173
173
|
"41": {
|
|
174
174
|
id: 41,
|
|
175
175
|
quantity: 4,
|
|
176
176
|
name: "cat 4 prod 1",
|
|
177
177
|
price: 1,
|
|
178
|
-
|
|
178
|
+
productsCategoryId: 4,
|
|
179
179
|
},
|
|
180
180
|
}}
|
|
181
181
|
totalWithDiscount={5}
|
|
@@ -20,7 +20,6 @@ export const BookingSummary = ({
|
|
|
20
20
|
productsWithErrors = [],
|
|
21
21
|
isLoading,
|
|
22
22
|
hasPeopleInput,
|
|
23
|
-
isPaymentLink,
|
|
24
23
|
peopleAmount,
|
|
25
24
|
}: Omit<BookingSummaryProps, "totallWithDiscount">) => {
|
|
26
25
|
const { t } = useTranslation("Design");
|
|
@@ -50,7 +49,6 @@ export const BookingSummary = ({
|
|
|
50
49
|
<div className="products-by-menu-step">
|
|
51
50
|
{menuSteps.map((menuStep) => (
|
|
52
51
|
<ProductsByMenuStep
|
|
53
|
-
isPaymentLink={isPaymentLink}
|
|
54
52
|
key={menuStep.id}
|
|
55
53
|
orderItems={formValues}
|
|
56
54
|
step={menuStep}
|
|
@@ -8,27 +8,21 @@ type ProductSummaryProps = {
|
|
|
8
8
|
name?: string;
|
|
9
9
|
productQuantityError?: string;
|
|
10
10
|
orderProduct: OrderItem;
|
|
11
|
-
isPaymentLink?: boolean;
|
|
12
11
|
};
|
|
13
12
|
|
|
14
13
|
export const ProductSummary = ({
|
|
15
14
|
name,
|
|
16
15
|
productQuantityError,
|
|
17
16
|
orderProduct,
|
|
18
|
-
isPaymentLink,
|
|
19
17
|
}: ProductSummaryProps) => {
|
|
20
18
|
const { t } = useTranslation("Design");
|
|
21
19
|
const { formatNumber } = useIntl();
|
|
22
20
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const fullPrice = formatNumber(priceForOneProduct * orderProduct?.quantity, {
|
|
29
|
-
style: "currency",
|
|
30
|
-
currency: Config.Currency.GBP,
|
|
31
|
-
});
|
|
21
|
+
const price = formatNumber(
|
|
22
|
+
(orderProduct?.deposit || orderProduct?.price || 0) *
|
|
23
|
+
orderProduct?.quantity,
|
|
24
|
+
{ style: "currency", currency: Config.Currency.GBP }
|
|
25
|
+
);
|
|
32
26
|
|
|
33
27
|
return (
|
|
34
28
|
<div className="product">
|
|
@@ -38,7 +32,7 @@ export const ProductSummary = ({
|
|
|
38
32
|
{t("shortQuantity")}: {orderProduct?.quantity}
|
|
39
33
|
</p>
|
|
40
34
|
|
|
41
|
-
<p className="price">{
|
|
35
|
+
<p className="price">{price}</p>
|
|
42
36
|
</div>
|
|
43
37
|
|
|
44
38
|
{productQuantityError && (
|
|
@@ -13,7 +13,7 @@ const doesStepHaveItems = (orderItems: OrderItems, step: MenuStep): boolean => {
|
|
|
13
13
|
const categoriesIds = step.productCategories.map((category) => category.id);
|
|
14
14
|
|
|
15
15
|
const stepItems = values(orderItems).filter((item) =>
|
|
16
|
-
categoriesIds.includes(item.
|
|
16
|
+
categoriesIds.includes(item.productsCategoryId)
|
|
17
17
|
);
|
|
18
18
|
|
|
19
19
|
return stepItems.length > 0;
|
|
@@ -23,20 +23,18 @@ const getOrderItemsForCategory = (
|
|
|
23
23
|
orderItems: OrderItems,
|
|
24
24
|
categoryId: number
|
|
25
25
|
): OrderItem[] =>
|
|
26
|
-
values(orderItems).filter((item) => item.
|
|
26
|
+
values(orderItems).filter((item) => item.productsCategoryId === categoryId);
|
|
27
27
|
|
|
28
28
|
export type ProductsByMenuStepsProps = {
|
|
29
29
|
orderItems: OrderItems;
|
|
30
30
|
step: MenuStep;
|
|
31
31
|
productsWithErrors?: QuantityCheckProductInfo[];
|
|
32
|
-
isPaymentLink?: boolean;
|
|
33
32
|
};
|
|
34
33
|
|
|
35
34
|
export const ProductsByMenuStep = ({
|
|
36
35
|
orderItems,
|
|
37
36
|
step,
|
|
38
37
|
productsWithErrors = [],
|
|
39
|
-
isPaymentLink,
|
|
40
38
|
}: ProductsByMenuStepsProps) => {
|
|
41
39
|
const { productCategories } = step;
|
|
42
40
|
|
|
@@ -64,7 +62,6 @@ export const ProductsByMenuStep = ({
|
|
|
64
62
|
|
|
65
63
|
return (
|
|
66
64
|
<ProductSummary
|
|
67
|
-
isPaymentLink={isPaymentLink}
|
|
68
65
|
key={orderItem.id}
|
|
69
66
|
name={orderItem.name}
|
|
70
67
|
productQuantityError={productQuantityError}
|
|
@@ -7,8 +7,10 @@ export const cartSumByOrderProducts = (orderProducts?: OrderItem[]) => {
|
|
|
7
7
|
}
|
|
8
8
|
return orderProducts.reduce((prevSumValue: number, product) => {
|
|
9
9
|
if (!product) return 0;
|
|
10
|
-
|
|
11
|
-
return
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
prevSumValue + (product?.deposit || product?.price) * product.quantity
|
|
13
|
+
);
|
|
12
14
|
}, 0);
|
|
13
15
|
};
|
|
14
16
|
|
|
@@ -42,6 +42,18 @@ export const CategoryProduct = ({
|
|
|
42
42
|
return error?.message;
|
|
43
43
|
}, [productsWithErrors, product.id]);
|
|
44
44
|
|
|
45
|
+
const deposit = useMemo(() => {
|
|
46
|
+
if (
|
|
47
|
+
!category.allowDeposits ||
|
|
48
|
+
!product.deposit ||
|
|
49
|
+
product?.isSoldOut ||
|
|
50
|
+
product.deposit >= product.price
|
|
51
|
+
) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
return product.deposit;
|
|
55
|
+
}, [category, product]);
|
|
56
|
+
|
|
45
57
|
const checkIfSoldOutProduct = () => {
|
|
46
58
|
if (!soldOutProducts || product?.isSoldOut) {
|
|
47
59
|
return undefined;
|
|
@@ -134,13 +146,10 @@ export const CategoryProduct = ({
|
|
|
134
146
|
</div>
|
|
135
147
|
<div className="iframe-event__product-price-wrapper">
|
|
136
148
|
<span className="product-price">
|
|
137
|
-
{formatNumber(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
currency: Config.Currency.GBP,
|
|
142
|
-
}
|
|
143
|
-
)}
|
|
149
|
+
{formatNumber(deposit ?? product.price, {
|
|
150
|
+
style: "currency",
|
|
151
|
+
currency: Config.Currency.GBP,
|
|
152
|
+
})}
|
|
144
153
|
</span>
|
|
145
154
|
<ProductQuantityInput
|
|
146
155
|
onChange={onChange}
|
|
@@ -153,16 +162,17 @@ export const CategoryProduct = ({
|
|
|
153
162
|
}}
|
|
154
163
|
category={category}
|
|
155
164
|
invalid={invalid}
|
|
165
|
+
deposit={deposit}
|
|
156
166
|
/>
|
|
157
167
|
</div>
|
|
158
|
-
{
|
|
168
|
+
{deposit && !category?.remainderExpireAfter && (
|
|
159
169
|
<div className="mt-4">
|
|
160
170
|
{t("Design:payNowAndUponArrival", {
|
|
161
|
-
deposit: formatNumber(
|
|
171
|
+
deposit: formatNumber(deposit, {
|
|
162
172
|
style: "currency",
|
|
163
173
|
currency: Config.Currency.GBP,
|
|
164
174
|
}),
|
|
165
|
-
remainder: formatNumber(product.price -
|
|
175
|
+
remainder: formatNumber(product.price - deposit, {
|
|
166
176
|
style: "currency",
|
|
167
177
|
currency: Config.Currency.GBP,
|
|
168
178
|
}),
|
|
@@ -170,14 +180,14 @@ export const CategoryProduct = ({
|
|
|
170
180
|
</div>
|
|
171
181
|
)}
|
|
172
182
|
|
|
173
|
-
{
|
|
183
|
+
{deposit && category?.remainderExpireAfter > 0 && (
|
|
174
184
|
<div className="mt-4">
|
|
175
185
|
{t("Design:payNowAndReminderDays", {
|
|
176
|
-
deposit: formatNumber(
|
|
186
|
+
deposit: formatNumber(deposit, {
|
|
177
187
|
style: "currency",
|
|
178
188
|
currency: Config.Currency.GBP,
|
|
179
189
|
}),
|
|
180
|
-
remainder: formatNumber(product.price -
|
|
190
|
+
remainder: formatNumber(product.price - deposit, {
|
|
181
191
|
style: "currency",
|
|
182
192
|
currency: Config.Currency.GBP,
|
|
183
193
|
}),
|
package/src/iframe/order-process/components/CategoryProduct/components/NumberInput/NumberInput.tsx
CHANGED
|
@@ -32,7 +32,7 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
|
|
|
32
32
|
ref
|
|
33
33
|
) => {
|
|
34
34
|
const handleArrowUpClick = () => {
|
|
35
|
-
if (max !== undefined &&
|
|
35
|
+
if (max !== undefined && value < max) {
|
|
36
36
|
onArrowUp(value + 1);
|
|
37
37
|
}
|
|
38
38
|
if (max === undefined) {
|
|
@@ -14,8 +14,7 @@ interface FormOrderItem {
|
|
|
14
14
|
id: number;
|
|
15
15
|
name: string;
|
|
16
16
|
price: number;
|
|
17
|
-
|
|
18
|
-
hasDeposit?: boolean;
|
|
17
|
+
productsCategoryId: number;
|
|
19
18
|
zoneId?: Zone["id"];
|
|
20
19
|
deposit?: number | null;
|
|
21
20
|
quantity: number;
|
|
@@ -41,23 +40,19 @@ export const ProductQuantityInput = ({
|
|
|
41
40
|
refCallback,
|
|
42
41
|
productInfo,
|
|
43
42
|
invalid,
|
|
43
|
+
deposit,
|
|
44
44
|
}: ProductQuantityInputProps) => {
|
|
45
45
|
const { t } = useTranslation("Design");
|
|
46
46
|
|
|
47
47
|
const onChange = (quantity: number | null) => {
|
|
48
|
-
let productQuantity = quantity;
|
|
49
|
-
if (product?.maxAmount && quantity > product?.maxAmount) {
|
|
50
|
-
productQuantity = product?.maxAmount;
|
|
51
|
-
}
|
|
52
48
|
_onChange({
|
|
53
49
|
id: product.id,
|
|
54
50
|
name: product.name,
|
|
55
|
-
deposit
|
|
56
|
-
hasDeposit: category.allowDeposits,
|
|
51
|
+
deposit,
|
|
57
52
|
price: product.price,
|
|
58
|
-
|
|
53
|
+
productsCategoryId: category.id,
|
|
59
54
|
zoneId: category.zone?.id,
|
|
60
|
-
quantity
|
|
55
|
+
quantity,
|
|
61
56
|
capacity: product?.capacity,
|
|
62
57
|
});
|
|
63
58
|
};
|
|
@@ -104,7 +99,6 @@ export const ProductQuantityInput = ({
|
|
|
104
99
|
clearErrors(`${product.id}` as const);
|
|
105
100
|
}}
|
|
106
101
|
min={0}
|
|
107
|
-
max={product?.maxAmount ? Number(product?.maxAmount) : undefined}
|
|
108
102
|
placeholder="0"
|
|
109
103
|
disabled={product.isSoldOut}
|
|
110
104
|
value={productInfo?.quantity}
|
|
@@ -47,7 +47,7 @@ export const useCategoryVerification = () => {
|
|
|
47
47
|
if (!minSubItems && !maxSubItems) return;
|
|
48
48
|
|
|
49
49
|
const categoryProductsQuantity = productArray.filter(
|
|
50
|
-
(product) => product?.
|
|
50
|
+
(product) => product?.productsCategoryId === id
|
|
51
51
|
).length;
|
|
52
52
|
|
|
53
53
|
if (minSubItems && categoryProductsQuantity < minSubItems) {
|