Skip to content

Commit 979fdff

Browse files
authored
Merge pull request #4054 from IntersectMBO/develop
v2.0.35.1
2 parents b16d941 + d01c5ca commit 979fdff

File tree

2 files changed

+211
-102
lines changed

2 files changed

+211
-102
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import * as React from "react";
2+
import { Chip, ChipProps, IconButton } from "@mui/material";
3+
import { IconX } from "@intersect.mbo/intersectmbo.org-icons-set";
4+
5+
interface ChipButtonProps
6+
extends Omit<ChipProps, "color" | "variant" | "deleteIcon"> {
7+
label: React.ReactNode;
8+
onDelete: () => void;
9+
bgColor?: string;
10+
deleteIconPosition?: "left" | "right";
11+
iconSize?: number;
12+
testId?: string;
13+
}
14+
15+
const ChipButton: React.FC<ChipButtonProps> = ({
16+
label,
17+
onDelete,
18+
bgColor = "#B9CCF5",
19+
deleteIconPosition = "left",
20+
iconSize = 14,
21+
testId,
22+
sx,
23+
...rest
24+
}) => (
25+
<Chip
26+
{...rest}
27+
label={label}
28+
onDelete={onDelete}
29+
data-testid={testId}
30+
deleteIcon={
31+
<IconButton
32+
disableRipple
33+
sx={{ p: "4px", "&:hover": { backgroundColor: "transparent" } }}
34+
>
35+
<IconX style={{ width: iconSize, height: iconSize, color: "#222" }} />
36+
</IconButton>
37+
}
38+
sx={{
39+
backgroundColor: bgColor,
40+
borderRadius: 999,
41+
height: "auto",
42+
py: 0.75,
43+
pl: 1.75,
44+
pr: 2.25,
45+
display: "flex",
46+
flexDirection: deleteIconPosition === "right" ? "row" : "row-reverse",
47+
gap: 0.5,
48+
"& .MuiChip-label": {
49+
fontSize: 12,
50+
fontWeight: 400,
51+
color: "#000",
52+
whiteSpace: "nowrap",
53+
overflow: "hidden",
54+
textOverflow: "ellipsis",
55+
px: 0,
56+
py: 0,
57+
},
58+
"& .MuiChip-deleteIcon": { m: 0 },
59+
...(sx as object),
60+
}}
61+
/>
62+
);
63+
64+
export default ChipButton;
Lines changed: 147 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
1-
import { Dispatch, FC, SetStateAction } from "react";
1+
import { Dispatch, FC, SetStateAction, useMemo, useState } from "react";
22
import { Box, InputBase, IconButton } from "@mui/material";
33
import Search from "@mui/icons-material/Search";
44
import CloseIcon from "@mui/icons-material/Close";
55

66
import { DataActionsFilters, DataActionsSorting } from "@molecules";
77
import { OrderActionsChip } from "./OrderActionsChip";
8-
import { theme } from "@/theme";
8+
import ChipButton from "../atoms/ChipButton";
99

