From 9988385f6e949f122d48a60e3cf76bd6238b8511 Mon Sep 17 00:00:00 2001 From: Roel Date: Thu, 24 Oct 2024 16:35:57 +0200 Subject: [PATCH] Modified the Search functionality to server components with streaming --- .../nextjs-site/src/app/[...slug]/page.tsx | 20 ++++--- .../nextjs-site/src/components/Searchbar.tsx | 55 +++++++++++++---- .../views/FullPage/BlogIndexPageFullPage.tsx | 60 ++++++++++++++----- .../src/views/FullPage/FullPageView.tsx | 12 +++- 4 files changed, 111 insertions(+), 36 deletions(-) diff --git a/browser/create-template/templates/nextjs-site/src/app/[...slug]/page.tsx b/browser/create-template/templates/nextjs-site/src/app/[...slug]/page.tsx index 19e7eb66..0b0a6a30 100644 --- a/browser/create-template/templates/nextjs-site/src/app/[...slug]/page.tsx +++ b/browser/create-template/templates/nextjs-site/src/app/[...slug]/page.tsx @@ -3,14 +3,16 @@ import { env } from '@/env'; import FullPageView from '@/views/FullPage/FullPageView'; import { notFound } from 'next/navigation'; -const Page = async ( - props: { - params: Promise<{ - slug: string[]; - }>; - } -) => { +const Page = async (props: { + params: Promise<{ + slug: string[]; + }>; + searchParams?: Promise<{ + search: string; + }>; +}) => { const params = await props.params; + const searchParams = await props.searchParams; const resourceUrl = new URL( `${env.NEXT_PUBLIC_ATOMIC_SERVER_URL}/${params.slug.join('/')}`, ); @@ -20,7 +22,9 @@ const Page = async ( return notFound(); } - return ; + return ( + + ); }; export default Page; diff --git a/browser/create-template/templates/nextjs-site/src/components/Searchbar.tsx b/browser/create-template/templates/nextjs-site/src/components/Searchbar.tsx index 23c32fbb..3bd0748e 100644 --- a/browser/create-template/templates/nextjs-site/src/components/Searchbar.tsx +++ b/browser/create-template/templates/nextjs-site/src/components/Searchbar.tsx @@ -4,16 +4,45 @@ import HStack from './Layout/HStack'; import styles from './Searchbar.module.css'; import FaMagnifyingGlass from './Icons/magnifying-glass-solid.svg'; import Image from 'next/image'; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; +import { useCallback, useEffect, useRef } from 'react'; + +const Searchbar = () => { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + + const inputRef = useRef(null); + const debounceTimer = useRef(null); + + const createQueryString = useCallback( + (name: string, value: string) => { + const params = new URLSearchParams(searchParams.toString()); + params.set(name, value); + return params.toString(); + }, + [searchParams], + ); + + const handleSearchChange = () => { + if (debounceTimer.current) { + clearTimeout(debounceTimer.current); + } + + debounceTimer.current = setTimeout(() => { + const searchValue = inputRef.current?.value || ''; + router.push(pathname + '?' + createQueryString('search', searchValue)); + }, 200); + }; + + useEffect(() => { + return () => { + if (debounceTimer.current) { + clearTimeout(debounceTimer.current); + } + }; + }, []); -const Searchbar = ({ - value, - handler, - placeholder = 'Search...', -}: { - value: string; - handler: (event: React.ChangeEvent) => void; - placeholder?: string; -}) => { return (
@@ -25,11 +54,13 @@ const Searchbar = ({ alt='search' />
diff --git a/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogIndexPageFullPage.tsx b/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogIndexPageFullPage.tsx index a2957aa6..b4e88209 100644 --- a/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogIndexPageFullPage.tsx +++ b/browser/create-template/templates/nextjs-site/src/views/FullPage/BlogIndexPageFullPage.tsx @@ -1,18 +1,34 @@ import Container from '@/components/Layout/Container'; -import type { Page } from '@/ontologies/website'; -import type { Resource } from '@tomic/lib'; +import { website, type Page } from '@/ontologies/website'; +import { core, type Resource } from '@tomic/lib'; import styles from './BlogIndexPageFullPage.module.css'; import VStack from '@/components/Layout/VStack'; import HStack from '@/components/Layout/HStack'; import ListItemView from '../ListItem/ListItemView'; import { getAllBlogposts } from '@/atomic/getAllBlogposts'; +import { Suspense } from 'react'; +import Searchbar from '@/components/Searchbar'; +import { store } from '@/app/store'; const BlogIndexPageFullPage = async ({ resource, + searchParams, }: { resource: Resource; + searchParams?: { search: string }; }) => { - const results = await getAllBlogposts(); + const allItems = await getAllBlogposts(); + let results: string[] = []; + + if (searchParams?.search) { + results = await store.search(searchParams.search, { + filters: { + [core.properties.isA]: website.classes.blogpost, + }, + }); + } else { + results = allItems; + } return ( @@ -20,19 +36,33 @@ const BlogIndexPageFullPage = async ({

{resource.title}

- {/* */} + + + } + > + +
-
    - {results.map((post: string) => ( -
  • - -
  • - ))} -
+ {results.length !== 0 ? ( +
    + {results.map((post: string) => ( +
  • + +
  • + ))} +
+ ) : ( + +

No results found.

+
+ )}
diff --git a/browser/create-template/templates/nextjs-site/src/views/FullPage/FullPageView.tsx b/browser/create-template/templates/nextjs-site/src/views/FullPage/FullPageView.tsx index 00b34671..a374fa33 100644 --- a/browser/create-template/templates/nextjs-site/src/views/FullPage/FullPageView.tsx +++ b/browser/create-template/templates/nextjs-site/src/views/FullPage/FullPageView.tsx @@ -5,7 +5,13 @@ import BlogpostFullPage from './BlogpostFullPage'; import DefaultFullPage from './DefaultFullPage'; import { store } from '@/app/store'; -const FullPageView = async ({ subject }: { subject: string }) => { +const FullPageView = async ({ + subject, + searchParams, +}: { + subject: string; + searchParams?: { search: string }; +}) => { const resource = await store.getResource(subject); const Component = resource.matchClass( @@ -17,6 +23,10 @@ const FullPageView = async ({ subject }: { subject: string }) => { DefaultFullPage, ); + if (Component === BlogIndexPageFullPage) { + return ; + } + return ; };