diff --git a/frontend/pages/vendors/index.js b/frontend/pages/vendors/index.js index f195ca6..1510026 100644 --- a/frontend/pages/vendors/index.js +++ b/frontend/pages/vendors/index.js @@ -1,7 +1,9 @@ import { Link } from '@chakra-ui/next-js' import { Alert, + AlertDescription, AlertIcon, + AlertTitle, Box, Button, ButtonGroup, @@ -12,8 +14,17 @@ import { Heading, IconButton, Image, + Input, + InputGroup, + InputLeftElement, + InputRightElement, LinkBox, LinkOverlay, + Menu, + MenuButton, + MenuDivider, + MenuItem, + MenuList, SimpleGrid, Skeleton, Spinner, @@ -23,18 +34,42 @@ import { Text, Tr, } from '@chakra-ui/react' -import { useLocalStorageValue } from '@react-hookz/web' +import { useDebouncedCallback, useLocalStorageValue } from '@react-hookz/web' import { useRouter } from 'next/router' -import { TbLayoutGrid, TbLayoutList } from 'react-icons/tb' +import { TbCheck, TbFilter, TbFilterEdit, TbLayoutGrid, TbLayoutList, TbMoodSad, TbSearch, TbX } from 'react-icons/tb' import useSWR from 'swr' import Pagination from '~/components/pagination' const PER_PAGE = 12 -export default function VendorsPage() { +export const getStaticProps = async () => { + const url = new URL(`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/items/categories`) + url.searchParams.append('fields[]', 'slug') + url.searchParams.append('fields[]', 'name') + url.searchParams.append('fields[]', 'subcategories.slug') + url.searchParams.append('fields[]', 'subcategories.name') + url.searchParams.append('sort', 'name') + url.searchParams.append('limit', -1) + url.searchParams.append( + 'filter', + JSON.stringify({ + parent_id: { + _null: true, + }, + }) + ) + + const res = await fetch(url.toString()) + + const { data: categories } = await res.json() + + return { props: { categories } } +} + +export default function VendorsPage({ categories }) { const router = useRouter() const { - query: { page = 1 }, + query: { page = 1, category = '', q: search = '' }, } = router const { value: perPage, set: setPerPage } = useLocalStorageValue('perPage', { @@ -47,14 +82,43 @@ export default function VendorsPage() { initializeWithValue: false, }) - const { data, error, isLoading, isValidating } = useSWR(['vendors', page, perPage], async () => { - // await new Promise((r) => setTimeout(r, 2000)) + const setSearch = useDebouncedCallback( + (q) => { + router.replace({ query: { ...router.query, q } }) + }, + [router], + 500 + ) + + const { data, error, isLoading, isValidating } = useSWR(['vendors', page, perPage, search, category], async () => { + if (!perPage) return + + await new Promise((r) => setTimeout(r, 2000)) const url = new URL(`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/items/vendors`) url.searchParams.append('fields[]', '*') url.searchParams.append('limit', perPage) url.searchParams.append('page', page) url.searchParams.append('sort', 'name') url.searchParams.append('meta[]', 'filter_count') + + if (search !== '' || category !== '') { + url.searchParams.append( + 'filter', + JSON.stringify({ + _and: [ + category !== '' ? { categories: { categories_id: { slug: { _eq: category } } } } : {}, + search !== '' + ? { + _or: ['name', 'description', 'long_description', 'city'].map((s) => ({ + [s]: { _contains: search }, + })), + } + : {}, + ], + }) + ) + } + const res = await fetch(url.toString()) if (!res.ok) { throw new Error('Oops') @@ -64,17 +128,54 @@ export default function VendorsPage() { const { meta, data: vendors } = data || { meta: {}, data: [] } + const lastPage = Math.max(1, Math.ceil(meta.filter_count / perPage)) + if (!isNaN(lastPage) && page > lastPage) { + router.replace({ query: { ...router.query, page: lastPage } }) + } + return ( -