willba-component-library 0.0.25 → 0.0.27
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 -0
- package/lib/components/FilterBar/FilterBar.stories.d.ts +6 -0
- package/lib/components/FilterBar/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/FilterBar/FilterBar.css +131 -0
- package/src/components/FilterBar/FilterBar.stories.tsx +20 -0
- package/src/components/FilterBar/FilterBar.tsx +183 -0
- package/src/components/FilterBar/index.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./FilterBar";
|
package/package.json
CHANGED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/* Structure ---------------------------- */
|
|
2
|
+
|
|
3
|
+
.root {
|
|
4
|
+
width: 100%;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.search-widget {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
max-width: 1100px;
|
|
10
|
+
position: relative;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.search-widget-header {
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
align-items: center;
|
|
17
|
+
padding: 10px 20px;
|
|
18
|
+
position: relative;
|
|
19
|
+
z-index: 222;
|
|
20
|
+
|
|
21
|
+
border-radius: 40px;
|
|
22
|
+
background-color: #ecf1f4;
|
|
23
|
+
box-shadow: 0px 6px 11px 0px #a7a4a480;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.search-widget-container {
|
|
27
|
+
background-color: #ecf1f4;
|
|
28
|
+
min-height: 100px;
|
|
29
|
+
|
|
30
|
+
padding: 90px 40px 30px 40px;
|
|
31
|
+
position: absolute;
|
|
32
|
+
top: 0;
|
|
33
|
+
z-index: 111;
|
|
34
|
+
border-radius: 40px;
|
|
35
|
+
width: -webkit-fill-available;
|
|
36
|
+
box-shadow: 0px 6px 11px 0px #a7a4a480;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.search-widget-divider {
|
|
40
|
+
width: 1px;
|
|
41
|
+
margin: 0 10px;
|
|
42
|
+
height: 35px;
|
|
43
|
+
background-color: #384265;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.search-widget-submit-button {
|
|
47
|
+
width: auto;
|
|
48
|
+
height: auto;
|
|
49
|
+
background-color: #384265;
|
|
50
|
+
color: #fff;
|
|
51
|
+
padding: 10px 20px;
|
|
52
|
+
border-radius: 20px;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
border: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.search-widget-select-button {
|
|
58
|
+
width: auto;
|
|
59
|
+
height: auto;
|
|
60
|
+
background-color: transparent;
|
|
61
|
+
border: none;
|
|
62
|
+
padding: 10px 20px;
|
|
63
|
+
border-radius: 20px;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Filters - Guests ---------------------------- */
|
|
68
|
+
|
|
69
|
+
.search-widget-guests {
|
|
70
|
+
text-align: initial;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.guests-filter-container {
|
|
74
|
+
display: flex;
|
|
75
|
+
margin-top: 30px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.guests-filter-inner {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.guests-filter-inner:not(:last-child) {
|
|
84
|
+
margin-right: 50px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.guests-filter-inner > span {
|
|
88
|
+
display: block;
|
|
89
|
+
margin-right: 20px;
|
|
90
|
+
font-weight: bold;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.guests-filter-inner > div {
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.guests-filter-inner > div > span {
|
|
99
|
+
margin: 0 10px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.guests-filter-inner > div button {
|
|
103
|
+
border-radius: 50%;
|
|
104
|
+
border: none;
|
|
105
|
+
background-color: #CDEEFF;
|
|
106
|
+
width: 25px;
|
|
107
|
+
height: 25px;
|
|
108
|
+
display: flex;
|
|
109
|
+
justify-content: center;
|
|
110
|
+
align-items: center;
|
|
111
|
+
font-size: 20px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Filters - Categories ---------------------------- */
|
|
115
|
+
|
|
116
|
+
.search-widget-categories {
|
|
117
|
+
text-align: center;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.categories-filter-inner {
|
|
121
|
+
display: flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
justify-content: center;
|
|
124
|
+
gap: 20px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.categories-filter-inner input {
|
|
128
|
+
cursor: pointer;
|
|
129
|
+
margin-right: 10px;
|
|
130
|
+
}
|
|
131
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import FilterBar from "./FilterBar";
|
|
4
|
+
|
|
5
|
+
// Default metadata of the story https://storybook.js.org/docs/react/api/csf#default-export
|
|
6
|
+
const meta: Meta<typeof FilterBar> = {
|
|
7
|
+
title: "Components/FilterBar",
|
|
8
|
+
component: FilterBar,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
// The story type for the component https://storybook.js.org/docs/react/api/csf#named-story-exports
|
|
14
|
+
type Story = StoryObj<typeof FilterBar>;
|
|
15
|
+
|
|
16
|
+
export const Primary: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
label: "Primary 😃",
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import "./FilterBar.css";
|
|
3
|
+
|
|
4
|
+
export default function FilterBar() {
|
|
5
|
+
const [selectedFilter, setSelectedFilter] = useState<number | boolean>(false);
|
|
6
|
+
// const [startDate, setStartDate] = useState(0);
|
|
7
|
+
// const [endDate, setEndDate] = useState(0);
|
|
8
|
+
const [guestsAdults, setGuestsAdults] = useState(0);
|
|
9
|
+
const [guestsKids, setGuestsKids] = useState(0);
|
|
10
|
+
const [categories, setCategories] = useState(0);
|
|
11
|
+
|
|
12
|
+
const handleSelectedFilter = (id: any) => {
|
|
13
|
+
setSelectedFilter(id);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const handleSubmit = () => {
|
|
17
|
+
const queryParams = new URLSearchParams();
|
|
18
|
+
|
|
19
|
+
const params = {
|
|
20
|
+
// startDate,
|
|
21
|
+
// endDate,
|
|
22
|
+
guestsAdults,
|
|
23
|
+
guestsKids,
|
|
24
|
+
categories,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
for (const [key, value] of Object.entries(params)) {
|
|
28
|
+
if (value) {
|
|
29
|
+
queryParams.append(key, value.toString());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const url = `http://localhost:4000/en/events/?${queryParams.toString()}`;
|
|
34
|
+
window.location.href = url;
|
|
35
|
+
handleSelectedFilter(false);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className="search-widget">
|
|
40
|
+
<div className="search-widget-header">
|
|
41
|
+
<SelectButton
|
|
42
|
+
label="Start date"
|
|
43
|
+
onClick={() => handleSelectedFilter(1)}
|
|
44
|
+
/>
|
|
45
|
+
<Divider />
|
|
46
|
+
<SelectButton
|
|
47
|
+
label="End date"
|
|
48
|
+
onClick={() => handleSelectedFilter(2)}
|
|
49
|
+
/>
|
|
50
|
+
<Divider />
|
|
51
|
+
<SelectButton label="Guests" onClick={() => handleSelectedFilter(3)} />
|
|
52
|
+
<Divider />
|
|
53
|
+
<SelectButton
|
|
54
|
+
label="Categories"
|
|
55
|
+
onClick={() => handleSelectedFilter(4)}
|
|
56
|
+
/>
|
|
57
|
+
<SubmitButton onClick={handleSubmit} />
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
{selectedFilter && (
|
|
61
|
+
<div className="search-widget-container">
|
|
62
|
+
{selectedFilter === 1 && <StartDate />}
|
|
63
|
+
{selectedFilter === 2 && <EndDate />}
|
|
64
|
+
{selectedFilter === 3 && (
|
|
65
|
+
<Guests
|
|
66
|
+
guestsAdults={guestsAdults}
|
|
67
|
+
guestsKids={guestsKids}
|
|
68
|
+
decrementAdults={() => setGuestsAdults(guestsAdults - 1)}
|
|
69
|
+
incrementAdults={() => setGuestsAdults(guestsAdults + 1)}
|
|
70
|
+
decrementKids={() => setGuestsKids(guestsKids - 1)}
|
|
71
|
+
incrementKids={() => setGuestsKids(guestsKids + 1)}
|
|
72
|
+
/>
|
|
73
|
+
)}
|
|
74
|
+
{selectedFilter === 4 && (
|
|
75
|
+
<Categories categories={categories} setCategories={setCategories} />
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const Divider = () => {
|
|
84
|
+
return <div className="search-widget-divider" />;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const SubmitButton = ({ onClick }: any) => {
|
|
88
|
+
return (
|
|
89
|
+
<button className="search-widget-submit-button" onClick={onClick}>
|
|
90
|
+
Apply filters
|
|
91
|
+
</button>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const SelectButton = ({ label, onClick }: any) => {
|
|
96
|
+
return (
|
|
97
|
+
<button className="search-widget-select-button" onClick={onClick}>
|
|
98
|
+
{label}
|
|
99
|
+
</button>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const StartDate = () => {
|
|
104
|
+
return <div>Start date</div>;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const EndDate = () => {
|
|
108
|
+
return <div>End date</div>;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const Guests = ({
|
|
112
|
+
guestsAdults,
|
|
113
|
+
guestsKids,
|
|
114
|
+
decrementAdults,
|
|
115
|
+
incrementAdults,
|
|
116
|
+
decrementKids,
|
|
117
|
+
incrementKids,
|
|
118
|
+
}: any) => {
|
|
119
|
+
return (
|
|
120
|
+
<div className="search-widget-guests">
|
|
121
|
+
<h3>Guests</h3>
|
|
122
|
+
<p>Who's coming?</p>
|
|
123
|
+
|
|
124
|
+
<div className="guests-filter-container">
|
|
125
|
+
<div className="guests-filter-inner">
|
|
126
|
+
<span>Adults</span>
|
|
127
|
+
<div>
|
|
128
|
+
<button onClick={decrementAdults} disabled={guestsAdults < 1}>
|
|
129
|
+
-
|
|
130
|
+
</button>
|
|
131
|
+
<span>{guestsAdults}</span>
|
|
132
|
+
<button onClick={incrementAdults}>+</button>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
<div className="guests-filter-inner">
|
|
136
|
+
<span>Kids</span>
|
|
137
|
+
<div>
|
|
138
|
+
<button onClick={decrementKids} disabled={guestsKids < 1}>
|
|
139
|
+
-
|
|
140
|
+
</button>
|
|
141
|
+
<span>{guestsKids}</span>
|
|
142
|
+
<button onClick={incrementKids}>+</button>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const Categories = ({ categories, setCategories }: any) => {
|
|
151
|
+
const categoriesPlaceholder = [
|
|
152
|
+
"Weekend",
|
|
153
|
+
"Week",
|
|
154
|
+
"Summer camp",
|
|
155
|
+
"Winter camp",
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
const [selectedCategory, setSelectedCategory] = useState("");
|
|
159
|
+
|
|
160
|
+
const handleCategoryChange = (selectedCategory: any) => {
|
|
161
|
+
setSelectedCategory(selectedCategory);
|
|
162
|
+
setCategories(selectedCategory); // Update the parent component's state with the selected category
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<div className="search-widget-categories">
|
|
167
|
+
<h3>CATEGORY</h3>
|
|
168
|
+
<div className="categories-filter-inner">
|
|
169
|
+
{categoriesPlaceholder.map((itm, idx) => (
|
|
170
|
+
<div key={idx}>
|
|
171
|
+
<input
|
|
172
|
+
type="radio"
|
|
173
|
+
value={itm}
|
|
174
|
+
checked={selectedCategory === itm}
|
|
175
|
+
onChange={() => handleCategoryChange(itm)}
|
|
176
|
+
/>
|
|
177
|
+
<span>{itm}</span>
|
|
178
|
+
</div>
|
|
179
|
+
))}
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./FilterBar";
|