feat: add search modal filter with persistence

This commit is contained in:
Sonny
2023-05-17 20:19:11 +02:00
parent f6ef55ace0
commit 69b34e824f
4 changed files with 75 additions and 17 deletions

View File

@@ -28,7 +28,6 @@ export default function SearchListItem({
useEffect(() => {
if (selected && !isHover) {
console.log(selected, ref.current);
ref.current?.scrollIntoView({ behavior: "smooth", block: "center" });
}
}, [isHover, selected]);

View File

@@ -12,6 +12,7 @@ import SearchList from "./SearchList";
import * as Keys from "constants/keys";
import { GOOGLE_SEARCH_URL } from "constants/search-urls";
import { Category, SearchItem } from "types";
import { useLocalStorage } from "hooks/useLocalStorage";
import styles from "./search.module.scss";
@@ -28,9 +29,14 @@ export default function SearchModal({
}) {
const autoFocusRef = useAutoFocus();
// TODO: peristance
const [canSearchLink, setCanSearchLink] = useState<boolean>(true);
const [canSearchCategory, setCanSearchCategory] = useState<boolean>(true);
const [canSearchLink, setCanSearchLink] = useLocalStorage(
"search-link",
true
);
const [canSearchCategory, setCanSearchCategory] = useLocalStorage(
"search-category",
false
);
const [search, setSearch] = useState<string>("");
const [cursor, setCursor] = useState<number>(0);
@@ -41,12 +47,15 @@ export default function SearchModal({
() =>
search.length === 0
? []
: items.filter((item) =>
item.name
.toLocaleLowerCase()
.includes(search.toLocaleLowerCase().trim())
: items.filter(
(item) =>
((item.type === "category" && canSearchCategory) ||
(item.type === "link" && canSearchLink)) &&
item.name
.toLocaleLowerCase()
.includes(search.toLocaleLowerCase().trim())
),
[items, search]
[canSearchCategory, canSearchLink, items, search]
);
useHotkeys(Keys.ARROW_UP, () => setCursor((cursor) => (cursor -= 1)), {
@@ -65,6 +74,14 @@ export default function SearchModal({
setSearch(value);
setCursor(0);
}, []);
const handleCanSearchLink = (checked: boolean) => {
setCanSearchLink(checked);
setCursor(0);
};
const handleCanSearchCategory = (checked: boolean) => {
setCanSearchCategory(checked);
setCursor(0);
};
const handleSubmit = useCallback(
(event: FormEvent<HTMLFormElement>) => {
@@ -108,18 +125,13 @@ export default function SearchModal({
</div>
<SearchFilter
canSearchLink={canSearchLink}
setCanSearchLink={setCanSearchLink}
setCanSearchLink={handleCanSearchLink}
canSearchCategory={canSearchCategory}
setCanSearchCategory={setCanSearchCategory}
setCanSearchCategory={handleCanSearchCategory}
/>
{search.length > 0 && (
<SearchList
items={itemsCompletion.map((item) => ({
id: item.id,
name: item.name,
url: item.url,
type: item.type,
}))}
items={itemsCompletion}
noItem={<LabelSearchWithGoogle />}
cursor={cursor}
setCursor={setCursor}

View File

@@ -0,0 +1,30 @@
import { useState } from "react";
export function useLocalStorage(key: string, initialValue: any) {
const [storedValue, setStoredValue] = useState(() => {
if (typeof window === "undefined") {
return initialValue;
}
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.log(error);
return initialValue;
}
});
const setValue = (value: any) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
if (typeof window !== "undefined") {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue];
}

17
src/utils/array.ts Normal file
View File

@@ -0,0 +1,17 @@
export function groupItemBy(array: any[], property: string) {
const hash = {};
const props = property.split(".");
for (const item of array) {
const key = props.reduce((acc, prop) => acc && acc[prop], item);
const hashKey = key !== undefined ? key : "catégories";
if (!hash[hashKey]) {
hash[hashKey] = [];
}
hash[hashKey].push(item);
}
return hash;
}