feat: add useOrders hooks to fetch orders

fix: getProviderName return aquilacms if correct env are sets
This commit is contained in:
Gérard Le Cloerec 2021-04-07 16:04:16 +02:00
parent 0071b6fefc
commit 9df1475c66
15 changed files with 232 additions and 39 deletions

View File

@ -1,5 +1,4 @@
{
"provider": "aquilacms",
"features": {
"wishlist": false,
"customCheckout": false

View File

@ -0,0 +1,35 @@
import type { OrdersHandlers } from '..'
import { normalizeOrder } from '../../../lib/normalize'
const getOrders: OrdersHandlers['getOrders'] = async ({ req, res, config }) => {
const token = req.cookies[config.customerCookie]
if (token) {
try {
const { datas } = await config.storeApiFetch('/v2/orders', {
method: 'POST',
body: JSON.stringify({
lang: 'en',
PostBody: {
sort: { createdAt: -1 },
populate: ['items.id'],
limit: 6,
page: 1,
},
}),
headers: {
authorization: token,
},
})
return res
.status(200)
.json({ data: { orders: datas.map(normalizeOrder) } })
} catch (err) {
console.error(err)
}
}
res.status(200).json({ data: null })
}
export default getOrders

View File

@ -0,0 +1,47 @@
import createApiHandler, {
AquilacmsApiHandler,
AquilacmsHandler,
} from '../utils/create-api-handler'
import isAllowedMethod from '../utils/is-allowed-method'
import { AquilacmsApiError } from '../utils/errors'
import getOrders from './handlers/get-orders'
import { Order } from '../../types'
export type { Order }
export type OrdersData = {
orders: Order[]
}
export type OrdersHandlers = {
getOrders: AquilacmsHandler<OrdersData>
}
const METHODS = ['POST']
const ordersApi: AquilacmsApiHandler<OrdersData, OrdersHandlers> = async (
req,
res,
config,
handlers
) => {
if (!isAllowedMethod(req, res, METHODS)) return
try {
const body = null
return await handlers['getOrders']({ req, res, config, body })
} catch (error) {
console.error(error)
const message =
error instanceof AquilacmsApiError
? 'An unexpected error ocurred with the Aquilacms API'
: 'An unexpected error ocurred'
res.status(500).json({ data: null, errors: [{ message }] })
}
}
const handlers = { getOrders }
export default createApiHandler(ordersApi, handlers, {})

View File

@ -17,8 +17,7 @@ export const handler: SWRHook<
method: 'GET',
},
async fetcher({ input: { cartId }, options, fetch }) {
const data = cartId ? await fetch(options) : null
return data // && normalizeCart(data)
return cartId ? await fetch(options) : null
},
useHook: ({ useData }) => (input) => {
const response = useData({

View File

@ -1,5 +1,4 @@
import type { Product, ProductOption } from '@commerce/types'
import { getConfig } from '../api'
import type {
Cart,
AquilacmsCart,
@ -10,6 +9,8 @@ import type {
AquilacmsUser,
User,
AquilacmsProductAttribute,
AquilacmsOrder,
Order,
} from '../types'
function normalizeProductOption(
@ -139,3 +140,17 @@ export function normalizeUser(data: AquilacmsUser): User {
},
}
}
export function normalizeOrder(data: AquilacmsOrder): Order {
return {
id: data._id,
code: data.number,
status: data.status,
price: {
value: data.priceTotal.ati,
currency: 'EUR',
},
items: [],
createdAt: data.created_at,
}
}

View File

@ -1,14 +0,0 @@
import { AquilacmsConfig } from '..'
import { getConfig } from '../api'
async function getAllOrders({
config,
}: {
config?: AquilacmsConfig
}): Promise<{ orders: any[] }> {
config = getConfig(config)
const data: any = []
return { orders: data }
}
export default getAllOrders

View File

@ -0,0 +1 @@
export { default as useOrders } from './use-orders'

View File

@ -0,0 +1,39 @@
import { HookFetcherFn, SWRHook } from '@commerce/utils/types'
import type { Order, OrdersData } from '../api/orders'
import { useHook, useSWRHook } from '@commerce/utils/use-hook'
import SWRFetcher from '@commerce/utils/default-fetcher'
import { Provider } from '../../commerce'
type UseOrders<
H extends SWRHook<any, any, any> = SWRHook<Order[] | null>
> = ReturnType<H['useHook']>
const fetcher: HookFetcherFn<Order[] | null, any> = SWRFetcher
const fn = (provider: Provider) => provider.orders?.useOrders!
const useOrders: UseOrders = (input) => {
const hook = useHook(fn)
return useSWRHook({ fetcher, ...hook } as any)(input)
}
export default useOrders as UseOrders<typeof handler>
export const handler: SWRHook<Order[] | null> = {
fetchOptions: {
url: '/api/bigcommerce/orders',
method: 'POST',
},
async fetcher({ options, fetch }) {
const data = await fetch<OrdersData | null>(options)
return data?.orders ?? null
},
useHook: ({ useData }) => (input) => {
return useData({
swrOptions: {
revalidateOnFocus: false,
...input?.swrOptions,
},
})
},
}

View File

@ -10,6 +10,8 @@ import { handler as useLogin } from './auth/use-login'
import { handler as useLogout } from './auth/use-logout'
import { handler as useSignup } from './auth/use-signup'
import { handler as useOrders } from './orders/use-orders'
import fetcher from './fetcher'
import { Provider } from '../commerce'
@ -21,6 +23,7 @@ export const aquilacmsProvider = {
customer: { useCustomer },
products: { useSearch },
auth: { useLogin, useLogout, useSignup },
orders: { useOrders },
} as Provider
export type AquilacmsProvider = typeof aquilacmsProvider

View File

@ -392,6 +392,8 @@ export type RemoveCartItemBody = Core.RemoveCartItemBody
export type RemoveCartItemHandlerBody = Core.RemoveCartItemHandlerBody
export type Order = Core.Order
export type User = {
entityId: string
firstName: string
@ -434,3 +436,19 @@ export type AquilacmsStatic = {
}
name: string
}
export type AquilacmsCartItem = {}
export type AquilacmsOrder = {
_id: string
items: AquilacmsCartItem[]
number: string
priceTotal: {
ati: number
et: number
paidTax: number
}
status: string
created_at: string
updated_at: string
}

View File

@ -7,17 +7,14 @@ const fs = require('fs')
const merge = require('deepmerge')
const prettier = require('prettier')
const PROVIDERS = ['bigcommerce', 'shopify']
const PROVIDERS = ['bigcommerce', 'shopify', 'aquilacms']
function getProviderName() {
return (
process.env.COMMERCE_PROVIDER ||
(process.env.BIGCOMMERCE_STOREFRONT_API_URL
? 'bigcommerce'
: process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN
? 'shopify'
: null)
)
if (process.env.COMMERCE_PROVIDER) return process.env.COMMERCE_PROVIDER
else if (process.env.BIGCOMMERCE_STOREFRONT_API_URL) return 'bigcommerce'
else if (process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN) return 'shopify'
else if (process.env.AQUILACMS_URL) return 'aquilacms'
else return null
}
function withCommerceConfig(nextConfig = {}) {

View File

@ -8,7 +8,13 @@ import {
} from 'react'
import { Fetcher, SWRHook, MutationHook } from './utils/types'
import type { FetchCartInput } from './cart/use-cart'
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
import type {
Cart,
Wishlist,
Customer,
SearchProductsData,
Order,
} from './types'
const Commerce = createContext<CommerceContextValue<any> | {}>({})
@ -36,6 +42,9 @@ export type Provider = CommerceConfig & {
useLogin?: MutationHook<any, any, any>
useLogout?: MutationHook<any, any, any>
}
orders?: {
useOrders?: SWRHook<Order[] | null, any, any>
}
}
export type CommerceProps<P extends Provider> = {

View File

@ -151,6 +151,20 @@ export type RemoveCartItemHandlerBody = Partial<RemoveCartItemBody> & {
cartId?: string
}
export type OrderItem = {}
export type Order = {
id: string
items: OrderItem[]
code: string
price: {
value: number
currency: string
}
status: string
createdAt: string
}
/**
* Temporal types
*/

View File

@ -0,0 +1,3 @@
import ordersApi from '@framework/api/orders'
export default ordersApi()

View File

@ -1,9 +1,10 @@
import type { GetStaticPropsContext } from 'next'
import { Bag } from '@components/icons'
import { Layout } from '@components/common'
import { Container, Text } from '@components/ui'
import { Button, Container, Text } from '@components/ui'
import { getConfig } from '@framework/api'
import getAllPages from '@framework/common/get-all-pages'
import { useOrders } from '../framework/aquilacms/orders'
export async function getStaticProps({
preview,
@ -17,10 +18,35 @@ export async function getStaticProps({
}
export default function Orders() {
const { data: orders } = useOrders()
return (
<Container>
<Text variant="pageHeading">My Orders</Text>
{orders?.length && (
<div className="flex flex-col">
{orders?.map((o) => (
<div className="flex p-5">
<div className="flex-1 justify-center items-center">{o.code}</div>
<div className="flex-1 justify-center items-center">
{o.createdAt}
</div>
<div className="flex-1 justify-center items-center">
{o.price.currency} {o.price.value}
</div>
<Button
Component="a"
className="flex-1 justify-center items-center"
onClick={() => alert(o.id)}
>
View Details
</Button>
</div>
))}
</div>
)}
<div className="flex-1 p-24 flex flex-col justify-center items-center">
{!orders?.length && (
<>
<span className="border border-dashed border-secondary rounded-full flex items-center justify-center w-16 h-16 p-12 bg-primary text-primary">
<Bag className="absolute" />
</span>
@ -30,6 +56,8 @@ export default function Orders() {
<p className="text-accents-6 px-10 text-center pt-2">
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
</p>
</>
)}
</div>
</Container>
)