Skip to content

Commit

Permalink
Migrate checkbox multilists to custom Chakra components
Browse files Browse the repository at this point in the history
  • Loading branch information
IAmVisco committed Jul 24, 2022
1 parent fdfa350 commit 708ed54
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 26 deletions.
74 changes: 74 additions & 0 deletions src/components/search/CheckboxSearchList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Checkbox, CheckboxGroup, Input, VStack } from "@chakra-ui/react";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";

interface MultiSearchProps {
dataField: string;
placeholder?: string;
showSearch?: boolean;
aggregations: {
[k: string]: { buckets: Array<{ key: string; doc_count: number }> };
};
setQuery: (query: any) => void;
}

export const CheckboxSearchList = ({
dataField,
placeholder,
showSearch = false,
aggregations,
setQuery,
}: MultiSearchProps) => {
const { t } = useTranslation();
const [filterValue, setFilterValue] = useState("");
const [checkboxValues, setCheckboxValues] = useState<Array<string | number>>(
[],
);

const getChannelsQuery = useCallback(
(values: typeof checkboxValues) => {
if (!values?.length) return {};

return {
query: { terms: { [dataField]: values } },
};
},
[dataField],
);

useEffect(() => {
setQuery({
value: checkboxValues,
query: getChannelsQuery(checkboxValues),
});
}, [checkboxValues, getChannelsQuery, setQuery]);

return (
<>
{showSearch && (
<Input
value={filterValue}
onChange={(e) => setFilterValue(e.target.value)}
placeholder={t(placeholder!)}
/>
)}
<CheckboxGroup
onChange={(e) => {
setCheckboxValues(e);
}}
>
<VStack maxH="200px" alignItems="stretch" overflowY="scroll" p={2}>
{aggregations?.[dataField]?.buckets
?.filter(({ key }) =>
key.toLowerCase().includes(filterValue.toLowerCase()),
)
.map(({ key }) => (
<Checkbox key={key} value={key}>
{key}
</Checkbox>
))}
</VStack>
</CheckboxGroup>
</>
);
};
92 changes: 66 additions & 26 deletions src/pages/Search.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
DataSearch,
MultiList,
ReactiveBase,
ReactiveComponent,
Expand All @@ -22,10 +21,12 @@ import {
VStack,
} from "@chakra-ui/react";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useSearchParams } from "react-router-dom";
import { SongTable, SongTableCol } from "../components/data/SongTable";
import "./Search.css";
import { GeneralSearchInput } from "../components/search/GeneralSearchInput";
import { CheckboxSearchList } from "../components/search/CheckboxSearchList";

const debounceValue = 1000;

Expand Down Expand Up @@ -65,6 +66,7 @@ const SearchResultSongTable = ({
};

export default function Search() {
const { t } = useTranslation();
const [suborgVisible, setSuborgVisible] = useState(false);
const flexWrap: "nowrap" | "wrap" | undefined = useBreakpointValue({
base: "wrap",
Expand Down Expand Up @@ -134,6 +136,7 @@ export default function Search() {
},
};
}, []);

return (
<ReactiveBase
className="m-search"
Expand Down Expand Up @@ -180,7 +183,7 @@ export default function Search() {
<AccordionItem>
<AccordionButton>
<Heading flex="1" textAlign="center" size="sm">
Advanced Filters
{t("Advanced Filters")}
</Heading>
<AccordionIcon />
</AccordionButton>
Expand All @@ -201,7 +204,7 @@ export default function Search() {
/>

<Tag colorScheme="brand" size="md" alignSelf="start">
Song
{t("Song")}
</Tag>
<ReactiveComponent
componentId="song"
Expand All @@ -220,13 +223,13 @@ export default function Search() {
onError={(e) => console.log(e)}
/>
<Tag colorScheme="brand" size="md" alignSelf="start">
Artist
{t("Artist")}
</Tag>
<ReactiveComponent
componentId="artist"
URLParams
filterLabel="Original Artist"
customQuery={getSongQuery}
customQuery={getArtistQuery}
render={(props) => (
<GeneralSearchInput
initialState={searchParams.get("artist")}
Expand All @@ -239,20 +242,37 @@ export default function Search() {
onError={(e) => console.log(e)}
/>

<MultiList
className="input-fix"
<Tag colorScheme="brand" size="md" alignSelf="start">
{t("Channel")}
</Tag>
<ReactiveComponent
componentId="ch"
dataField="channel.name"
filterLabel="Channel"
title="Filter by Channel"
URLParams
react={{ and: ["q", "song", "artist", "isMv", "org"] }}
showSearch
onValueChange={(e) => {
setChannelSelected(e && e.length > 0);
defaultQuery={() => ({
aggs: {
"channel.name": {
terms: {
field: "channel.name",
size: 12,
order: { _count: "desc" },
},
},
},
})}
render={(props) => {
setChannelSelected(props.value?.length > 0);
return (
<CheckboxSearchList
dataField="channel.name"
placeholder="Channel name"
showSearch
{...props}
/>
);
}}
URLParams
size={12}
showCheckbox
onError={(e) => console.log(e)}
/>
{!channelSelected && (
<SingleList
Expand All @@ -269,17 +289,37 @@ export default function Search() {
/>
)}
{suborgVisible && !channelSelected && (
<MultiList
componentId="suborg"
dataField="suborg"
filterLabel="Suborg"
title="Filter by Suborg"
showCheckbox
showSearch={false}
queryFormat="and"
react={{ and: ["q", "org", "song", "artist", "isMv"] }}
URLParams
/>
<>
<Tag colorScheme="brand" size="md" alignSelf="start">
{t("Suborg")}
</Tag>
<ReactiveComponent
componentId="suborg"
filterLabel="Suborg"
URLParams
react={{ and: ["q", "song", "artist", "isMv", "org"] }}
defaultQuery={() => ({
aggs: {
suborg: {
terms: {
field: "suborg",
order: { _count: "desc" },
},
},
},
})}
render={(props) => {
return (
<CheckboxSearchList
dataField="suborg"
placeholder="Suborg name"
{...props}
/>
);
}}
onError={(e) => console.log(e)}
/>
</>
)}
</VStack>
</AccordionPanel>
Expand Down

0 comments on commit 708ed54

Please sign in to comment.