willba-component-library 0.1.57 → 0.1.59
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/lib/components/FilterBar/FilterBar.d.ts +3 -2
- package/lib/components/FilterBar/FilterBarTypes.d.ts +7 -0
- package/lib/components/FilterBar/components/calendar/Calendar.d.ts +3 -0
- package/lib/components/FilterBar/hooks/useFilterBar.d.ts +3 -3
- package/lib/components/FilterBar/utils/parseGuests.d.ts +1 -1
- package/lib/index.d.ts +5 -1
- package/lib/index.esm.js +61 -28
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +61 -28
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +61 -28
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/FilterBar/FilterBar.stories.tsx +4 -0
- package/src/components/FilterBar/FilterBar.tsx +21 -8
- package/src/components/FilterBar/FilterBarTypes.ts +9 -0
- package/src/components/FilterBar/components/calendar/Calendar.tsx +17 -3
- package/src/components/FilterBar/hooks/useFilterBar.tsx +15 -11
- package/src/components/FilterBar/utils/parseGuests.tsx +32 -10
- package/src/locales/en/filterBar.json +2 -1
- package/src/locales/fi/filterBar.json +2 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Palette } from '../../themes/useTheme';
|
|
3
3
|
import '../../themes/Default.css';
|
|
4
|
-
import { AgeCategoryType, Filters } from './FilterBarTypes';
|
|
4
|
+
import { AgeCategoryType, CalendarOffset, Filters } from './FilterBarTypes';
|
|
5
5
|
import './FilterBar.css';
|
|
6
6
|
export type FilterBarProps = {
|
|
7
7
|
vendor?: string;
|
|
@@ -12,5 +12,6 @@ export type FilterBarProps = {
|
|
|
12
12
|
currentViewApply?: string;
|
|
13
13
|
onSubmit?: ((val: Filters) => void) | null;
|
|
14
14
|
fullWidth?: boolean;
|
|
15
|
+
calendarOffset: CalendarOffset;
|
|
15
16
|
};
|
|
16
|
-
export default function FilterBar({ language, ageCategories, redirectUrl, palette, currentViewApply, onSubmit, fullWidth, }: FilterBarProps): React.JSX.Element | undefined;
|
|
17
|
+
export default function FilterBar({ language, ageCategories, redirectUrl, palette, currentViewApply, onSubmit, fullWidth, calendarOffset, }: FilterBarProps): React.JSX.Element | undefined;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DateRange } from 'react-day-picker';
|
|
3
|
+
import { CalendarOffset } from '../../FilterBarTypes';
|
|
3
4
|
import 'react-day-picker/dist/style.css';
|
|
4
5
|
import './Calendar.css';
|
|
5
6
|
type Props = {
|
|
6
7
|
calendarRange: DateRange | undefined;
|
|
7
8
|
setCalendarRange: (range: DateRange | undefined) => void;
|
|
9
|
+
calendarOffset: CalendarOffset;
|
|
10
|
+
selectedPath: string;
|
|
8
11
|
};
|
|
9
12
|
export declare const Calendar: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
|
|
10
13
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { DateRange } from 'react-day-picker';
|
|
3
|
-
import { AgeCategoryCount, AgeCategoryType, Filters } from '../FilterBarTypes';
|
|
3
|
+
import { AgeCategoryCount, AgeCategoryType, Filters, Pages } from '../FilterBarTypes';
|
|
4
4
|
type Props = {
|
|
5
5
|
redirectUrl?: string;
|
|
6
6
|
currentViewApply?: string;
|
|
@@ -12,7 +12,7 @@ export declare const useFilterBar: ({ redirectUrl, currentViewApply, ageCategori
|
|
|
12
12
|
ageCategoryCounts: AgeCategoryCount;
|
|
13
13
|
categories: number;
|
|
14
14
|
calendarRange: DateRange | undefined;
|
|
15
|
-
selectedPath:
|
|
15
|
+
selectedPath: Pages;
|
|
16
16
|
setCalendarRange: import("react").Dispatch<import("react").SetStateAction<DateRange | undefined>>;
|
|
17
17
|
setSelectedFilter: import("react").Dispatch<import("react").SetStateAction<string | boolean>>;
|
|
18
18
|
setAgeCategoryCounts: import("react").Dispatch<import("react").SetStateAction<AgeCategoryCount>>;
|
|
@@ -21,6 +21,6 @@ export declare const useFilterBar: ({ redirectUrl, currentViewApply, ageCategori
|
|
|
21
21
|
handleSubmit: () => string | void;
|
|
22
22
|
updateGuestsCount: (id: string, newCount: number) => void;
|
|
23
23
|
handleResetFilters: () => void;
|
|
24
|
-
setSelectedPath: import("react").Dispatch<import("react").SetStateAction<
|
|
24
|
+
setSelectedPath: import("react").Dispatch<import("react").SetStateAction<Pages>>;
|
|
25
25
|
};
|
|
26
26
|
export {};
|
|
@@ -3,5 +3,5 @@ type Props = {
|
|
|
3
3
|
ageCategoryCounts: AgeCategoryCount;
|
|
4
4
|
ageCategories: AgeCategoryType[];
|
|
5
5
|
};
|
|
6
|
-
export declare const parseGuests: ({ ageCategoryCounts, ageCategories }: Props) => string;
|
|
6
|
+
export declare const parseGuests: ({ ageCategoryCounts, ageCategories }: Props) => string | 0;
|
|
7
7
|
export {};
|
package/lib/index.d.ts
CHANGED
|
@@ -41,6 +41,9 @@ type AgeCategoryType = {
|
|
|
41
41
|
type Filters = {
|
|
42
42
|
[key: string]: string;
|
|
43
43
|
};
|
|
44
|
+
type CalendarOffset = {
|
|
45
|
+
[key: string]: number;
|
|
46
|
+
};
|
|
44
47
|
|
|
45
48
|
type FilterBarProps = {
|
|
46
49
|
vendor?: string;
|
|
@@ -51,7 +54,8 @@ type FilterBarProps = {
|
|
|
51
54
|
currentViewApply?: string;
|
|
52
55
|
onSubmit?: ((val: Filters) => void) | null;
|
|
53
56
|
fullWidth?: boolean;
|
|
57
|
+
calendarOffset: CalendarOffset;
|
|
54
58
|
};
|
|
55
|
-
declare function FilterBar({ language, ageCategories, redirectUrl, palette, currentViewApply, onSubmit, fullWidth, }: FilterBarProps): React.JSX.Element | undefined;
|
|
59
|
+
declare function FilterBar({ language, ageCategories, redirectUrl, palette, currentViewApply, onSubmit, fullWidth, calendarOffset, }: FilterBarProps): React.JSX.Element | undefined;
|
|
56
60
|
|
|
57
61
|
export { Button, FilterBar };
|
package/lib/index.esm.js
CHANGED
|
@@ -58,6 +58,16 @@ function __read(o, n) {
|
|
|
58
58
|
return ar;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
function __spreadArray$1(to, from, pack) {
|
|
62
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
63
|
+
if (ar || !(i in from)) {
|
|
64
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
65
|
+
ar[i] = from[i];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
62
72
|
var e = new Error(message);
|
|
63
73
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
@@ -3890,14 +3900,23 @@ var parseDates = function (_a) {
|
|
|
3890
3900
|
|
|
3891
3901
|
var parseGuests = function (_a) {
|
|
3892
3902
|
var ageCategoryCounts = _a.ageCategoryCounts, ageCategories = _a.ageCategories;
|
|
3893
|
-
|
|
3903
|
+
var parsedData = Object.entries(ageCategoryCounts).reduce(function (acc, _a) {
|
|
3894
3904
|
var _b = __read(_a, 2), key = _b[0], value = _b[1];
|
|
3895
|
-
var
|
|
3905
|
+
var ageCategoryId = key[key.length - 1];
|
|
3906
|
+
var ageCategory = ageCategories.find(function (c) { return c.id === ageCategoryId; });
|
|
3896
3907
|
if (ageCategory && value) {
|
|
3897
|
-
|
|
3908
|
+
return {
|
|
3909
|
+
total: acc.total + value,
|
|
3910
|
+
html: __spreadArray$1(__spreadArray$1([], __read(acc.html), false), [
|
|
3911
|
+
"<span style=\"display: inline-block; width: 21px, text-align: center\">".concat(value, "</span>"),
|
|
3912
|
+
], false),
|
|
3913
|
+
};
|
|
3898
3914
|
}
|
|
3899
3915
|
return acc;
|
|
3900
|
-
},
|
|
3916
|
+
}, { total: 0, html: [] });
|
|
3917
|
+
var htmlString = parsedData.html.length > 1 ? parsedData.html.join(' + ') : '';
|
|
3918
|
+
return ((parsedData.total || htmlString) &&
|
|
3919
|
+
": ".concat(parsedData.total, " ").concat(htmlString ? "- ( ".concat(htmlString, " )") : ''));
|
|
3901
3920
|
};
|
|
3902
3921
|
|
|
3903
3922
|
var FilterSections;
|
|
@@ -3910,10 +3929,15 @@ var ViewApply;
|
|
|
3910
3929
|
(function (ViewApply) {
|
|
3911
3930
|
ViewApply["ROOMS"] = "roomFilters";
|
|
3912
3931
|
})(ViewApply || (ViewApply = {}));
|
|
3932
|
+
var Pages;
|
|
3933
|
+
(function (Pages) {
|
|
3934
|
+
Pages["ROOMS"] = "/rooms";
|
|
3935
|
+
Pages["EVENTS"] = "/events";
|
|
3936
|
+
})(Pages || (Pages = {}));
|
|
3913
3937
|
|
|
3914
3938
|
var useFilterBar = function (_a) {
|
|
3915
3939
|
var redirectUrl = _a.redirectUrl, currentViewApply = _a.currentViewApply, ageCategories = _a.ageCategories, onSubmit = _a.onSubmit;
|
|
3916
|
-
var _b = __read(useState(
|
|
3940
|
+
var _b = __read(useState(Pages.EVENTS), 2), selectedPath = _b[0], setSelectedPath = _b[1];
|
|
3917
3941
|
var _c = __read(useState(false), 2), selectedFilter = _c[0], setSelectedFilter = _c[1];
|
|
3918
3942
|
var _d = __read(useState(), 2), calendarRange = _d[0], setCalendarRange = _d[1];
|
|
3919
3943
|
var _e = __read(useState(0), 2), categories = _e[0], setCategories = _e[1];
|
|
@@ -3947,11 +3971,11 @@ var useFilterBar = function (_a) {
|
|
|
3947
3971
|
// Handle default selected tab
|
|
3948
3972
|
if (typeof window === 'undefined')
|
|
3949
3973
|
return;
|
|
3950
|
-
var currentPath = window.location.pathname.includes(
|
|
3951
|
-
?
|
|
3952
|
-
: window.location.pathname.includes(
|
|
3953
|
-
?
|
|
3954
|
-
:
|
|
3974
|
+
var currentPath = window.location.pathname.includes(Pages.EVENTS)
|
|
3975
|
+
? Pages.EVENTS
|
|
3976
|
+
: window.location.pathname.includes(Pages.ROOMS)
|
|
3977
|
+
? Pages.ROOMS
|
|
3978
|
+
: Pages.EVENTS;
|
|
3955
3979
|
setSelectedPath(currentPath);
|
|
3956
3980
|
}, []);
|
|
3957
3981
|
var updateGuestsCount = function (id, newCount) {
|
|
@@ -4013,7 +4037,7 @@ var useFilterBar = function (_a) {
|
|
|
4013
4037
|
var baseUrl = window.location.origin + window.location.pathname;
|
|
4014
4038
|
var updatedUrl = "".concat(baseUrl, "?").concat(updatedParams.toString());
|
|
4015
4039
|
handleSelectedFilter(false);
|
|
4016
|
-
if (onSubmit && selectedPath ===
|
|
4040
|
+
if (onSubmit && selectedPath === Pages.ROOMS) {
|
|
4017
4041
|
var updatedParamsObject_1 = {};
|
|
4018
4042
|
updatedParams.forEach(function (value, key) {
|
|
4019
4043
|
if (value)
|
|
@@ -4041,15 +4065,14 @@ var useFilterBar = function (_a) {
|
|
|
4041
4065
|
finally { if (e_3) throw e_3.error; }
|
|
4042
4066
|
}
|
|
4043
4067
|
handleSelectedFilter(false);
|
|
4044
|
-
return onSubmit && selectedPath ===
|
|
4068
|
+
return onSubmit && selectedPath === Pages.ROOMS
|
|
4045
4069
|
? onSubmit(newParams)
|
|
4046
4070
|
: (window.location.href = "".concat(redirectUrl, "/").concat(selectedPath).concat(querySearchParams ? "?".concat(querySearchParams.toString()) : ''));
|
|
4047
4071
|
}
|
|
4048
4072
|
};
|
|
4049
4073
|
var handleResetFilters = function () {
|
|
4050
4074
|
setAgeCategoryCounts({});
|
|
4051
|
-
|
|
4052
|
-
setSelectedFilter(false);
|
|
4075
|
+
setCalendarRange(undefined);
|
|
4053
4076
|
};
|
|
4054
4077
|
return {
|
|
4055
4078
|
selectedFilter: selectedFilter,
|
|
@@ -6393,7 +6416,8 @@ var guests$1 = {
|
|
|
6393
6416
|
labelPlaceholder: "Add guests",
|
|
6394
6417
|
title: "Who's coming?",
|
|
6395
6418
|
adultsLabel: "Adults",
|
|
6396
|
-
kidsLabel: "kids"
|
|
6419
|
+
kidsLabel: "kids",
|
|
6420
|
+
guestsLabel: "Guests"
|
|
6397
6421
|
};
|
|
6398
6422
|
var categories$1 = {
|
|
6399
6423
|
label: "Categories",
|
|
@@ -6427,7 +6451,8 @@ var guests = {
|
|
|
6427
6451
|
labelPlaceholder: "Lisää vieraat",
|
|
6428
6452
|
title: "Ketkä ovat tulossa?",
|
|
6429
6453
|
adultsLabel: "Aikuiset",
|
|
6430
|
-
kidsLabel: "lapset"
|
|
6454
|
+
kidsLabel: "lapset",
|
|
6455
|
+
guestsLabel: "Gieraita"
|
|
6431
6456
|
};
|
|
6432
6457
|
var categories = {
|
|
6433
6458
|
label: "Kategoriat",
|
|
@@ -10629,17 +10654,19 @@ var css_248z$3 = ".will-calendar-filter-header {\n padding: 15px 0;\n border-b
|
|
|
10629
10654
|
styleInject(css_248z$3);
|
|
10630
10655
|
|
|
10631
10656
|
var Calendar = forwardRef(function (_a, ref) {
|
|
10632
|
-
var
|
|
10657
|
+
var _b;
|
|
10658
|
+
var calendarRange = _a.calendarRange, setCalendarRange = _a.setCalendarRange, calendarOffset = _a.calendarOffset, selectedPath = _a.selectedPath;
|
|
10633
10659
|
var isTablet = reactResponsiveExports.useMediaQuery({ maxWidth: 960 });
|
|
10634
10660
|
useEffect(function () {
|
|
10635
10661
|
if (!calendarRange)
|
|
10636
10662
|
setCalendarRange(undefined);
|
|
10637
10663
|
}, []);
|
|
10638
10664
|
var today = startOfDay(new Date());
|
|
10665
|
+
var daysToOffsetCalendar = (_b = Object.entries(calendarOffset)) === null || _b === void 0 ? void 0 : _b.find(function (page) { return selectedPath.substring(1) === page[0]; });
|
|
10639
10666
|
var disabledDays = [
|
|
10640
10667
|
{
|
|
10641
|
-
from: addDays(today, -2),
|
|
10642
|
-
to: addDays(today, -
|
|
10668
|
+
from: addDays(today, !!(daysToOffsetCalendar === null || daysToOffsetCalendar === void 0 ? void 0 : daysToOffsetCalendar.length) ? daysToOffsetCalendar[1] : -2),
|
|
10669
|
+
to: addDays(today, -100),
|
|
10643
10670
|
},
|
|
10644
10671
|
];
|
|
10645
10672
|
var selectedStartDate = calendarRange === null || calendarRange === void 0 ? void 0 : calendarRange.from;
|
|
@@ -10687,7 +10714,7 @@ var css_248z = ".will-root {\n z-index: 999;\n width: fit-content;\n min-widt
|
|
|
10687
10714
|
styleInject(css_248z);
|
|
10688
10715
|
|
|
10689
10716
|
function FilterBar(_a) {
|
|
10690
|
-
var language = _a.language, _b = _a.ageCategories, ageCategories = _b === void 0 ? AGE_CATEGORIES_FALLBACK : _b, _c = _a.redirectUrl, redirectUrl = _c === void 0 ? REDIRECT_URL_FALLBACK : _c, palette = _a.palette, currentViewApply = _a.currentViewApply, onSubmit = _a.onSubmit, fullWidth = _a.fullWidth;
|
|
10717
|
+
var language = _a.language, _b = _a.ageCategories, ageCategories = _b === void 0 ? AGE_CATEGORIES_FALLBACK : _b, _c = _a.redirectUrl, redirectUrl = _c === void 0 ? REDIRECT_URL_FALLBACK : _c, palette = _a.palette, currentViewApply = _a.currentViewApply, onSubmit = _a.onSubmit, fullWidth = _a.fullWidth, calendarOffset = _a.calendarOffset;
|
|
10691
10718
|
var themePalette = useTheme({ palette: palette });
|
|
10692
10719
|
// Translations
|
|
10693
10720
|
useUpdateTranslations({ language: language });
|
|
@@ -10698,11 +10725,11 @@ function FilterBar(_a) {
|
|
|
10698
10725
|
currentViewApply: currentViewApply,
|
|
10699
10726
|
ageCategories: ageCategories,
|
|
10700
10727
|
onSubmit: onSubmit,
|
|
10701
|
-
}), selectedFilter = _d.selectedFilter, ageCategoryCounts = _d.ageCategoryCounts, categories = _d.categories, calendarRange = _d.calendarRange, selectedPath = _d.selectedPath, setCalendarRange = _d.setCalendarRange, setCategories = _d.setCategories, handleSelectedFilter = _d.handleSelectedFilter, handleSubmit = _d.handleSubmit, updateGuestsCount = _d.updateGuestsCount, setSelectedPath = _d.setSelectedPath;
|
|
10728
|
+
}), selectedFilter = _d.selectedFilter, ageCategoryCounts = _d.ageCategoryCounts, categories = _d.categories, calendarRange = _d.calendarRange, selectedPath = _d.selectedPath, setCalendarRange = _d.setCalendarRange, setCategories = _d.setCategories, handleSelectedFilter = _d.handleSelectedFilter, handleSubmit = _d.handleSubmit, updateGuestsCount = _d.updateGuestsCount, setSelectedPath = _d.setSelectedPath, handleResetFilters = _d.handleResetFilters;
|
|
10702
10729
|
// Default selected tab when tabs are hidden
|
|
10703
10730
|
useEffect(function () {
|
|
10704
10731
|
if (currentViewApply === ViewApply.ROOMS) {
|
|
10705
|
-
setSelectedPath(
|
|
10732
|
+
setSelectedPath(Pages.ROOMS);
|
|
10706
10733
|
}
|
|
10707
10734
|
}, []);
|
|
10708
10735
|
// Scroll in to view
|
|
@@ -10722,21 +10749,27 @@ function FilterBar(_a) {
|
|
|
10722
10749
|
var parsedGuests = parseGuests({ ageCategoryCounts: ageCategoryCounts, ageCategories: ageCategories });
|
|
10723
10750
|
return (React__default__default.createElement("div", { className: "will-root ".concat(fullWidth ? 'is-full-width' : ''), style: themePalette },
|
|
10724
10751
|
!currentViewApply && (React__default__default.createElement("div", { className: "will-filter-bar-tabs", ref: !currentViewApply ? targetFilterBarRef : null },
|
|
10725
|
-
React__default__default.createElement(TabButton, { label: t('tabs.events'), onClick: function () {
|
|
10726
|
-
|
|
10752
|
+
React__default__default.createElement(TabButton, { label: t('tabs.events'), onClick: function () {
|
|
10753
|
+
setSelectedPath(Pages.EVENTS), handleResetFilters();
|
|
10754
|
+
}, active: selectedPath === Pages.EVENTS }),
|
|
10755
|
+
React__default__default.createElement(TabButton, { label: t('tabs.rooms'), onClick: function () {
|
|
10756
|
+
setSelectedPath(Pages.ROOMS), handleResetFilters();
|
|
10757
|
+
}, active: selectedPath === Pages.ROOMS }))),
|
|
10727
10758
|
React__default__default.createElement("div", { className: "will-filter-bar-header", ref: currentViewApply ? targetFilterBarRef : null },
|
|
10728
10759
|
React__default__default.createElement(SelectButton, { label: t('calendar.label'), description: parsedDates
|
|
10729
10760
|
? parsedDates
|
|
10730
|
-
: selectedPath ===
|
|
10761
|
+
: selectedPath === Pages.ROOMS
|
|
10731
10762
|
? t('calendar.roomsLabelPlaceholder')
|
|
10732
10763
|
: t('calendar.eventsLabelPlaceholder'), onClick: function () { return handleSelectedFilter(FilterSections.CALENDAR); }, active: selectedFilter === FilterSections.CALENDAR }),
|
|
10733
|
-
selectedPath ===
|
|
10764
|
+
selectedPath === Pages.ROOMS && (React__default__default.createElement(React__default__default.Fragment, null,
|
|
10734
10765
|
React__default__default.createElement(Divider, null),
|
|
10735
|
-
React__default__default.createElement(SelectButton, { label: t('guests.label'), description: parsedGuests
|
|
10766
|
+
React__default__default.createElement(SelectButton, { label: t('guests.label'), description: parsedGuests
|
|
10767
|
+
? t('guests.guestsLabel') + parsedGuests
|
|
10768
|
+
: t('guests.labelPlaceholder'), onClick: function () { return handleSelectedFilter(FilterSections.GUESTS); }, active: selectedFilter === FilterSections.GUESTS }))),
|
|
10736
10769
|
React__default__default.createElement(SubmitButton, { onClick: handleSubmit })),
|
|
10737
10770
|
selectedFilter && (React__default__default.createElement("div", { className: "will-filter-bar-container", style: currentViewApply && !isMobile ? { top: 66 } : {} },
|
|
10738
10771
|
React__default__default.createElement(CloseButton, { handleClose: function () { return handleSelectedFilter(false); } }),
|
|
10739
|
-
selectedFilter === FilterSections.CALENDAR && (React__default__default.createElement(Calendar, { calendarRange: calendarRange, setCalendarRange: setCalendarRange, ref: filtersRef })),
|
|
10772
|
+
selectedFilter === FilterSections.CALENDAR && (React__default__default.createElement(Calendar, { calendarRange: calendarRange, setCalendarRange: setCalendarRange, ref: filtersRef, calendarOffset: calendarOffset, selectedPath: selectedPath })),
|
|
10740
10773
|
selectedFilter === FilterSections.GUESTS && (React__default__default.createElement(Guests, { updateGuestsCount: updateGuestsCount, ageCategories: ageCategories, ageCategoryCounts: ageCategoryCounts, ref: filtersRef })),
|
|
10741
10774
|
selectedFilter === FilterSections.CATEGORIES && (React__default__default.createElement(Categories, { categories: categories, setCategories: setCategories }))))));
|
|
10742
10775
|
}
|