import { Code, Dot, Input, Note, Text } from "@geist-ui/core" import NextLink from "next/link" import Link from '../Link' import styles from './post-list.module.css' import ListItemSkeleton from "./list-item-skeleton" import ListItem from "./list-item" import { Post } from "@lib/types" import { ChangeEvent, useEffect, useMemo, useState } from "react" import debounce from "lodash.debounce" type Props = { posts: Post[] error: any } const PostList = ({ posts, error }: Props) => { const [search, setSearchValue] = useState('') // const [searching, setSearching] = useState(false) const [searchResults, setSearchResults] = useState(posts) // update posts on search useEffect(() => { if (search) { // support filters like "title is:private has:content" in the text // extract the filters const filters = search.split(' ').filter(s => s.includes(':')) const filtersMap = new Map() filters.forEach(f => { const [key, value] = f.split(':') filtersMap.set(key, value) }) const results = posts.filter(post => { if (filtersMap.has('is') && filtersMap.get('is') !== post.visibility) { return false } for (const file of post.files) { if (file.content.toLowerCase().includes(search.toLowerCase())) { return true } } return post.title.toLowerCase().includes(search.toLowerCase()) }) setSearchResults(results) } else { setSearchResults(posts) } }, [search, posts]) const handleSearchChange = (e: ChangeEvent) => { setSearchValue(e.target.value) } const debouncedSearchHandler = useMemo( () => debounce(handleSearchChange, 300) , []); useEffect(() => { return () => { debouncedSearchHandler.cancel(); } }, [debouncedSearchHandler]); return (
Available filters: is:visibility
{error && Failed to load.} { !posts &&
} {posts.length === 0 && !error && No posts found.Create one here.} {searchResults.length === 0 && No posts returned. Create one here.} { searchResults?.length > 0 &&
    {searchResults.map((post) => { return })}
}
) } export default PostList