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(() => { useEffect(() => {
if (selected && !isHover) { if (selected && !isHover) {
console.log(selected, ref.current);
ref.current?.scrollIntoView({ behavior: "smooth", block: "center" }); ref.current?.scrollIntoView({ behavior: "smooth", block: "center" });
} }
}, [isHover, selected]); }, [isHover, selected]);

View File

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