1010
type DataActionsBarProps = {
1111
chosenFilters?: string[];
1212
chosenFiltersLength?: number;
1313
chosenSorting: string;
1414
closeFilters?: () => void;
1515
closeSorts: () => void;
16-
filterOptions?: {
17-
key: string;
18-
label: string;
19-
}[];
16+
filterOptions?: { key: string; label: string }[];
2017
filtersOpen?: boolean;
2118
filtersTitle?: string;
2219
isFiltering?: boolean;
@@ -26,107 +23,155 @@ type DataActionsBarProps = {
2623
setChosenSorting: Dispatch<SetStateAction<string>>;
2724
setFiltersOpen?: Dispatch<SetStateAction<boolean>>;
2825
setSearchText: Dispatch<SetStateAction<string>>;
29-
setSortOpen: Dispatch<SetStateAction<boolean>>;
30-
sortOpen: boolean;
31-
sortOptions?: {
32-
key: string;
33-
label: string;
34-
}[];
26+
setSortOpen?: Dispatch<SetStateAction<boolean>>;
27+
sortOpen?: boolean;
28+
sortOptions?: { key: string; label: string }[];
3529
};
3630

37-
export const DataActionsBar: FC<DataActionsBarProps> = ({ ...props }) => {
38-
const {
39-
chosenFilters = [],
40-
chosenFiltersLength,
41-
chosenSorting,
42-
closeFilters = () => {},
43-
closeSorts,
44-
filterOptions = [],
45-
filtersOpen,
46-
filtersTitle,
47-
isFiltering = true,
48-
searchText,
49-
setChosenFilters = () => {},
50-
setChosenSorting,
51-
setFiltersOpen,
52-
setSearchText,
53-
setSortOpen,
54-
sortOpen,
55-
sortOptions = [],
56-
placeholder = "Search...",
57-
} = props;
58-
const {
59-
palette: { boxShadow2 },
60-
} = theme;
31+
export const DataActionsBar: FC<DataActionsBarProps> = ({
32+
chosenFilters = [],
33+
chosenFiltersLength,
34+
chosenSorting,
35+
closeFilters = () => {},
36+
closeSorts,
37+
filterOptions = [],
38+
filtersOpen,
39+
filtersTitle,
40+
isFiltering = true,
41+
searchText,
42+
setChosenFilters = () => {},
43+
setChosenSorting,
44+
setFiltersOpen,
45+
setSearchText,
46+
setSortOpen,
47+
sortOpen,
48+
sortOptions = [],
49+
placeholder = "Search...",
50+
}) => {
51+
const [localFiltersOpen, setLocalFiltersOpen] = useState(false);
52+
const [localSortOpen, setLocalSortOpen] = useState(false);
53+
54+
const effectiveFiltersOpen = filtersOpen ?? localFiltersOpen;
55+
const effectiveSortOpen = sortOpen ?? localSortOpen;
56+
const setEffectiveFiltersOpen = setFiltersOpen ?? setLocalFiltersOpen;
57+
const setEffectiveSortOpen = setSortOpen ?? setLocalSortOpen;
58+
59+
const selectedFilterItems = useMemo(
60+
() =>
61+
(chosenFilters ?? []).map((key) => ({
62+
key,
63+
label: (filterOptions ?? []).find((o) => o.key === key)?.label ?? key,
64+
})),
65+
[chosenFilters, filterOptions],
66+
);
67+
68+
const handleRemoveFilter = (key: string) =>
69+
setChosenFilters?.((prev) => (prev ?? []).filter((k) => k !== key));
6170

6271
return (
63-
<Box alignItems="center" display="flex" justifyContent="space-between">
64-
<InputBase
65-
inputProps={{ "data-testid": "search-input" }}
66-
onChange={(e) => setSearchText(e.target.value)}
67-
placeholder={placeholder}
68-
value={searchText}
69-
startAdornment={
70-
<Search
71-
style={{
72-
color: "#99ADDE",
73-
height: 16,
74-
marginRight: 4,
75-
width: 16,
76-
}}
77-
/>
78-
}
79-
endAdornment={
80-
searchText && (
81-
<IconButton
82-
size="small"
83-
onClick={() => setSearchText("")}
84-
sx={{ ml: 1 }}
85-
>
86-
<CloseIcon fontSize="small" />
87-
</IconButton>
88-
)
89-
}
90-
sx={{
91-
bgcolor: "white",
92-
border: 1,
93-
borderColor: "secondaryBlue",
94-
borderRadius: 50,
95-
boxShadow: `2px 2px 20px 0px ${boxShadow2}`,
96-
fontSize: 11,
97-
fontWeight: 500,
98-
height: 48,
99-
padding: "16px 24px",
100-
maxWidth: 500,
101-
}}
102-
/>
103-
<OrderActionsChip
104-
chosenFiltersLength={chosenFiltersLength}
105-
filtersOpen={filtersOpen}
106-
isFiltering={isFiltering}
107-
setFiltersOpen={setFiltersOpen}
108-
chosenSorting={chosenSorting}
109-
setSortOpen={setSortOpen}
110-
sortOpen={sortOpen}
72+
<Box display="flex" flexDirection="column" gap={1.5}>
73+
<Box
74+
alignItems="center"
75+
display="flex"
76+
justifyContent="space-between"
77+
gap={1.5}
78+
flexWrap="wrap"
11179
>
112-
{filtersOpen && (
113-
<DataActionsFilters
114-
chosenFilters={chosenFilters}
115-
setChosenFilters={setChosenFilters}
116-
closeFilters={closeFilters}
117-
options={filterOptions}
118-
title={filtersTitle}
119-
/>
120-
)}
121-
{sortOpen && (
122-
<DataActionsSorting
123-
chosenSorting={chosenSorting}
124-
setChosenSorting={setChosenSorting}
125-
closeSorts={closeSorts}
126-
options={sortOptions}
127-
/>
128-
)}
129-
</OrderActionsChip>
80+
<InputBase
81+
inputProps={{ "data-testid": "search-input" }}
82+
onChange={(e) => setSearchText(e.target.value)}
83+
placeholder={placeholder}
84+
value={searchText}
85+
startAdornment={
86+
<Search
87+
style={{
88+
color: "#99ADDE",
89+
height: 16,
90+
marginRight: 4,
91+
width: 16,
92+
}}
93+
/>
94+
}
95+
endAdornment={
96+
searchText && (
97+
<IconButton
98+
size="small"
99+
onClick={() => setSearchText("")}
100+
sx={{ ml: 1 }}
101+
>
102+
<CloseIcon fontSize="small" />
103+
</IconButton>
104+
)
105+
}
106+
sx={{
107+
bgcolor: "white",
108+
border: 1,
109+
borderColor: "#6E87D9",
110+
borderRadius: 50,
111+
boxShadow: "2px 2px 20px 0 rgba(0,0,0,0.05)",
112+
fontSize: 11,
113+
fontWeight: 500,
114+
height: 48,
115+
padding: "16px 24px",
116+
maxWidth: 500,
117+
flex: "0 0 auto",
118+
}}
119+
/>
120+
121+
<OrderActionsChip
122+
chosenFiltersLength={chosenFiltersLength}
123+
filtersOpen={effectiveFiltersOpen}
124+
isFiltering={isFiltering}
125+
setFiltersOpen={setEffectiveFiltersOpen}
126+
chosenSorting={chosenSorting}
127+
setSortOpen={setEffectiveSortOpen}
128+
sortOpen={effectiveSortOpen}
129+
>
130+
{effectiveFiltersOpen && (
131+
<DataActionsFilters
132+
chosenFilters={chosenFilters}
133+
setChosenFilters={setChosenFilters}
134+
closeFilters={closeFilters}
135+
options={filterOptions}
136+
title={filtersTitle}
137+
/>
138+
)}
139+
{effectiveSortOpen && (
140+
<DataActionsSorting
141+
chosenSorting={chosenSorting}
142+
setChosenSorting={setChosenSorting}
143+
closeSorts={closeSorts}
144+
options={sortOptions}
145+
/>
146+
)}
147+
</OrderActionsChip>
148+
</Box>
149+
150+
{selectedFilterItems.length > 0 && (
151+
<Box
152+
display="flex"
153+
flexWrap="wrap"
154+
gap={1}
155+
alignItems="flex-start"
156+
sx={{
157+
mt: 2,
158+
"& > *": { flex: "0 0 auto", alignSelf: "flex-start" },
159+
}}
160+
>
161+
{selectedFilterItems.map(({ key, label }) => (
162+
<ChipButton
163+
key={key}
164+
label={label}
165+
onDelete={() => handleRemoveFilter(key)}
166+
deleteIconPosition="left"
167+
bgColor="#B9CCF5"
168+
size="small"
169+
/>
170+
))}
171+
</Box>
172+
)}
130173
</Box>
131174
);
132175
};
176+
177+
export default DataActionsBar;

0 commit comments

Comments
 (0)