Skip to content

Commit

Permalink
Modified the Search functionality to server components with streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
RoelLeijser committed Oct 24, 2024
1 parent f4b1a48 commit 9988385
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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('/')}`,
);
Expand All @@ -20,7 +22,9 @@ const Page = async (
return notFound();
}

return <FullPageView subject={resource.subject} />;
return (
<FullPageView subject={resource.subject} searchParams={searchParams} />
);
};

export default Page;
Original file line number Diff line number Diff line change
Expand Up @@ -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<HTMLInputElement>(null);
const debounceTimer = useRef<NodeJS.Timeout | null>(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<HTMLInputElement>) => void;
placeholder?: string;
}) => {
return (
<div className={styles.searchBar}>
<HStack align='center' gap='1ch'>
Expand All @@ -25,11 +54,13 @@ const Searchbar = ({
alt='search'
/>
<input
ref={inputRef}
className={styles.input}
type='search'
value={value}
onChange={handler}
placeholder={placeholder}
defaultValue={searchParams.get('search') || ''}
onChange={handleSearchChange}
aria-label='Search'
placeholder='Search blogposts...'
/>
</HStack>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,68 @@
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<Page>;
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 (
<Container>
<div className={styles.wrapper}>
<VStack>
<HStack wrap fullWidth align='center' justify='space-between'>
<h1>{resource.title}</h1>
{/* <Searchbar
// value={search}
// handler={handleSearch}
// placeholder='Search blogposts...'
// /> */}

<Suspense
fallback={
<input
className={styles.input}
type='search'
aria-label='Search'
placeholder='Search blogposts...'
/>
}
>
<Searchbar />
</Suspense>
</HStack>
<ul>
{results.map((post: string) => (
<li key={post}>
<ListItemView subject={post} />
</li>
))}
</ul>
{results.length !== 0 ? (
<ul>
{results.map((post: string) => (
<li key={post}>
<ListItemView subject={post} />
</li>
))}
</ul>
) : (
<Container>
<p>No results found.</p>
</Container>
)}
</VStack>
</div>
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -17,6 +23,10 @@ const FullPageView = async ({ subject }: { subject: string }) => {
DefaultFullPage,
);

if (Component === BlogIndexPageFullPage) {
return <Component resource={resource} searchParams={searchParams} />;
}

return <Component resource={resource} />;
};

Expand Down

0 comments on commit 9988385

Please sign in to comment.