willba-component-library 0.2.8 → 0.2.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.
- package/README.md +1 -1
- package/lib/components/FilterBar/FilterBar.d.ts +2 -15
- package/lib/components/FilterBar/FilterBarTypes.d.ts +14 -3
- package/lib/components/FilterBar/components/buttons/index.d.ts +2 -2
- package/lib/components/FilterBar/components/index.d.ts +0 -1
- package/lib/components/FilterBar/hooks/index.d.ts +0 -2
- package/lib/components/FilterBar/utils/index.d.ts +0 -1
- package/lib/components/FilterCalendar/FilterCalendar.d.ts +5 -0
- package/lib/components/FilterCalendar/FilterCalendar.stories.d.ts +6 -0
- package/lib/components/FilterCalendar/FilterCalendarTypes.d.ts +8 -0
- package/lib/components/FilterCalendar/hooks/useFilterCalendar.d.ts +14 -0
- package/lib/components/FilterCalendar/index.d.ts +2 -0
- package/lib/core/components/buttons/close-button/CloseButton.d.ts +7 -0
- package/lib/core/components/buttons/submit-button/SubmitButton.d.ts +10 -0
- package/lib/core/components/calendar/Calendar.d.ts +5 -0
- package/lib/core/components/calendar/CalendarTypes.d.ts +15 -0
- package/lib/core/components/index.d.ts +3 -0
- package/lib/core/hooks/index.d.ts +3 -0
- package/lib/core/hooks/useAwaitRender.d.ts +1 -0
- package/lib/core/hooks/useCloseFilterSection.d.ts +8 -0
- package/lib/core/hooks/useUpdateTranslations.d.ts +5 -0
- package/lib/core/utils/index.d.ts +3 -0
- package/lib/core/utils/nightsCount.d.ts +6 -0
- package/lib/core/utils/parseDate.d.ts +6 -0
- package/lib/core/utils/parseDates.d.ts +6 -0
- package/lib/index.d.ts +40 -19
- package/lib/index.esm.js +6152 -6053
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +6151 -6051
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +6151 -6051
- package/lib/index.umd.js.map +1 -1
- package/lib/themes/useTheme.d.ts +4 -4
- package/package.json +1 -1
- package/src/components/FilterBar/FilterBar.tsx +20 -44
- package/src/components/FilterBar/FilterBarTypes.ts +16 -4
- package/src/components/FilterBar/components/buttons/index.ts +3 -2
- package/src/components/FilterBar/components/buttons/tab-button/TabButton.tsx +1 -1
- package/src/components/FilterBar/components/index.ts +0 -1
- package/src/components/FilterBar/hooks/index.ts +0 -2
- package/src/components/FilterBar/utils/index.tsx +0 -1
- package/src/components/FilterCalendar/FilterCalendar.css +67 -0
- package/src/components/FilterCalendar/FilterCalendar.stories.tsx +48 -0
- package/src/components/FilterCalendar/FilterCalendar.tsx +112 -0
- package/src/components/FilterCalendar/FilterCalendarTypes.ts +10 -0
- package/src/components/FilterCalendar/hooks/useFilterCalendar.ts +29 -0
- package/src/components/FilterCalendar/index.ts +3 -0
- package/src/{components/FilterBar → core}/components/buttons/submit-button/SubmitButton.css +6 -0
- package/src/core/components/buttons/submit-button/SubmitButton.tsx +28 -0
- package/src/{components/FilterBar → core}/components/calendar/Calendar.css +1 -12
- package/src/{components/FilterBar → core}/components/calendar/Calendar.tsx +15 -21
- package/src/core/components/calendar/CalendarTypes.ts +17 -0
- package/src/core/components/index.ts +4 -0
- package/src/core/hooks/index.ts +3 -0
- package/src/core/hooks/useAwaitRender.tsx +12 -0
- package/src/{components/FilterBar → core}/hooks/useCloseFilterSection.tsx +1 -0
- package/src/{components/FilterBar → core}/hooks/useUpdateTranslations.tsx +1 -1
- package/src/core/utils/index.ts +3 -0
- package/src/core/utils/nightsCount.tsx +19 -0
- package/src/core/utils/parseDate.tsx +9 -0
- package/src/i18n.ts +4 -2
- package/src/index.ts +2 -1
- package/src/locales/en/common.json +7 -0
- package/src/locales/en/filterBar.json +0 -3
- package/src/locales/fi/common.json +8 -0
- package/src/locales/fi/filterBar.json +0 -3
- package/src/themes/useTheme.tsx +2 -2
- package/src/components/FilterBar/components/buttons/submit-button/SubmitButton.tsx +0 -18
- /package/src/{components/FilterBar → core}/components/buttons/close-button/CloseButton.css +0 -0
- /package/src/{components/FilterBar → core}/components/buttons/close-button/CloseButton.tsx +0 -0
- /package/src/{components/FilterBar → core}/utils/parseDates.tsx +0 -0
package/lib/themes/useTheme.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
|
-
export
|
|
2
|
+
export type Palette = {
|
|
3
3
|
primary: string;
|
|
4
4
|
secondary: string;
|
|
5
|
-
}
|
|
6
|
-
export
|
|
5
|
+
};
|
|
6
|
+
export type ThemeProps = {
|
|
7
7
|
palette?: Palette;
|
|
8
|
-
}
|
|
8
|
+
};
|
|
9
9
|
interface CustomPaletteTypes extends CSSProperties {
|
|
10
10
|
'--will-primary'?: string;
|
|
11
11
|
'--will-secondary'?: string;
|
package/package.json
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
import { useTranslation } from 'react-i18next'
|
|
3
|
+
import { FaSearch } from 'react-icons/fa'
|
|
3
4
|
|
|
4
|
-
import useTheme
|
|
5
|
+
import useTheme from '../../themes/useTheme'
|
|
5
6
|
import '../../themes/Default.css'
|
|
6
|
-
|
|
7
|
-
import { parseDates, parseGuests } from './utils'
|
|
8
|
-
import {
|
|
9
|
-
AgeCategoryType,
|
|
10
|
-
CalendarOffset,
|
|
11
|
-
FilterSections,
|
|
12
|
-
Filters,
|
|
13
|
-
Pages,
|
|
14
|
-
Tab,
|
|
15
|
-
} from './FilterBarTypes'
|
|
16
7
|
import {
|
|
8
|
+
useAwaitRender,
|
|
17
9
|
useCloseFilterSection,
|
|
18
|
-
useFilterBar,
|
|
19
|
-
useScrollInToView,
|
|
20
10
|
useUpdateTranslations,
|
|
21
|
-
} from '
|
|
11
|
+
} from '../../core/hooks'
|
|
12
|
+
import { Calendar, SubmitButton, CloseButton } from '../../core/components'
|
|
13
|
+
import { parseDates } from '../../core/utils'
|
|
14
|
+
|
|
15
|
+
import { parseGuests } from './utils'
|
|
16
|
+
import { FilterBarProps, FilterSections, Pages } from './FilterBarTypes'
|
|
17
|
+
import { useFilterBar, useScrollInToView } from './hooks'
|
|
22
18
|
import {
|
|
23
19
|
TabButton,
|
|
24
20
|
SelectButton,
|
|
25
|
-
SubmitButton,
|
|
26
|
-
CloseButton,
|
|
27
|
-
Calendar,
|
|
28
21
|
Guests,
|
|
29
22
|
Divider,
|
|
30
23
|
Categories,
|
|
@@ -32,19 +25,6 @@ import {
|
|
|
32
25
|
|
|
33
26
|
import './FilterBar.css'
|
|
34
27
|
|
|
35
|
-
export type FilterBarProps = {
|
|
36
|
-
language?: string
|
|
37
|
-
ageCategories?: AgeCategoryType[]
|
|
38
|
-
redirectUrl?: string
|
|
39
|
-
palette?: Palette
|
|
40
|
-
onSubmit?: ((val: Filters) => void) | null
|
|
41
|
-
fullWidth?: boolean
|
|
42
|
-
calendarOffset?: CalendarOffset
|
|
43
|
-
mode?: string
|
|
44
|
-
defaultTab?: string
|
|
45
|
-
tabs?: Tab[]
|
|
46
|
-
}
|
|
47
|
-
|
|
48
28
|
export default function FilterBar({
|
|
49
29
|
language,
|
|
50
30
|
ageCategories = AGE_CATEGORIES_FALLBACK,
|
|
@@ -90,15 +70,7 @@ export default function FilterBar({
|
|
|
90
70
|
const { filtersRef } = useCloseFilterSection({ handleSelectedFilter })
|
|
91
71
|
|
|
92
72
|
// Display component after fully loaded
|
|
93
|
-
|
|
94
|
-
useState<boolean>(false)
|
|
95
|
-
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
setInitialRenderComplete(true)
|
|
98
|
-
}, [])
|
|
99
|
-
|
|
100
|
-
if (!initialRenderComplete) return null
|
|
101
|
-
//----/----
|
|
73
|
+
useAwaitRender()
|
|
102
74
|
|
|
103
75
|
// Parsed data for filter section description
|
|
104
76
|
const parsedDates = parseDates({ calendarRange })
|
|
@@ -138,7 +110,7 @@ export default function FilterBar({
|
|
|
138
110
|
)}
|
|
139
111
|
|
|
140
112
|
<div
|
|
141
|
-
className={`will-filter-bar-header ${mode || '
|
|
113
|
+
className={`will-filter-bar-header ${mode || 'light'}`}
|
|
142
114
|
ref={tabs?.length === 1 ? targetFilterBarRef : null}
|
|
143
115
|
>
|
|
144
116
|
<SelectButton
|
|
@@ -167,12 +139,16 @@ export default function FilterBar({
|
|
|
167
139
|
</>
|
|
168
140
|
)}
|
|
169
141
|
|
|
170
|
-
<SubmitButton
|
|
142
|
+
<SubmitButton
|
|
143
|
+
onClick={handleSubmit}
|
|
144
|
+
startIcon={<FaSearch />}
|
|
145
|
+
label={t('common:search')}
|
|
146
|
+
/>
|
|
171
147
|
</div>
|
|
172
148
|
|
|
173
149
|
{selectedFilter && (
|
|
174
150
|
<div
|
|
175
|
-
className={`will-filter-bar-container ${mode || '
|
|
151
|
+
className={`will-filter-bar-container ${mode || 'light'}`}
|
|
176
152
|
style={(!tabs || tabs.length < 2) && !isMobile ? { top: 66 } : {}}
|
|
177
153
|
>
|
|
178
154
|
<CloseButton handleClose={() => handleSelectedFilter(false)} />
|
|
@@ -184,7 +160,7 @@ export default function FilterBar({
|
|
|
184
160
|
ref={filtersRef}
|
|
185
161
|
calendarOffset={calendarOffset}
|
|
186
162
|
selectedPath={selectedPath}
|
|
187
|
-
|
|
163
|
+
language={language}
|
|
188
164
|
/>
|
|
189
165
|
)}
|
|
190
166
|
{selectedFilter === FilterSections.GUESTS && (
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
import { Palette } from '../../themes/useTheme'
|
|
2
|
+
import { CalendarOffset } from '../../core/components/calendar/CalendarTypes'
|
|
3
|
+
|
|
4
|
+
export type FilterBarProps = {
|
|
5
|
+
language?: string
|
|
6
|
+
ageCategories?: AgeCategoryType[]
|
|
7
|
+
redirectUrl?: string
|
|
8
|
+
palette?: Palette
|
|
9
|
+
onSubmit?: ((val: Filters) => void) | null
|
|
10
|
+
fullWidth?: boolean
|
|
11
|
+
calendarOffset?: CalendarOffset
|
|
12
|
+
mode?: string
|
|
13
|
+
defaultTab?: string
|
|
14
|
+
tabs?: Tab[]
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
export type AgeCategoryCount = {
|
|
2
18
|
[categoryId: string]: number
|
|
3
19
|
}
|
|
@@ -31,10 +47,6 @@ export enum Pages {
|
|
|
31
47
|
EVENTS = '/events',
|
|
32
48
|
}
|
|
33
49
|
|
|
34
|
-
export type CalendarOffset = {
|
|
35
|
-
[key: string]: number
|
|
36
|
-
}
|
|
37
|
-
|
|
38
50
|
type Translations = {
|
|
39
51
|
en: string
|
|
40
52
|
fi: string
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { CloseButton } from '
|
|
1
|
+
export { CloseButton } from '../../../../core/components/buttons/close-button/CloseButton'
|
|
2
|
+
export { SubmitButton } from '../../../../core/components/buttons/submit-button/SubmitButton'
|
|
3
|
+
|
|
2
4
|
export { SelectButton } from './select-button/SelectButton'
|
|
3
|
-
export { SubmitButton } from './submit-button/SubmitButton'
|
|
4
5
|
export { TabButton } from './tab-button/TabButton'
|
|
@@ -12,7 +12,7 @@ type Props = {
|
|
|
12
12
|
export const TabButton = ({ onClick, label, active, mode }: Props) => {
|
|
13
13
|
return (
|
|
14
14
|
<button
|
|
15
|
-
className={`will-filter-bar-tab-button ${mode || '
|
|
15
|
+
className={`will-filter-bar-tab-button ${mode || 'light'} ${
|
|
16
16
|
active && 'active'
|
|
17
17
|
} `}
|
|
18
18
|
onClick={onClick}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { CloseButton, SelectButton, SubmitButton, TabButton } from './buttons'
|
|
2
2
|
|
|
3
3
|
export { Guests } from './guests/Guests'
|
|
4
|
-
export { Calendar } from './calendar/Calendar'
|
|
5
4
|
export { Divider } from './divider/Divider'
|
|
6
5
|
export { Categories } from './categories/Categories'
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
.will-root .will-calendar-wrapper {
|
|
2
|
+
box-shadow: var(--will-box-shadow-dark);
|
|
3
|
+
border-radius: 20px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.will-root .will-calendar-wrapper .will-calendar-header,
|
|
7
|
+
.will-root .will-calendar-wrapper .will-calendar-main,
|
|
8
|
+
.will-root .will-calendar-wrapper .will-calendar-footer {
|
|
9
|
+
padding: 20px;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Header */
|
|
13
|
+
|
|
14
|
+
.will-root .will-calendar-wrapper .will-calendar-header {
|
|
15
|
+
display: flex;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
border-bottom: 1px solid grey;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Footer */
|
|
21
|
+
|
|
22
|
+
.will-root .will-calendar-wrapper .will-calendar-footer {
|
|
23
|
+
display: flex;
|
|
24
|
+
justify-content: space-between;
|
|
25
|
+
align-items: center;
|
|
26
|
+
border-top: 1px solid grey;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.will-root .will-calendar-wrapper .will-calendar-footer-dates > div {
|
|
30
|
+
margin-bottom: 5px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.will-root .will-calendar-wrapper .will-calendar-footer-dates-separator {
|
|
34
|
+
margin: 0 15px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.will-root .will-calendar-wrapper .will-calendar-footer-actions {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 10px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@media (max-width: 960px) {
|
|
44
|
+
.will-root .will-calendar-wrapper .will-calendar-footer {
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.will-root .will-calendar-wrapper .will-calendar-footer-dates {
|
|
49
|
+
margin-bottom: 20px;
|
|
50
|
+
text-align: center;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.will-root .will-calendar-wrapper .will-calendar-footer-actions {
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
width: 100%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.will-root .will-calendar-wrapper .will-calendar-footer-actions button{
|
|
59
|
+
width: 100%;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**/
|
|
64
|
+
|
|
65
|
+
.will-root .will-calendar-wrapper .will-calendar-header .will-filter-bar-close-button {
|
|
66
|
+
position: initial;
|
|
67
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
3
|
+
|
|
4
|
+
import FilterCalendar from './FilterCalendar'
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof FilterCalendar> = {
|
|
7
|
+
title: 'Components/FilterCalendar',
|
|
8
|
+
component: FilterCalendar,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default meta
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof FilterCalendar>
|
|
14
|
+
|
|
15
|
+
export const Primary: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
calendarOffsetGroup: [
|
|
18
|
+
{
|
|
19
|
+
from: new Date('06.04.2024'),
|
|
20
|
+
to: new Date('06.04.2024'),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
from: new Date('06.05.2024'),
|
|
24
|
+
to: new Date('06.05.2024'),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
from: new Date('06.06.2024'),
|
|
28
|
+
to: new Date('06.06.2024'),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
from: new Date('06.09.2024'),
|
|
32
|
+
to: new Date('06.09.2024'),
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
language: 'en',
|
|
36
|
+
palette: {
|
|
37
|
+
primary: '',
|
|
38
|
+
secondary: '',
|
|
39
|
+
},
|
|
40
|
+
openCalendar: true,
|
|
41
|
+
onSubmit: (val: any) => console.log(val),
|
|
42
|
+
},
|
|
43
|
+
render: (args) => (
|
|
44
|
+
<div style={{ padding: '30px', height: '100vh' }}>
|
|
45
|
+
<FilterCalendar {...args} />
|
|
46
|
+
</div>
|
|
47
|
+
),
|
|
48
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import React, { useEffect } from 'react'
|
|
2
|
+
import { useTranslation } from 'react-i18next'
|
|
3
|
+
|
|
4
|
+
import useTheme from '../../themes/useTheme'
|
|
5
|
+
import '../../themes/Default.css'
|
|
6
|
+
import { Calendar, SubmitButton, CloseButton } from '../../core/components'
|
|
7
|
+
import {
|
|
8
|
+
useAwaitRender,
|
|
9
|
+
useCloseFilterSection,
|
|
10
|
+
useUpdateTranslations,
|
|
11
|
+
} from '../../core/hooks'
|
|
12
|
+
import { nightsCount, parseDate } from '../../core/utils'
|
|
13
|
+
|
|
14
|
+
import { FilterCalendarType } from './FilterCalendarTypes'
|
|
15
|
+
import { useFilterCalendar } from './hooks/useFilterCalendar'
|
|
16
|
+
|
|
17
|
+
import './FilterCalendar.css'
|
|
18
|
+
|
|
19
|
+
export default function FilterCalendar({
|
|
20
|
+
calendarOffset,
|
|
21
|
+
language,
|
|
22
|
+
palette,
|
|
23
|
+
openCalendar,
|
|
24
|
+
onSubmit,
|
|
25
|
+
calendarOffsetGroup,
|
|
26
|
+
}: FilterCalendarType) {
|
|
27
|
+
const themePalette = useTheme({ palette })
|
|
28
|
+
|
|
29
|
+
// Translations
|
|
30
|
+
useUpdateTranslations({ language })
|
|
31
|
+
const { t } = useTranslation()
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
handleSubmit,
|
|
35
|
+
setToggleCalendar,
|
|
36
|
+
setCalendarRange,
|
|
37
|
+
handleClearDates,
|
|
38
|
+
toggleCalendar,
|
|
39
|
+
calendarRange,
|
|
40
|
+
} = useFilterCalendar({ onSubmit })
|
|
41
|
+
|
|
42
|
+
// Display component after fully loaded
|
|
43
|
+
useAwaitRender()
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (openCalendar) setToggleCalendar(true)
|
|
47
|
+
}, [openCalendar])
|
|
48
|
+
|
|
49
|
+
// Handle close filter section
|
|
50
|
+
const { filtersRef } = useCloseFilterSection({
|
|
51
|
+
handleSelectedFilter: setToggleCalendar,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const nights = nightsCount({ calendarRange })
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div className={`will-root`} style={themePalette}>
|
|
58
|
+
{toggleCalendar && (
|
|
59
|
+
<div className={`will-calendar-wrapper`} ref={filtersRef}>
|
|
60
|
+
<div className={`will-calendar-header`}>
|
|
61
|
+
<h2>{t('filterBar:calendar.title')}</h2>
|
|
62
|
+
<CloseButton handleClose={() => setToggleCalendar(false)} />
|
|
63
|
+
</div>
|
|
64
|
+
<div className={`will-calendar-main`}>
|
|
65
|
+
<Calendar
|
|
66
|
+
calendarRange={calendarRange}
|
|
67
|
+
setCalendarRange={setCalendarRange}
|
|
68
|
+
calendarOffset={calendarOffset}
|
|
69
|
+
selectedPath={'/rooms'}
|
|
70
|
+
language={language}
|
|
71
|
+
calendarOffsetGroup={calendarOffsetGroup}
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
<div className={`will-calendar-footer`}>
|
|
75
|
+
<div className={`will-calendar-footer-dates`}>
|
|
76
|
+
<div>
|
|
77
|
+
<span>
|
|
78
|
+
{parseDate({
|
|
79
|
+
date: calendarRange?.from,
|
|
80
|
+
dateFormat: 'EEEEEE d.M.yyyy',
|
|
81
|
+
}) || t('common:checkIn')}
|
|
82
|
+
</span>
|
|
83
|
+
<span className={`will-calendar-footer-dates-separator`}>
|
|
84
|
+
-
|
|
85
|
+
</span>
|
|
86
|
+
<span>
|
|
87
|
+
{parseDate({
|
|
88
|
+
date: calendarRange?.to,
|
|
89
|
+
dateFormat: 'EEEEEE d.M.yyyy',
|
|
90
|
+
}) || t('common:checkOut')}
|
|
91
|
+
</span>
|
|
92
|
+
</div>
|
|
93
|
+
{nights && (
|
|
94
|
+
<span>{`${nights} ${t(
|
|
95
|
+
`common:${nights > 1 ? 'nights' : 'night'}`
|
|
96
|
+
)}`}</span>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
99
|
+
<div className={`will-calendar-footer-actions`}>
|
|
100
|
+
<SubmitButton
|
|
101
|
+
onClick={handleClearDates}
|
|
102
|
+
disabled={!calendarRange?.from}
|
|
103
|
+
label={'Clear dates'}
|
|
104
|
+
/>
|
|
105
|
+
<SubmitButton onClick={handleSubmit} label={t(`common:search`)} />
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DateRange } from 'react-day-picker'
|
|
2
|
+
|
|
3
|
+
import { Palette } from '../../themes/useTheme'
|
|
4
|
+
import { CalendarTypes } from '../../core/components/calendar/CalendarTypes'
|
|
5
|
+
|
|
6
|
+
export interface FilterCalendarType extends Partial<CalendarTypes> {
|
|
7
|
+
palette: Palette
|
|
8
|
+
openCalendar?: boolean
|
|
9
|
+
onSubmit: (val: DateRange) => void
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { DateRange } from 'react-day-picker'
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
onSubmit: (val: any) => void
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const useFilterCalendar = ({ onSubmit }: Props) => {
|
|
9
|
+
const [calendarRange, setCalendarRange] = useState<DateRange | undefined>()
|
|
10
|
+
const [toggleCalendar, setToggleCalendar] = useState<boolean>(false)
|
|
11
|
+
|
|
12
|
+
const handleSubmit = () => {
|
|
13
|
+
return onSubmit(calendarRange)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const handleClearDates = () => {
|
|
17
|
+
setCalendarRange(undefined)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
handleSubmit,
|
|
22
|
+
handleClearDates,
|
|
23
|
+
setToggleCalendar,
|
|
24
|
+
setCalendarRange,
|
|
25
|
+
|
|
26
|
+
calendarRange,
|
|
27
|
+
toggleCalendar,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import './SubmitButton.css'
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
onClick?: () => void
|
|
7
|
+
startIcon?: ReactNode
|
|
8
|
+
label?: string
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const SubmitButton = ({
|
|
13
|
+
onClick,
|
|
14
|
+
startIcon,
|
|
15
|
+
label,
|
|
16
|
+
disabled,
|
|
17
|
+
}: Props) => {
|
|
18
|
+
return (
|
|
19
|
+
<button
|
|
20
|
+
className="will-filter-bar-submit-button"
|
|
21
|
+
onClick={onClick}
|
|
22
|
+
disabled={disabled}
|
|
23
|
+
>
|
|
24
|
+
{startIcon && <span>{startIcon}</span>}
|
|
25
|
+
{label || 'Label'}
|
|
26
|
+
</button>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
.will-calendar-filter-header {
|
|
2
|
-
padding: 15px 0;
|
|
3
|
-
border-bottom: 1px solid var(--will-grey);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.will-calendar-filter-title {
|
|
7
|
-
font-size: 16px;
|
|
8
|
-
text-transform: uppercase;
|
|
9
|
-
margin: 10px 0;
|
|
10
|
-
text-align: left;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
1
|
.will-calendar-filter-container {
|
|
14
2
|
display: flex;
|
|
15
3
|
justify-content: center;
|
|
4
|
+
user-select: none;
|
|
16
5
|
}
|
|
17
6
|
|
|
18
7
|
/* Calendar overrides */
|
|
@@ -1,31 +1,23 @@
|
|
|
1
1
|
import React, { forwardRef, useEffect } from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import { DayPicker } from 'react-day-picker'
|
|
3
3
|
import { addDays, startOfDay } from 'date-fns'
|
|
4
4
|
import { fi, enUS } from 'date-fns/locale'
|
|
5
5
|
import { useMediaQuery } from 'react-responsive'
|
|
6
6
|
|
|
7
|
-
import { CalendarOffset } from '../../FilterBarTypes'
|
|
8
|
-
|
|
9
7
|
import 'react-day-picker/dist/style.css'
|
|
10
8
|
import './Calendar.css'
|
|
9
|
+
import { CalendarTypes } from './CalendarTypes'
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
calendarRange: DateRange | undefined
|
|
14
|
-
setCalendarRange: (range: DateRange | undefined) => void
|
|
15
|
-
calendarOffset?: CalendarOffset
|
|
16
|
-
selectedPath: string
|
|
17
|
-
locale?: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const Calendar = forwardRef<HTMLDivElement, Props>(
|
|
11
|
+
export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
21
12
|
(
|
|
22
13
|
{
|
|
23
14
|
calendarRange,
|
|
24
15
|
setCalendarRange,
|
|
25
16
|
calendarOffset,
|
|
26
17
|
selectedPath,
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
language,
|
|
19
|
+
calendarOffsetGroup,
|
|
20
|
+
}: CalendarTypes,
|
|
29
21
|
ref
|
|
30
22
|
) => {
|
|
31
23
|
const isTablet = useMediaQuery({ maxWidth: 960 })
|
|
@@ -36,11 +28,12 @@ export const Calendar = forwardRef<HTMLDivElement, Props>(
|
|
|
36
28
|
|
|
37
29
|
const today = startOfDay(new Date())
|
|
38
30
|
|
|
39
|
-
const daysToOffsetCalendar =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
31
|
+
const daysToOffsetCalendar =
|
|
32
|
+
calendarOffset && selectedPath
|
|
33
|
+
? Object.entries(calendarOffset)?.find(
|
|
34
|
+
(page) => selectedPath?.substring(1) === page[0]
|
|
35
|
+
)
|
|
36
|
+
: null
|
|
44
37
|
|
|
45
38
|
const disabledDays = [
|
|
46
39
|
{
|
|
@@ -51,6 +44,7 @@ export const Calendar = forwardRef<HTMLDivElement, Props>(
|
|
|
51
44
|
to: addDays(today, -100),
|
|
52
45
|
},
|
|
53
46
|
]
|
|
47
|
+
|
|
54
48
|
const selectedStartDate = calendarRange?.from
|
|
55
49
|
|
|
56
50
|
return (
|
|
@@ -59,7 +53,7 @@ export const Calendar = forwardRef<HTMLDivElement, Props>(
|
|
|
59
53
|
<DayPicker
|
|
60
54
|
id="will-calendar"
|
|
61
55
|
mode="range"
|
|
62
|
-
locale={
|
|
56
|
+
locale={language === 'en' ? enUS : fi}
|
|
63
57
|
numberOfMonths={!isTablet ? 2 : 1}
|
|
64
58
|
weekStartsOn={1}
|
|
65
59
|
selected={calendarRange}
|
|
@@ -72,7 +66,7 @@ export const Calendar = forwardRef<HTMLDivElement, Props>(
|
|
|
72
66
|
}}
|
|
73
67
|
captionLayout="dropdown-buttons"
|
|
74
68
|
defaultMonth={selectedStartDate || disabledDays[0].from}
|
|
75
|
-
disabled={disabledDays}
|
|
69
|
+
disabled={calendarOffsetGroup || disabledDays}
|
|
76
70
|
fromMonth={today}
|
|
77
71
|
/>
|
|
78
72
|
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DateRange } from 'react-day-picker'
|
|
2
|
+
|
|
3
|
+
export type CalendarOffset = {
|
|
4
|
+
[key: string]: number
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type CalendarTypes = {
|
|
8
|
+
calendarRange?: DateRange | undefined
|
|
9
|
+
setCalendarRange: (range: DateRange | undefined) => void
|
|
10
|
+
calendarOffset?: CalendarOffset
|
|
11
|
+
selectedPath?: string
|
|
12
|
+
language?: string
|
|
13
|
+
calendarOffsetGroup?: {
|
|
14
|
+
from: Date
|
|
15
|
+
to: Date
|
|
16
|
+
}[]
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
export const useAwaitRender = () => {
|
|
4
|
+
const [initialRenderComplete, setInitialRenderComplete] =
|
|
5
|
+
useState<boolean>(false)
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
setInitialRenderComplete(true)
|
|
9
|
+
}, [])
|
|
10
|
+
|
|
11
|
+
if (!initialRenderComplete) return null
|
|
12
|
+
}
|