SWR, improved vendors list
This commit is contained in:
@@ -12,13 +12,14 @@
|
||||
"@chakra-ui/icons": "2.0.19",
|
||||
"@chakra-ui/next-js": "2.1.4",
|
||||
"@chakra-ui/react": "2.7.1",
|
||||
"@directus/sdk": "10.3.3",
|
||||
"@emotion/react": "11.11.1",
|
||||
"@emotion/styled": "11.11.0",
|
||||
"@tanstack/react-query": "4.29.19",
|
||||
"@react-hookz/web": "23.1.0",
|
||||
"clsx": "1.2.1",
|
||||
"next": "13.4.8",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"react-dom": "18.2.0",
|
||||
"react-icons": "4.10.1",
|
||||
"swr": "2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export const getStaticPaths = async () => {
|
||||
const url = new URL(`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/items/pages`)
|
||||
url.searchParams.append('fields[]', 'slug')
|
||||
url.searchParams.append('limit', -1)
|
||||
const res = await fetch(url.toString())
|
||||
|
||||
const { data: pages } = await res.json()
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { ChakraProvider } from '@chakra-ui/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import Layout from '~/components/layout'
|
||||
import theme from '~/src/theme'
|
||||
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ChakraProvider theme={theme}>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</ChakraProvider>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
|
||||
151
frontend/pages/vendors/index.js
vendored
151
frontend/pages/vendors/index.js
vendored
@@ -1,7 +1,32 @@
|
||||
import { Link } from '@chakra-ui/next-js'
|
||||
import { Card, CardBody, Heading, Image, LinkBox, LinkOverlay, SimpleGrid, Skeleton } from '@chakra-ui/react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import {
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Box,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Card,
|
||||
CardBody,
|
||||
Flex,
|
||||
HStack,
|
||||
Heading,
|
||||
IconButton,
|
||||
Image,
|
||||
LinkBox,
|
||||
LinkOverlay,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
Spinner,
|
||||
Table,
|
||||
Tbody,
|
||||
Td,
|
||||
Text,
|
||||
Tr,
|
||||
} from '@chakra-ui/react'
|
||||
import { useLocalStorageValue } from '@react-hookz/web'
|
||||
import { useRouter } from 'next/router'
|
||||
import { TbLayoutGrid, TbLayoutList } from 'react-icons/tb'
|
||||
import useSWR from 'swr'
|
||||
import Pagination from '~/components/pagination'
|
||||
|
||||
const PER_PAGE = 12
|
||||
@@ -12,65 +37,157 @@ export default function VendorsPage() {
|
||||
query: { page = 1 },
|
||||
} = router
|
||||
|
||||
const { data, isFetching } = useQuery({
|
||||
queryKey: ['vendors', page],
|
||||
queryFn: async (...props2) => {
|
||||
const { value: perPage, set: setPerPage } = useLocalStorageValue('perPage', {
|
||||
defaultValue: PER_PAGE,
|
||||
initializeWithValue: false,
|
||||
})
|
||||
|
||||
const { value: layout, set: setLayout } = useLocalStorageValue('layout', {
|
||||
defaultValue: 'GRID',
|
||||
initializeWithValue: false,
|
||||
})
|
||||
|
||||
const { data, error, isLoading, isValidating } = useSWR(['vendors', page, perPage], async () => {
|
||||
// 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', PER_PAGE)
|
||||
url.searchParams.append('limit', perPage)
|
||||
url.searchParams.append('page', page)
|
||||
url.searchParams.append('sort', 'name')
|
||||
url.searchParams.append('meta[]', 'filter_count')
|
||||
|
||||
const res = await fetch(url.toString())
|
||||
if (!res.ok) {
|
||||
throw new Error('Oops')
|
||||
}
|
||||
|
||||
return res.json()
|
||||
},
|
||||
keepPreviousData: true,
|
||||
cacheTime: 1000 * 60 * 30,
|
||||
staleTime: 1000 * 60 * 30,
|
||||
})
|
||||
|
||||
const { meta, data: vendors } = data || { meta: {}, data: [] }
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<Heading size="lg" my={8}>
|
||||
Vendors
|
||||
</Heading>
|
||||
<Box>{isValidating && <Spinner />}</Box>
|
||||
<ButtonGroup isAttached>
|
||||
<IconButton icon={<TbLayoutGrid />} onClick={() => setLayout('GRID')} isDisabled={layout === 'GRID'} />
|
||||
<IconButton icon={<TbLayoutList />} onClick={() => setLayout('LIST')} isDisabled={layout === 'LIST'} />
|
||||
</ButtonGroup>
|
||||
</Flex>
|
||||
|
||||
{error && (
|
||||
<Alert status="error" marginY={3}>
|
||||
<AlertIcon />
|
||||
There was an error processing your request
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{layout === 'GRID' && (
|
||||
<SimpleGrid columns={[1, 2, 3, 4]} spacing={3}>
|
||||
{isFetching &&
|
||||
new Array(PER_PAGE).fill(true).map((v, k) => (
|
||||
{isLoading &&
|
||||
new Array(perPage).fill(true).map((v, k) => (
|
||||
<Card key={k}>
|
||||
<Skeleton h="40" />
|
||||
<CardBody>
|
||||
<Skeleton h="6" mb="2" />
|
||||
<Skeleton h="4" mb="1" />
|
||||
<Skeleton h="4" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
))}
|
||||
{!isFetching &&
|
||||
{!isLoading &&
|
||||
vendors.map((v) => (
|
||||
<LinkBox as={Card} rounded={4} key={v.id}>
|
||||
<Image
|
||||
roundedTop={4}
|
||||
objectFit="cover"
|
||||
src="https://images.unsplash.com/photo-1531403009284-440f080d1e12?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=250&q=80"
|
||||
src={`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/assets/${v.logo}?key=logo-card`}
|
||||
alt={v.name}
|
||||
width="250"
|
||||
height="150"
|
||||
style={{ objectFit: 'contain', background: '#fff' }}
|
||||
/>
|
||||
<CardBody>
|
||||
<LinkOverlay as={Link} href={`/vendors/${v.slug}`} prefetch={false}>
|
||||
<Text mb="2" fontWeight="900">
|
||||
{v.name}
|
||||
</Text>
|
||||
<Text fontSize="sm">
|
||||
{v?.description?.substring(0, v?.description?.substring(0, 80).lastIndexOf(' '))} …
|
||||
</Text>
|
||||
</LinkOverlay>
|
||||
</CardBody>
|
||||
</LinkBox>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
)}
|
||||
|
||||
<Pagination page={Number(page)} itemsPerPage={PER_PAGE} totalItems={meta.filter_count} />
|
||||
{layout === 'LIST' && (
|
||||
<>
|
||||
{isLoading && (
|
||||
<Table>
|
||||
<Tbody>
|
||||
{new Array(perPage).fill(true).map((v, k) => (
|
||||
<Tr key={k}>
|
||||
<Td w="10%">
|
||||
<Skeleton h="12" w="12" />
|
||||
</Td>
|
||||
<Td w="30%">
|
||||
<Skeleton h="6" />
|
||||
</Td>
|
||||
<Td w="60%">
|
||||
<Skeleton h="6" />
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
)}
|
||||
{!isLoading && (
|
||||
<Table>
|
||||
<Tbody>
|
||||
{vendors.map((v) => (
|
||||
<Link key={v.id} href={`/vendors/${v.slug}`} prefetch={false} display="contents">
|
||||
<Tr verticalAlign="middle">
|
||||
<Td>
|
||||
<Image
|
||||
rounded="md"
|
||||
src={`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/assets/${v.logo}?key=logo-card`}
|
||||
alt={v.name}
|
||||
width="12"
|
||||
height="12"
|
||||
style={{ objectFit: 'contain', background: '#fff' }}
|
||||
/>
|
||||
</Td>
|
||||
<Td>{v.name}</Td>
|
||||
<Td>
|
||||
<Text fontSize="sm">
|
||||
{v?.description?.substring(0, v?.description?.substring(0, 80).lastIndexOf(' '))} …
|
||||
</Text>
|
||||
</Td>
|
||||
</Tr>
|
||||
</Link>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<Pagination page={Number(page)} itemsPerPage={perPage} totalItems={meta.filter_count} />
|
||||
|
||||
<HStack>
|
||||
<Text>Results per page:</Text>
|
||||
<ButtonGroup isAttached>
|
||||
{[12, 24, 48].map((n) => (
|
||||
<Button key={n} onClick={() => setPerPage(n)} isDisabled={perPage === n}>
|
||||
{n}
|
||||
</Button>
|
||||
))}
|
||||
</ButtonGroup>
|
||||
</HStack>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
137
frontend/pnpm-lock.yaml
generated
137
frontend/pnpm-lock.yaml
generated
@@ -14,18 +14,15 @@ dependencies:
|
||||
'@chakra-ui/react':
|
||||
specifier: 2.7.1
|
||||
version: 2.7.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(framer-motion@6.5.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@directus/sdk':
|
||||
specifier: 10.3.3
|
||||
version: 10.3.3
|
||||
'@emotion/react':
|
||||
specifier: 11.11.1
|
||||
version: 11.11.1(react@18.2.0)
|
||||
'@emotion/styled':
|
||||
specifier: 11.11.0
|
||||
version: 11.11.0(@emotion/react@11.11.1)(react@18.2.0)
|
||||
'@tanstack/react-query':
|
||||
specifier: 4.29.19
|
||||
version: 4.29.19(react-dom@18.2.0)(react@18.2.0)
|
||||
'@react-hookz/web':
|
||||
specifier: 23.1.0
|
||||
version: 23.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||
clsx:
|
||||
specifier: 1.2.1
|
||||
version: 1.2.1
|
||||
@@ -38,6 +35,12 @@ dependencies:
|
||||
react-dom:
|
||||
specifier: 18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
react-icons:
|
||||
specifier: 4.10.1
|
||||
version: 4.10.1(react@18.2.0)
|
||||
swr:
|
||||
specifier: 2.2.0
|
||||
version: 2.2.0(react@18.2.0)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -1203,14 +1206,6 @@ packages:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@directus/sdk@10.3.3:
|
||||
resolution: {integrity: sha512-58gw+QjkuIr0lJFRx5HwSp1ewAf7rjfV++eJqAmC13p7vif9wfJEcWcJwqXstYdvtJVUg+nB4O/CE0OBEtp5HQ==}
|
||||
dependencies:
|
||||
axios: 0.27.2
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/@emotion/babel-plugin@11.11.0:
|
||||
resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==}
|
||||
dependencies:
|
||||
@@ -1474,34 +1469,31 @@ packages:
|
||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||
dev: false
|
||||
|
||||
/@react-hookz/deep-equal@1.0.4:
|
||||
resolution: {integrity: sha512-N56fTrAPUDz/R423pag+n6TXWbvlBZDtTehaGFjK0InmN+V2OFWLE/WmORhmn6Ce7dlwH5+tQN1LJFw3ngTJVg==}
|
||||
dev: false
|
||||
|
||||
/@react-hookz/web@23.1.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-fvbURdsa1ukttbLR1ASE/XmqXP09vZ1PiCYppYeR1sNMzCrdkG0iBnjxniFSVjJ8gIw2fRs6nqMTbeBz2uAkuA==}
|
||||
peerDependencies:
|
||||
js-cookie: ^3.0.5
|
||||
react: ^16.8 || ^17 || ^18
|
||||
react-dom: ^16.8 || ^17 || ^18
|
||||
peerDependenciesMeta:
|
||||
js-cookie:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@react-hookz/deep-equal': 1.0.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@swc/helpers@0.5.1:
|
||||
resolution: {integrity: sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==}
|
||||
dependencies:
|
||||
tslib: 2.6.0
|
||||
dev: false
|
||||
|
||||
/@tanstack/query-core@4.29.19:
|
||||
resolution: {integrity: sha512-uPe1DukeIpIHpQi6UzIgBcXsjjsDaLnc7hF+zLBKnaUlh7jFE/A+P8t4cU4VzKPMFB/C970n/9SxtpO5hmIRgw==}
|
||||
dev: false
|
||||
|
||||
/@tanstack/react-query@4.29.19(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-XiTIOHHQ5Cw1WUlHaD4fmVUMhoWjuNJlAeJGq7eM4BraI5z7y8WkZO+NR8PSuRnQGblpuVdjClQbDFtwxTtTUw==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-native: '*'
|
||||
peerDependenciesMeta:
|
||||
react-dom:
|
||||
optional: true
|
||||
react-native:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@tanstack/query-core': 4.29.19
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@types/lodash.mergewith@4.6.7:
|
||||
resolution: {integrity: sha512-3m+lkO5CLRRYU0fhGRp7zbsGi6+BZj0uTVSwvcKU+nSlhjA9/QRNfuSGnD2mX6hQA7ZbmcCkzk5h4ZYGOtk14A==}
|
||||
dependencies:
|
||||
@@ -1538,19 +1530,6 @@ packages:
|
||||
tslib: 2.5.3
|
||||
dev: false
|
||||
|
||||
/asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
dev: false
|
||||
|
||||
/axios@0.27.2:
|
||||
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
|
||||
dependencies:
|
||||
follow-redirects: 1.15.2
|
||||
form-data: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/babel-plugin-macros@3.1.0:
|
||||
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
|
||||
engines: {node: '>=10', npm: '>=6'}
|
||||
@@ -1608,13 +1587,6 @@ packages:
|
||||
resolution: {integrity: sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w==}
|
||||
dev: false
|
||||
|
||||
/combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
dev: false
|
||||
|
||||
/compute-scroll-into-view@1.0.20:
|
||||
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
|
||||
dev: false
|
||||
@@ -1650,11 +1622,6 @@ packages:
|
||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
||||
dev: false
|
||||
|
||||
/delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/detect-node-es@1.1.0:
|
||||
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
|
||||
dev: false
|
||||
@@ -1686,25 +1653,6 @@ packages:
|
||||
tslib: 2.5.3
|
||||
dev: false
|
||||
|
||||
/follow-redirects@1.15.2:
|
||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/form-data@4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/framer-motion@6.5.1(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==}
|
||||
peerDependencies:
|
||||
@@ -1821,18 +1769,6 @@ packages:
|
||||
js-tokens: 4.0.0
|
||||
dev: false
|
||||
|
||||
/mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
dev: false
|
||||
|
||||
/nanoid@3.3.6:
|
||||
resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
@@ -1984,6 +1920,14 @@ packages:
|
||||
use-sidecar: 1.1.2(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-icons@4.10.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
dev: false
|
||||
@@ -2123,6 +2067,15 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: false
|
||||
|
||||
/swr@2.2.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==}
|
||||
peerDependencies:
|
||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/tiny-invariant@1.3.1:
|
||||
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
|
||||
dev: false
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
import directus from '~/lib/directus'
|
||||
import all from '~/public/data.json'
|
||||
|
||||
function sluggify(str = '') {
|
||||
return (
|
||||
str
|
||||
.toLocaleLowerCase()
|
||||
.normalize('NFKC')
|
||||
.trim()
|
||||
//
|
||||
.split('.')
|
||||
.join(' ')
|
||||
.split('(')
|
||||
.join('')
|
||||
.split(')')
|
||||
.join('')
|
||||
.split('|')
|
||||
.join(' ')
|
||||
.trim()
|
||||
.split(',')
|
||||
.join('')
|
||||
.split(' ')
|
||||
.join('-')
|
||||
.split('-/-')
|
||||
.join('-')
|
||||
.split(' &')
|
||||
.join('')
|
||||
.split('&')
|
||||
.join('and')
|
||||
.split('/')
|
||||
.join('-')
|
||||
.replace(/\-\-+/, '-')
|
||||
.trim()
|
||||
)
|
||||
}
|
||||
|
||||
function sanitize(str = '') {
|
||||
return (
|
||||
str
|
||||
//
|
||||
.split(' &')
|
||||
.join('')
|
||||
.split(' / ')
|
||||
.join('/')
|
||||
.split('/')
|
||||
.join(' / ')
|
||||
.trim()
|
||||
)
|
||||
}
|
||||
|
||||
async function importCategories() {
|
||||
all.results.map((one) => {
|
||||
one.raw.marketplaceexhibitorcategory?.map(async (cat) => {
|
||||
const name = sanitize(cat)
|
||||
const slug = sluggify(name)
|
||||
try {
|
||||
await directus.items('categories').createOne({
|
||||
slug,
|
||||
name,
|
||||
})
|
||||
} catch (error) {}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function importSubcategories() {
|
||||
all.results.map((one) => {
|
||||
one.raw.marketplaceexhibitorsubcategory?.map(async (cat) => {
|
||||
const name = sanitize(cat)
|
||||
const slug = sluggify(name)
|
||||
try {
|
||||
await directus.items('categories').createOne({
|
||||
slug,
|
||||
name,
|
||||
})
|
||||
} catch (error) {}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function importCategoryStructure() {
|
||||
const { data: categories } = await directus.items('categories').readByQuery({ limit: -1 })
|
||||
|
||||
all.results.map((one) => {
|
||||
one.raw.marketplaceexhibitorcategorysubcategory?.map(async (cat) => {
|
||||
const [parentTitle, catTitle] = cat.split('|')
|
||||
const catSlug = sluggify(catTitle)
|
||||
const parentSlug = sluggify(parentTitle)
|
||||
if (parentSlug) {
|
||||
try {
|
||||
const category = categories.find((c) => catSlug === c.slug)
|
||||
const parent = categories.find((c) => parentSlug === c.slug)
|
||||
await directus.items('categories').updateOne(category.id, {
|
||||
parent_id: parent.id,
|
||||
})
|
||||
} catch (error) {}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function importVendors() {
|
||||
const { data: categories } = await directus.items('categories').readByQuery({ limit: -1 })
|
||||
|
||||
return Promise.all(
|
||||
all.results.map(async (one) => {
|
||||
const name = sanitize(one.raw.name)
|
||||
let slug = sluggify(name)
|
||||
const {
|
||||
data: [existingVendor],
|
||||
} = await directus.items('vendors').readByQuery({
|
||||
fields: ['slug'],
|
||||
limit: -1,
|
||||
filter: {
|
||||
slug: {
|
||||
_eq: slug,
|
||||
},
|
||||
},
|
||||
})
|
||||
let i = 1
|
||||
while (existingVendor?.slug === slug) {
|
||||
slug = sluggify(name) + '-' + i++
|
||||
}
|
||||
|
||||
const categoryIds = new Set(
|
||||
one.raw.marketplaceexhibitorcategory
|
||||
?.map((t) => sluggify(sanitize(t)))
|
||||
.map((s) => categories.filter((t) => !t.parent_id).find((t) => s === t.slug)?.id)
|
||||
.filter((s) => !!s)
|
||||
)
|
||||
|
||||
const vendor = {
|
||||
slug,
|
||||
name,
|
||||
status: 'published',
|
||||
description: one.raw?.description,
|
||||
address_line_1: one.raw?.addressline1,
|
||||
address_line_2: one.raw?.addressline2,
|
||||
city: one.raw?.city,
|
||||
state: one.raw?.state,
|
||||
country: one.raw?.country,
|
||||
website: one.raw?.website,
|
||||
}
|
||||
try {
|
||||
const res = await directus.items('vendors').createOne(vendor)
|
||||
categoryIds.forEach(async (cid) => {
|
||||
await directus.items('vendors_categories').createOne({ vendors_id: res.id, categories_id: cid })
|
||||
})
|
||||
} catch (error) {}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
// importCategories()
|
||||
// importSubcategories()
|
||||
// importCategoryStructure()
|
||||
// importVendors()
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1>Import {new Date().toISOString()}</h1>
|
||||
{/* <pre>{JSON.stringify(res, null, 2)} </pre> */}
|
||||
</main>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user