willba-component-library 0.3.13 → 0.3.15

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 (110) hide show
  1. package/README.md +12 -12
  2. package/lib/assets/IconsSvg.d.ts +2 -1
  3. package/lib/components/Button/Button.d.ts +2 -2
  4. package/lib/components/FilterBar/FilterBar.d.ts +3 -2
  5. package/lib/components/FilterBar/components/FilterControls/FilterControls.d.ts +3 -0
  6. package/lib/components/FilterBar/components/FilterPanels/Categories/Categories.d.ts +11 -0
  7. package/lib/components/FilterBar/components/FilterPanels/Dates/Dates.d.ts +16 -0
  8. package/lib/components/FilterBar/components/FilterPanels/FilterPanels.d.ts +3 -0
  9. package/lib/components/FilterBar/components/FilterPanels/Guests/GuestCount/GuestCount.d.ts +4 -0
  10. package/lib/components/FilterBar/components/FilterPanels/Guests/Guests.d.ts +12 -0
  11. package/lib/components/FilterBar/components/FilterPanels/Locations/Locations.d.ts +14 -0
  12. package/lib/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.d.ts +8 -0
  13. package/lib/components/FilterBar/components/FilterTabs/FilterTabs.d.ts +3 -0
  14. package/lib/components/FilterBar/components/ImageCard/ImageCard.d.ts +11 -0
  15. package/lib/components/FilterBar/components/SelectButton/SelectButton.d.ts +13 -0
  16. package/lib/components/FilterBar/components/TabButton/TabButton.d.ts +10 -0
  17. package/lib/components/FilterBar/components/buttons/select-button/SelectButton.d.ts +2 -1
  18. package/lib/components/FilterBar/components/buttons/tab-button/TabButton.d.ts +2 -1
  19. package/lib/components/FilterBar/components/cards/image-card/ImageCard.d.ts +2 -1
  20. package/lib/components/FilterBar/components/categories/Categories.d.ts +2 -1
  21. package/lib/components/FilterBar/components/common/FilterSectionHeader.d.ts +2 -2
  22. package/lib/components/FilterBar/components/dates/Dates.d.ts +2 -2
  23. package/lib/components/FilterBar/components/divider/Divider.d.ts +2 -1
  24. package/lib/components/FilterBar/components/guests/Guests.d.ts +2 -1
  25. package/lib/components/FilterBar/components/index.d.ts +6 -5
  26. package/lib/components/FilterBar/components/locations/Locations.d.ts +2 -1
  27. package/lib/components/FilterBar/hooks/index.d.ts +4 -1
  28. package/lib/components/FilterBar/hooks/useFilterActions.d.ts +25 -0
  29. package/lib/components/FilterBar/hooks/useFilterState.d.ts +22 -0
  30. package/lib/components/FilterBar/hooks/useFilterUi.d.ts +7 -0
  31. package/lib/components/FilterBar/hooks/usePanelPosition.d.ts +12 -0
  32. package/lib/components/FilterBar/index.d.ts +1 -1
  33. package/lib/components/FilterBar/providers/FilterBarProvider.d.ts +31 -0
  34. package/lib/components/FilterBar/providers/index.d.ts +1 -0
  35. package/lib/components/FilterBar/utils/ageCategoriesRules.d.ts +7 -0
  36. package/lib/components/FilterBar/utils/index.d.ts +1 -1
  37. package/lib/components/FilterBar/utils/parseGuests.d.ts +5 -1
  38. package/lib/components/FilterCalendar/FilterCalendar.d.ts +3 -2
  39. package/lib/components/FilterCalendar/components/Footer.d.ts +2 -1
  40. package/lib/core/components/buttons/CloseButton/CloseButton.d.ts +7 -0
  41. package/lib/core/components/buttons/SubmitButton/SubmitButton.d.ts +14 -0
  42. package/lib/core/components/buttons/close-button/CloseButton.d.ts +2 -1
  43. package/lib/core/components/buttons/submit-button/SubmitButton.d.ts +2 -1
  44. package/lib/core/components/calendar/Calendar.d.ts +2 -1
  45. package/lib/core/components/index.d.ts +4 -2
  46. package/lib/index.d.ts +4 -5
  47. package/lib/index.esm.js +1593 -1480
  48. package/lib/index.esm.js.map +1 -1
  49. package/lib/index.js +2156 -2043
  50. package/lib/index.js.map +1 -1
  51. package/lib/index.umd.js +2159 -2045
  52. package/lib/index.umd.js.map +1 -1
  53. package/lib/themes/useTheme.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/rollup.config.mjs +1 -1
  56. package/src/components/FilterBar/FilterBar.css +4 -70
  57. package/src/components/FilterBar/FilterBar.stories.tsx +1 -1
  58. package/src/components/FilterBar/FilterBar.tsx +28 -283
  59. package/src/components/FilterBar/components/FilterControls/FilterControls.css +18 -0
  60. package/src/components/FilterBar/components/FilterControls/FilterControls.tsx +135 -0
  61. package/src/components/FilterBar/components/{categories → FilterPanels/Categories}/Categories.css +1 -1
  62. package/src/components/FilterBar/components/{categories → FilterPanels/Categories}/Categories.tsx +3 -1
  63. package/src/components/FilterBar/components/{dates → FilterPanels/Dates}/Dates.tsx +11 -11
  64. package/src/components/FilterBar/components/FilterPanels/FilterPanels.css +24 -0
  65. package/src/components/FilterBar/components/FilterPanels/FilterPanels.tsx +115 -0
  66. package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/GuestCount/GuestCount.tsx +1 -1
  67. package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/Guests.css +5 -6
  68. package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/Guests.tsx +7 -7
  69. package/src/components/FilterBar/components/{locations → FilterPanels/Locations}/Locations.css +1 -1
  70. package/src/components/FilterBar/components/{locations → FilterPanels/Locations}/Locations.tsx +7 -6
  71. package/src/components/FilterBar/components/{common/FilterSectionHeader.tsx → FilterPanels/SectionHeader/SectionHeader.tsx} +2 -2
  72. package/src/components/FilterBar/components/FilterTabs/FilterTabs.css +10 -0
  73. package/src/components/FilterBar/components/FilterTabs/FilterTabs.tsx +47 -0
  74. package/src/components/FilterBar/components/{buttons/select-button → SelectButton}/SelectButton.css +1 -0
  75. package/src/components/FilterBar/components/{buttons/select-button → SelectButton}/SelectButton.tsx +7 -6
  76. package/src/components/FilterBar/components/index.ts +6 -6
  77. package/src/components/FilterBar/hooks/index.ts +4 -1
  78. package/src/components/FilterBar/hooks/useFilterActions.tsx +126 -0
  79. package/src/components/FilterBar/hooks/useFilterState.tsx +86 -0
  80. package/src/components/FilterBar/hooks/useFilterUi.tsx +19 -0
  81. package/src/components/FilterBar/hooks/usePanelPosition.tsx +66 -0
  82. package/src/components/FilterBar/index.ts +1 -1
  83. package/src/components/FilterBar/providers/FilterBarProvider.tsx +169 -0
  84. package/src/components/FilterBar/providers/index.ts +1 -0
  85. package/src/components/FilterBar/utils/ageCategoriesRules.ts +27 -0
  86. package/src/components/FilterBar/utils/index.tsx +1 -1
  87. package/src/components/FilterBar/utils/parseGuests.tsx +20 -9
  88. package/src/components/FilterBar/utils/{parseLocations.tsx → parseLocations.ts} +3 -4
  89. package/src/components/FilterCalendar/FilterCalendar.tsx +2 -2
  90. package/src/core/components/index.ts +5 -2
  91. package/src/index.ts +1 -1
  92. package/src/themes/useTheme.tsx +1 -1
  93. package/src/components/FilterBar/components/buttons/index.ts +0 -5
  94. package/src/components/FilterBar/components/cards/index.ts +0 -1
  95. package/src/components/FilterBar/components/dates/index.ts +0 -1
  96. package/src/components/FilterBar/hooks/useFilterBar.tsx +0 -208
  97. package/src/components/FilterBar/utils/calculateDropdownPosition.tsx +0 -96
  98. /package/src/components/FilterBar/components/{divider → Divider}/Divider.css +0 -0
  99. /package/src/components/FilterBar/components/{divider → Divider}/Divider.tsx +0 -0
  100. /package/src/components/FilterBar/components/{dates → FilterPanels/Dates}/Dates.css +0 -0
  101. /package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/GuestCount/GuestCount.css +0 -0
  102. /package/src/components/FilterBar/components/{common/FilterSectionHeader.css → FilterPanels/SectionHeader/SectionHeader.css} +0 -0
  103. /package/src/components/FilterBar/components/{cards/image-card → ImageCard}/ImageCard.css +0 -0
  104. /package/src/components/FilterBar/components/{cards/image-card → ImageCard}/ImageCard.tsx +0 -0
  105. /package/src/components/FilterBar/components/{buttons/tab-button → TabButton}/TabButton.css +0 -0
  106. /package/src/components/FilterBar/components/{buttons/tab-button → TabButton}/TabButton.tsx +0 -0
  107. /package/src/core/components/buttons/{close-button → CloseButton}/CloseButton.css +0 -0
  108. /package/src/core/components/buttons/{close-button → CloseButton}/CloseButton.tsx +0 -0
  109. /package/src/core/components/buttons/{submit-button → SubmitButton}/SubmitButton.css +0 -0
  110. /package/src/core/components/buttons/{submit-button → SubmitButton}/SubmitButton.tsx +0 -0
