From c23994091bb2a622edb2a2257bcce05a25b93c0b Mon Sep 17 00:00:00 2001 From: b1ek Date: Mon, 11 Nov 2024 21:17:21 +1000 Subject: [PATCH] add search bar --- front/package.json | 1 + .../components/display/SearchBar.module.scss | 24 ++++++++++++++ front/src/components/display/SearchBar.tsx | 27 +++++++++++++++ front/src/components/display/SearchIcon.tsx | 9 +++++ front/src/pages/index.tsx | 33 +++++++++++++++---- front/yarn.lock | 5 +++ 6 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 front/src/components/display/SearchBar.module.scss create mode 100644 front/src/components/display/SearchBar.tsx create mode 100644 front/src/components/display/SearchIcon.tsx diff --git a/front/package.json b/front/package.json index 09d1c21..5df741f 100644 --- a/front/package.json +++ b/front/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "delay": "^6.0.0", "ky": "^1.7.2", "preact": "^10.24.3", "react-draggable-list": "^4.2.1", diff --git a/front/src/components/display/SearchBar.module.scss b/front/src/components/display/SearchBar.module.scss new file mode 100644 index 0000000..52918c4 --- /dev/null +++ b/front/src/components/display/SearchBar.module.scss @@ -0,0 +1,24 @@ +.search { + margin: 1rem 0; + + border: 1px solid gray; + + display: flex; + + * { + padding: 1rem; + } + + input { + border: none; + background: none; + height: 100%; width: 100%; + } + + button { + cursor: pointer; + color: white; + background: royalblue; + border: none; + } +} \ No newline at end of file diff --git a/front/src/components/display/SearchBar.tsx b/front/src/components/display/SearchBar.tsx new file mode 100644 index 0000000..41a0610 --- /dev/null +++ b/front/src/components/display/SearchBar.tsx @@ -0,0 +1,27 @@ +import { useState } from "preact/hooks"; +import styles from './SearchBar.module.scss'; +import { SearchIcon } from "./SearchIcon"; +import { TargetedEvent } from "preact/compat"; + +export type SearchBarProps = { + default?: string, + placeholder?: string, + onChange?: (data: string) => void, + onSearch?: (data: string) => void +}; +export function SearchBar({ default: def, placeholder, onChange, onSearch }: SearchBarProps) { + const [ query, setQuery ] = useState(def ?? ''); + + function updateValue(e: TargetedEvent) { + setQuery(e.currentTarget.value); + if (onChange) onChange(e.currentTarget.value); + } + + return ( +
+ + + +
+ ) +} \ No newline at end of file diff --git a/front/src/components/display/SearchIcon.tsx b/front/src/components/display/SearchIcon.tsx new file mode 100644 index 0000000..08d2395 --- /dev/null +++ b/front/src/components/display/SearchIcon.tsx @@ -0,0 +1,9 @@ +import type React from "preact/compat"; + +export function SearchIcon(props: React.JSX.SVGAttributes) { + return ( + + + + ) +} \ No newline at end of file diff --git a/front/src/pages/index.tsx b/front/src/pages/index.tsx index 3d98473..5797d87 100644 --- a/front/src/pages/index.tsx +++ b/front/src/pages/index.tsx @@ -1,11 +1,13 @@ import { useCallback, useEffect, useState } from "preact/hooks"; -import { DataRow } from "../api/DataRow"; +import { DataRow, DataRowSearchOptions } from "../api/DataRow"; import style from './index.module.scss'; import { Posts } from "../components/Posts"; import InfiniteScroller from 'react-infinite-scroller'; import { DraggablePostsList } from "../components/DraggablePostsList"; import { DataRowSelection } from "../api/DataRowSelection"; +import { SearchBar } from "../components/display/SearchBar"; +import delay from "delay"; export function Index() { const [ data, setData ] = useState(null as null | DataRow[]); @@ -15,6 +17,8 @@ export function Index() { const [ hasMore, setHasMore ] = useState(true); const [ fetching, setFetching ] = useState(false); + const [ filter, setFilter ] = useState(null as null | string); + useEffect(() => { (async () => { setSelected(await dataRowSelection.get()); @@ -22,14 +26,17 @@ export function Index() { }, []); const fetchMore = useCallback( - async function(_page: number) { + async function() { if (fetching) return; setFetching(true); - // await new Promise(r => setTimeout(r, 1000)); - const newData = await DataRow.find({ - page: data ? Math.floor(data.length / 20) : 0 - }); + + const query = { + page: data ? Math.floor(data.length / 20) : 0, + } as DataRowSearchOptions; + if (filter) query.search = `%${filter}%`; + + const newData = await DataRow.find(query); setData([ ...data ?? [], ...newData ]); setHasMore(newData.length === 20); setFetching(false); @@ -52,9 +59,19 @@ export function Index() { } } + async function search(query: string) { + setFetching(true); + + setHasMore(true); + setFilter(query); + setData(null); + await delay(0); // stupid thing won't work w/o delay + + setFetching(false); + } + return (
- { selected ? @@ -65,6 +82,8 @@ export function Index() { : null } + +