mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-08 22:53:25 +00:00
feat: add search modal filter with persistence
This commit is contained in:
@@ -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]);
|
||||
|
||||
@@ -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}
|
||||
|
||||
30
src/hooks/useLocalStorage.tsx
Normal file
30
src/hooks/useLocalStorage.tsx
Normal 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
17
src/utils/array.ts
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user