@@ -0,0 +1,169 @@
1
+ import React, {
2
+ createContext,
3
+ useContext,
4
+ PropsWithChildren,
5
+ RefObject,
6
+ MutableRefObject,
7
+ useMemo,
8
+ } from 'react'
9
+ import { DateRange } from 'react-day-picker'
10
+
11
+ import { AgeCategoryCount, Location, FilterBarTypes } from '../FilterBarTypes'
12
+ import { useFilterActions, useFilterState, useFilterUi } from '../hooks'
13
+
14
+ type FilterBarProviderProps = PropsWithChildren<FilterBarTypes>
15
+
16
+ type FilterBarContextType = FilterBarTypes & {
17
+ selectedFilter: string | boolean
18
+ ageCategoryCounts: AgeCategoryCount
19
+ categories: number
20
+ calendarRange?: DateRange
21
+ selectedPath: string
22
+ innerLoading: boolean
23
+ selectedLocations: Location[]
24
+
25
+ setSelectedLocations: (val: Location[]) => void
26
+ setCalendarRange: (val: DateRange | undefined) => void
27
+ setSelectedFilter: (val: string | boolean) => void
28
+ setAgeCategoryCounts: (val: AgeCategoryCount) => void
29
+ setCategories: (val: number) => void
30
+ setSelectedPath: (val: string) => void
31
+
32
+ handleSelectedFilter: (id: string | boolean) => void
33
+ handleSubmit: () => void
34
+ updateGuestsCount: (id: string, newCount: number) => void
35
+ handleResetFilters: () => void
36
+
37
+ // Refs
38
+ previouslyFocusedButtonRef: MutableRefObject<HTMLButtonElement | null>
39
+ panelRef: MutableRefObject<HTMLDivElement | null>
40
+ buttonRefs: MutableRefObject<Record<string, HTMLButtonElement | null>>
41
+
42
+ // Mobile
43
+ isMobile: boolean
44
+ targetFilterBarRef: RefObject<HTMLDivElement>
45
+ }
46
+
47
+ const FilterBarContext = createContext<FilterBarContextType | undefined>(
48
+ undefined
49
+ )
50
+
51
+ export const FilterBarProvider = ({
52
+ children,
53
+ language,
54
+ ageCategories,
55
+ redirectUrl,
56
+ palette,
57
+ onSubmit,
58
+ fullWidth,
59
+ disableCalendarDates,
60
+ mode,
61
+ tabs,
62
+ outerLoading,
63
+ locations,
64
+ }: FilterBarProviderProps) => {
65
+ const {
66
+ selectedPath,
67
+ selectedFilter,
68
+ calendarRange,
69
+ innerLoading,
70
+ categories,
71
+ ageCategoryCounts,
72
+ selectedLocations,
73
+ setSelectedLocations,
74
+ setCalendarRange,
75
+ setAgeCategoryCounts,
76
+ setCategories,
77
+ setSelectedPath,
78
+ setSelectedFilter,
79
+ setInnerLoading,
80
+ } = useFilterState({ locations })
81
+
82
+ const filterActions = useFilterActions({
83
+ tabs,
84
+ ageCategoryCounts,
85
+ ageCategories,
86
+ selectedLocations,
87
+ selectedPath,
88
+ redirectUrl,
89
+ setSelectedPath,
90
+ setAgeCategoryCounts,
91
+ setSelectedFilter,
92
+ setCalendarRange,
93
+ onSubmit,
94
+ setInnerLoading,
95
+ })
96
+
97
+ const filterUi = useFilterUi(selectedFilter)
98
+
99
+ const contextValue = useMemo(
100
+ () => ({
101
+ selectedFilter,
102
+ ageCategoryCounts,
103
+ categories,
104
+ calendarRange,
105
+ selectedPath,
106
+ innerLoading,
107
+ selectedLocations,
108
+
109
+ setSelectedLocations,
110
+ setCalendarRange,
111
+ setSelectedFilter,
112
+ setAgeCategoryCounts,
113
+ setCategories,
114
+ setSelectedPath,
115
+
116
+ ...filterActions,
117
+
118
+ language,
119
+ ageCategories,
120
+ redirectUrl,
121
+ palette,
122
+ onSubmit,
123
+ fullWidth,
124
+ disableCalendarDates,
125
+ mode,
126
+ tabs,
127
+ outerLoading,
128
+ locations,
129
+
130
+ ...filterUi,
131
+ }),
132
+ [
133
+ selectedFilter,
134
+ ageCategoryCounts,
135
+ categories,
136
+ calendarRange,
137
+ selectedPath,
138
+ innerLoading,
139
+ selectedLocations,
140
+ language,
141
+ ageCategories,
142
+ redirectUrl,
143
+ palette,
144
+ onSubmit,
145
+ fullWidth,
146
+ disableCalendarDates,
147
+ mode,
148
+ tabs,
149
+ outerLoading,
150
+ locations,
151
+ filterUi.isMobile,
152
+ filterUi.targetFilterBarRef,
153
+ ]
154
+ )
155
+
156
+ return (
157
+ <FilterBarContext.Provider value={contextValue}>
158
+ {children}
159
+ </FilterBarContext.Provider>
160
+ )
161
+ }
162
+
163
+ export const useFilterBar = () => {
164
+ const context = useContext(FilterBarContext)
165
+ if (!context) {
166
+ throw new Error('useFilterBar must be used within FilterBarProvider')
167
+ }
168
+ return context
169
+ }
@@ -0,0 +1 @@
1
+ export { FilterBarProvider, useFilterBar } from './FilterBarProvider'
@@ -0,0 +1,27 @@
1
+ import { AgeCategoryCount, AgeCategoryType } from '../FilterBarTypes'
2
+
3
+ type Props = {
4
+ ageCategoryCounts: AgeCategoryCount
5
+ ageCategories?: AgeCategoryType[]
6
+ }
7
+
8
+ export const ageCategoryRules = ({
9
+ ageCategoryCounts,
10
+ ageCategories,
11
+ }: Props): string => {
12
+ if (ageCategories?.length) {
13
+ ageCategories?.map((a) => {
14
+ if (a.minVal) {
15
+ const ageCategory = ageCategoryCounts[`guests-${a.id}`]
16
+
17
+ if (!ageCategory) {
18
+ ageCategoryCounts[`guests-${a.id}`] = a.minVal
19
+ }
20
+ }
21
+ })
22
+ }
23
+
24
+ return Object.entries(ageCategoryCounts).length
25
+ ? JSON.stringify(ageCategoryCounts)
26
+ : ''
27
+ }
@@ -1,3 +1,3 @@
1
1
  export { parseGuests } from './parseGuests'
