diff --git a/src/graphql/queries/Metadata.ts b/src/graphql/queries/Metadata.ts index d210009..f9134a4 100644 --- a/src/graphql/queries/Metadata.ts +++ b/src/graphql/queries/Metadata.ts @@ -53,11 +53,13 @@ export const BLOG_METADATA_QUERY: DocumentNode = gql` $tags: [String!] $category: String $onlyPublished: Boolean + $query: String ) { blogMetadata( tags: $tags category: $category onlyPublished: $onlyPublished + query: $query ) { id name @@ -84,5 +86,6 @@ export namespace BlogMetadataQuery { onlyPublished?: boolean tags?: string[] category?: string + query?: string } } diff --git a/src/hooks/debounce.ts b/src/hooks/debounce.ts new file mode 100644 index 0000000..c176092 --- /dev/null +++ b/src/hooks/debounce.ts @@ -0,0 +1,28 @@ +import { useState, useEffect } from 'react' + +export type UseDebouncedOpts = { + delay?: number +} + +export type UseDebouncedResponse = [T, T, SetState] + +export function useDebounced( + defaultValue: T, + opts?: UseDebouncedOpts, +): UseDebouncedResponse { + let delay = 200 + if (opts?.delay) delay = opts.delay + + const [value, setValue] = useState(defaultValue) + const [debouncedValue, setDebouncedValue] = + useState(defaultValue) + + useEffect(() => { + const id = setTimeout(() => { + setDebouncedValue(value) + }, delay) + return () => clearTimeout(id) + }, [value, delay]) + + return [value, debouncedValue, setValue] +} diff --git a/src/pages/Blog/index.tsx b/src/pages/Blog/index.tsx index d123231..effff99 100644 --- a/src/pages/Blog/index.tsx +++ b/src/pages/Blog/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import { useTextGradient } from '../../hooks/styles' -// import { Input } from "@nextui-org/react"; -// import { MagnifyingGlassIcon } from "@heroicons/react/24/solid"; +import { Input } from '@nextui-org/react' +import { MagnifyingGlassIcon } from '@heroicons/react/24/solid' import BlogTags from './BlogTags' import BlogCategories from './BlogCategories' import { @@ -11,6 +11,7 @@ import { import { useQuery } from '@apollo/client' import BlogCard, { BlogCardSkeleton } from './BlogCard' import { useBreakpointValue } from '../../hooks/mediaQuery' +import { useDebounced } from '../../hooks/debounce' const Blog: React.FC = () => { const textGradient = useTextGradient({ @@ -20,6 +21,10 @@ const Blog: React.FC = () => { }) const [tags, setTags] = useState([]) const [category, setCategory] = useState() + const [query, debouncedQuery, setQuery] = useDebounced('', { + delay: 400, + }) + const { data, loading } = useQuery< BlogMetadataQuery.Response, BlogMetadataQuery.Variables @@ -28,6 +33,7 @@ const Blog: React.FC = () => { onlyPublished: true, category, tags, + query: debouncedQuery, }, }) const isMobile = useBreakpointValue({ default: true, md: false }) @@ -40,17 +46,19 @@ const Blog: React.FC = () => { > Blog -

+

Sometimes I like to write about things I've worked on, my experiences or anything else of interest to me.

{/* TODO: Implement search in backend and come back to this. */} - {/* } + } isClearable - /> */} + value={query} + onValueChange={setQuery} + />
setTags(values)}