2
2
  export { parseLocations } from './parseLocations'
3
- export { calculateDropdownPosition } from './calculateDropdownPosition'
3
+ export { ageCategoryRules } from './ageCategoriesRules'
@@ -1,8 +1,10 @@
1
+ import React from 'react'
2
+
1
3
  import { AgeCategoryCount, AgeCategoryType } from '../FilterBarTypes'
2
4
 
3
5
  type Props = {
4
6
  ageCategoryCounts: AgeCategoryCount
5
- ageCategories: AgeCategoryType[]
7
+ ageCategories?: AgeCategoryType[]
6
8
  guestLabel: string
7
9
  guestsLabel: string
8
10
  guestsPlaceholder: string
@@ -26,7 +28,7 @@ export const parseGuests = ({
26
28
  if (parts.length < 2) return acc
27
29
 
28
30
  const ageCategoryId = parts[1]
29
- const ageCategory = ageCategories.find((c) => c.id === ageCategoryId)
31
+ const ageCategory = ageCategories?.find((c) => c.id === ageCategoryId)
30
32
 
31
33
  if (ageCategory && value) {
32
34
  return {
@@ -40,15 +42,24 @@ export const parseGuests = ({
40
42
  { total: 0, html: [] }
41
43
  )
42
44
 
43
- const htmlString =
44
- parsedData.html.length > 1 ? parsedData.html.join(' + ') : ''
45
+ if (!parsedData.total) {
46
+ return {
47
+ content: guestsPlaceholder,
48
+ data: parsedData,
49
+ }
50
+ }
51
+
52
+ const breakdown =
53
+ parsedData.html.length > 1 ? parsedData.html.join(' + ') : null
45
54
 
46
55
  return {
47
- content: parsedData.total
48
- ? `<span class="will-guest-count">${parsedData.total}</span> ${
49
- parsedData.total > 1 ? guestsLabel : guestLabel
50
- }${htmlString ? ` &nbsp; ( ${htmlString} )` : ''}`
51
- : guestsPlaceholder,
56
+ content: (
57
+ <>
58
+ <span className="will-guest-count">{parsedData.total}</span>{' '}
59
+ {parsedData.total > 1 ? guestsLabel : guestLabel}
60
+ {breakdown && <> &nbsp; ( {breakdown} )</>}
61
+ </>
62
+ ),
52
63
  data: parsedData,
53
64
  }
54
65
  }
@@ -8,7 +8,6 @@ type Props = {
8
8
 
9
9
  export const parseLocations = ({
10
10
  selectedLocations,
11
-
12
11
  locationsPlaceholder,
13
12
  locationsSelectedLabel = 'locations',
14
13
  }: Props) => {
@@ -17,12 +16,12 @@ export const parseLocations = ({
17
16
  }
18
17
 
19
18
  if (selectedLocations.length === 1) {
20
- const translation = selectedLocations[0].label
19
+ const singleSelection = selectedLocations[0].label
21
20
 
22
- if (!translation) {
21
+ if (!singleSelection) {
23
22
  return locationsPlaceholder
24
23
  }
25
- return translation
24
+ return singleSelection
26
25
  }
27
26
 
28
27
  return `${selectedLocations.length} ${locationsSelectedLabel}`
@@ -1,8 +1,7 @@
1
1
  import React from 'react'
2
2
  import { useTranslation } from 'react-i18next'
3
3
 
4
- import useTheme from '../../themes/useTheme'
5
- import '../../themes/Default.css'
4
+ import { useTheme } from '../../themes/useTheme'
6
5
  import { Calendar, CloseButton } from '../../core/components'
7
6
  import {
8
7
  useAwaitRender,
@@ -14,6 +13,7 @@ import { FilterCalendarTypes } from './FilterCalendarTypes'
14
13
  import { useFilterCalendar } from './hooks/useFilterCalendar'
15
14
  import { Footer } from './components/Footer'
16
15
 
16
+ import '../../themes/Default.css'
17
17
  import './FilterCalendar.css'
18
18
 
19
19
  export default function FilterCalendar({
@@ -1,4 +1,7 @@
1
- export { SubmitButton } from './buttons/submit-button/SubmitButton'
2
- export { CloseButton } from './buttons/close-button/CloseButton'
1
+ export { SubmitButton } from './buttons/SubmitButton/SubmitButton'
2
+ export { CloseButton } from './buttons/CloseButton/CloseButton'
3
3
 
4
+ // Calendar
4
5
  export { Calendar } from './calendar/Calendar'
6
+ export type { CalendarTypes } from './calendar/CalendarTypes'
7
+ export { parseDates } from './calendar/utils'
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Button from './components/Button'
2
- import FilterBar from './components/FilterBar'
2
+ import { FilterBar } from './components/FilterBar'
3
3
  import FilterCalendar from './components/FilterCalendar'
4
4
 
5
5
  export { Button, FilterBar, FilterCalendar }
@@ -16,7 +16,7 @@ export interface CustomPaletteTypes extends CSSProperties {
16
16
  '--will-error'?: string
17
17
  }
18
18
 
19
- export default function useTheme({ palette }: ThemeProps) {
19
+ export const useTheme = ({ palette }: ThemeProps) => {
20
20
  const themePalette: CustomPaletteTypes = {
21
21
  '--will-primary': palette?.primary,
22
22
  '--will-secondary': palette?.secondary,
@@ -1,5 +0,0 @@
1
- export { CloseButton } from '../../../../core/components/buttons/close-button/CloseButton'
2
- export { SubmitButton } from '../../../../core/components/buttons/submit-button/SubmitButton'
3
-
4
- export { SelectButton } from './select-button/SelectButton'
5
- export { TabButton } from './tab-button/TabButton'
@@ -1 +0,0 @@
1
- export { ImageCard } from './image-card/ImageCard'
@@ -1 +0,0 @@
1
- export { Dates } from './Dates'
@@ -1,208 +0,0 @@
1
- import { useEffect, useState } from 'react'
2
- import { DateRange } from 'react-day-picker'
3
- import { format } from 'date-fns'
4
-
5
- import {
6
- AgeCategoryCount,
7
- AgeCategoryType,
8
- Filters,
9
- Pages,
10
- Tab,
11
- Location,
12
- } from '../FilterBarTypes'
13
-
14
- type Props = {
15
- redirectUrl?: string
16
- ageCategories?: AgeCategoryType[]
17
- onSubmit?: ((val: Filters) => void) | null
18
- tabs?: Tab[]
19
- locations?: {
20
- multiSelect: boolean
21
- data: Location[]
22
- }
23
- }
24
-
25
- export const useFilterBar = ({
26
- redirectUrl,
27
- ageCategories,
28
- onSubmit,
29
- tabs,
30
- locations,
31
- }: Props) => {
32
- const [selectedPath, setSelectedPath] = useState<string>(Pages.EVENTS)
33
- const [selectedFilter, setSelectedFilter] = useState<string | boolean>(false)
34
- const [calendarRange, setCalendarRange] = useState<DateRange | undefined>()
35
- const [innerLoading, setInnerLoading] = useState<boolean>(false)
36
-
37
- const [categories, setCategories] = useState<number>(0)
38
- const [ageCategoryCounts, setAgeCategoryCounts] = useState<AgeCategoryCount>(
39
- {}
40
- )
41
- const [selectedLocations, setSelectedLocations] = useState<Location[]>([])
42
-
43
- useEffect(() => {
44
- const urlSearchParams = new URLSearchParams(window.location.search)
45
-
46
- const startDateParam = urlSearchParams.get('startDate')
47
- const endDateParam = urlSearchParams.get('endDate')
48
- // Get all locationId params from URL
49
- const locationIdParams = urlSearchParams.getAll('locationId')
50
- const ageCategoryCountsParam = JSON.parse(
51
- urlSearchParams.get('ageCategoryCounts') || '{}'
52
- )
53
- const parsedCategories = parseInt(
54
- urlSearchParams.get('categories') || '0',
55
- 10
56
- )
57
-
58
- if (startDateParam && endDateParam) {
59
- setCalendarRange({
60
- from: new Date(startDateParam),
61
- to: new Date(endDateParam),
62
- })
63
- }
64
-
65
- setAgeCategoryCounts(ageCategoryCountsParam)
66
- setCategories(parsedCategories)
67
-
68
- // Set selected locations from URL - handle all locationIds
69
- if (locations?.data?.length && locationIdParams.length) {
70
- const matchedLocations = locations.data.filter((location) =>
71
- locationIdParams.includes(location.id.toString())
72
- )
73
- setSelectedLocations(matchedLocations)
74
- }
75
- }, [])
76
-
77
- useEffect(() => {
78
- if (typeof window === 'undefined') return
79
-
80
- const defaultTab =
81
- tabs?.length === 1 ? tabs[0] : tabs?.find((tab) => tab.default)
82
-
83
- const findMatchingPath = () => {
84
- const paths = [Pages.EVENTS, Pages.ROOMS, Pages.SALES]
85
-
86
- for (const path of paths) {
87
- if (window.location.pathname.includes(path)) {
88
- return path
89
- }
90
- }
91
-
92
- return defaultTab ? defaultTab.path : Pages.EVENTS
93
- }
94
-
95
- const currentPath = findMatchingPath()
96
- setSelectedPath(currentPath)
97
- }, [])
98
-
99
- const updateGuestsCount = (id: string, newCount: number) => {
100
- setAgeCategoryCounts((prevCounts) => ({
101
- ...prevCounts,
102
- [id]: newCount,
103
- }))
104
- }
105
-
106
- const handleSelectedFilter = (id: string | boolean) => {
107
- setSelectedFilter(id)
108
- }
109
-
110
- const handleSubmit = () => {
111
- const newParams = {
112
- startDate: calendarRange?.from
113
- ? format(calendarRange.from, 'yyyy-MM-dd')
114
- : '',
115
- endDate: calendarRange?.to ? format(calendarRange.to, 'yyyy-MM-dd') : '',
116
- //categories: categories.toString(),
117
- ageCategoryCounts: handleAgeCategoryRules({
118
- ageCategoryCounts,
119
- ageCategories,
120
- }),
121
-
122
- selectedLocations: selectedLocations
123
- .map((location) => location.id.toString())
124
- .join(','),
125
- }
126
-
127
- const querySearchParams = new URLSearchParams()
128
-
129
- for (const [key, value] of Object.entries(newParams)) {
130
- if (value) {
131
- if (key === 'selectedLocations' && !!selectedLocations.length) {
132
- // Append all selected locationIds
133
- selectedLocations.forEach((location) => {
134
- querySearchParams.append('locationId', location.id.toString())
135
- })
136
- } else {
137
- querySearchParams.append(key, value.toString())
138
- }
139
- }
140
- }
141
-
142
- handleSelectedFilter(false)
143
-
144
- if (onSubmit && window.location.href.includes(selectedPath)) {
145
- onSubmit(newParams)
146
- } else {
147
- const params = new URLSearchParams(querySearchParams ?? undefined)
148
-
149
- const paramString = params.toString()
150
- const path = `${redirectUrl}${selectedPath}`
151
-
152
- setInnerLoading(true)
153
- window.location.href = paramString ? `${path}?${paramString}` : path
154
- }
155
- }
156
-
157
- const handleResetFilters = () => {
158
- setAgeCategoryCounts({})
159
- setCalendarRange(undefined)
160
- }
161
-
162
- return {
163
- selectedFilter,
164
- ageCategoryCounts,
165
- categories,
166
- calendarRange,
167
- selectedPath,
168
- innerLoading,
169
- selectedLocations,
170
- setSelectedLocations,
171
- setCalendarRange,
172
- setSelectedFilter,
173
- setAgeCategoryCounts,
174
- setCategories,
175
- handleSelectedFilter,
176
- handleSubmit,
177
- updateGuestsCount,
178
- handleResetFilters,
179
- setSelectedPath,
180
- }
181
- }
182
-
183
- ////////////
184
-
185
- const handleAgeCategoryRules = ({
186
- ageCategoryCounts,
187
- ageCategories,
188
- }: {
189
- ageCategoryCounts: AgeCategoryCount
190
- ageCategories?: AgeCategoryType[]
191
- }) => {
192
- if (ageCategories?.length) {
193
- ageCategories?.map((a) => {
194
- if (a.minVal) {
195
- // Age categories rules
196
- const ageCategory = ageCategoryCounts[`guests-${a.id}`]
197
-
198
- if (!ageCategory) {
199
- ageCategoryCounts[`guests-${a.id}`] = a.minVal
200
- }
201
- }
202
- })
203
- }
204
-
205
- return Object.entries(ageCategoryCounts).length
206
- ? JSON.stringify(ageCategoryCounts)
207
- : ''
208
- }
@@ -1,96 +0,0 @@
1
- import { CSSProperties, RefObject } from 'react'
2
- import { FilterSections } from '../FilterBarTypes'
3
-
4
- type CalculateDropdownPositionParams = {
5
- filterSection: FilterSections
6
- headerRef: RefObject<HTMLDivElement>
7
- locationsButtonRef: RefObject<HTMLButtonElement>
8
- datesButtonRef: RefObject<HTMLButtonElement>
9
- guestsButtonRef: RefObject<HTMLButtonElement>
10
- isMobile: boolean
11
- }
12
-
13
- export const calculateDropdownPosition = ({
14
- filterSection,
15
- headerRef,
16
- locationsButtonRef,
17
- datesButtonRef,
18
- guestsButtonRef,
19
- isMobile,
20
- }: CalculateDropdownPositionParams): CSSProperties => {
21
- if (isMobile) {
22
- return {}
23
- }
24
-
25
- if (!headerRef.current) return {}
26
-
27
- const containerRect = headerRef.current.getBoundingClientRect()
28
- const containerLeft = 0
29
-
30
- switch (filterSection) {
31
- case FilterSections.LOCATIONS:
32
- if (locationsButtonRef.current) {
33
- const buttonRect = locationsButtonRef.current.getBoundingClientRect()
34
- const relativeLeft = buttonRect.left - containerRect.left
35
- return {
36
- left: relativeLeft,
37
- right: 'auto',
38
- width: 'auto',
39
- }
40
- }
41
- break
42
-
43
- case FilterSections.CALENDAR:
44
- if (datesButtonRef.current) {
45
- const buttonRect = datesButtonRef.current.getBoundingClientRect()
46
- const relativeLeft = buttonRect.left - containerRect.left
47
- const availableWidth = containerRect.width - relativeLeft
48
- const calendarMinWidth = 650
49
-
50
- if (availableWidth < calendarMinWidth) {
51
- return {
52
- left: 'auto',
53
- right: containerLeft,
54
- width: 'auto',
55
- maxWidth: `${containerRect.width}px`,
56
- }
57
- } else {
58
- return {
59
- left: relativeLeft,
60
- right: 'auto',
61
- width: 'auto',
62
- }
63
- }
64
- }
65
- break
66
-
67
- case FilterSections.GUESTS:
68
- if (guestsButtonRef.current) {
69
- const buttonRect = guestsButtonRef.current.getBoundingClientRect()
70
- const relativeLeft = buttonRect.left - containerRect.left
71
- const availableWidth = containerRect.width - relativeLeft
72
- const dropdownMinWidth = 350
73
-
74
- if (availableWidth < dropdownMinWidth) {
75
- return {
76
- left: 'auto',
77
- right: containerLeft,
78
- width: 'auto',
79
- maxWidth: `${containerRect.width}px`,
80
- }
81
- } else {
82
- return {
83
- left: relativeLeft,
84
- right: 'auto',
85
- width: 'auto',
86
- }
87
- }
88
- }
89
- break
90
-
91
- default:
92
- return {}
93
- }
94
-
95
- return {}
96
- }