mirror of
https://github.com/vercel/commerce.git
synced 2025-06-18 21:21:21 +00:00
feat: add useOrders hooks to fetch orders
fix: getProviderName return aquilacms if correct env are sets
This commit is contained in:
parent
0071b6fefc
commit
9df1475c66
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"provider": "aquilacms",
|
|
||||||
"features": {
|
"features": {
|
||||||
"wishlist": false,
|
"wishlist": false,
|
||||||
"customCheckout": false
|
"customCheckout": false
|
||||||
|
35
framework/aquilacms/api/orders/handlers/get-orders.ts
Normal file
35
framework/aquilacms/api/orders/handlers/get-orders.ts
Normal 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
|
47
framework/aquilacms/api/orders/index.ts
Normal file
47
framework/aquilacms/api/orders/index.ts
Normal 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, {})
|
@ -17,8 +17,7 @@ export const handler: SWRHook<
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
},
|
},
|
||||||
async fetcher({ input: { cartId }, options, fetch }) {
|
async fetcher({ input: { cartId }, options, fetch }) {
|
||||||
const data = cartId ? await fetch(options) : null
|
return cartId ? await fetch(options) : null
|
||||||
return data // && normalizeCart(data)
|
|
||||||
},
|
},
|
||||||
useHook: ({ useData }) => (input) => {
|
useHook: ({ useData }) => (input) => {
|
||||||
const response = useData({
|
const response = useData({
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { Product, ProductOption } from '@commerce/types'
|
import type { Product, ProductOption } from '@commerce/types'
|
||||||
import { getConfig } from '../api'
|
|
||||||
import type {
|
import type {
|
||||||
Cart,
|
Cart,
|
||||||
AquilacmsCart,
|
AquilacmsCart,
|
||||||
@ -10,6 +9,8 @@ import type {
|
|||||||
AquilacmsUser,
|
AquilacmsUser,
|
||||||
User,
|
User,
|
||||||
AquilacmsProductAttribute,
|
AquilacmsProductAttribute,
|
||||||
|
AquilacmsOrder,
|
||||||
|
Order,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
|
||||||
function normalizeProductOption(
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
|
1
framework/aquilacms/orders/index.ts
Normal file
1
framework/aquilacms/orders/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as useOrders } from './use-orders'
|
39
framework/aquilacms/orders/use-orders.tsx
Normal file
39
framework/aquilacms/orders/use-orders.tsx
Normal 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,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
@ -10,6 +10,8 @@ import { handler as useLogin } from './auth/use-login'
|
|||||||
import { handler as useLogout } from './auth/use-logout'
|
import { handler as useLogout } from './auth/use-logout'
|
||||||
import { handler as useSignup } from './auth/use-signup'
|
import { handler as useSignup } from './auth/use-signup'
|
||||||
|
|
||||||
|
import { handler as useOrders } from './orders/use-orders'
|
||||||
|
|
||||||
import fetcher from './fetcher'
|
import fetcher from './fetcher'
|
||||||
import { Provider } from '../commerce'
|
import { Provider } from '../commerce'
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ export const aquilacmsProvider = {
|
|||||||
customer: { useCustomer },
|
customer: { useCustomer },
|
||||||
products: { useSearch },
|
products: { useSearch },
|
||||||
auth: { useLogin, useLogout, useSignup },
|
auth: { useLogin, useLogout, useSignup },
|
||||||
|
orders: { useOrders },
|
||||||
} as Provider
|
} as Provider
|
||||||
|
|
||||||
export type AquilacmsProvider = typeof aquilacmsProvider
|
export type AquilacmsProvider = typeof aquilacmsProvider
|
||||||
|
@ -392,6 +392,8 @@ export type RemoveCartItemBody = Core.RemoveCartItemBody
|
|||||||
|
|
||||||
export type RemoveCartItemHandlerBody = Core.RemoveCartItemHandlerBody
|
export type RemoveCartItemHandlerBody = Core.RemoveCartItemHandlerBody
|
||||||
|
|
||||||
|
export type Order = Core.Order
|
||||||
|
|
||||||
export type User = {
|
export type User = {
|
||||||
entityId: string
|
entityId: string
|
||||||
firstName: string
|
firstName: string
|
||||||
@ -434,3 +436,19 @@ export type AquilacmsStatic = {
|
|||||||
}
|
}
|
||||||
name: string
|
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
|
||||||
|
}
|
||||||
|
@ -7,17 +7,14 @@ const fs = require('fs')
|
|||||||
const merge = require('deepmerge')
|
const merge = require('deepmerge')
|
||||||
const prettier = require('prettier')
|
const prettier = require('prettier')
|
||||||
|
|
||||||
const PROVIDERS = ['bigcommerce', 'shopify']
|
const PROVIDERS = ['bigcommerce', 'shopify', 'aquilacms']
|
||||||
|
|
||||||
function getProviderName() {
|
function getProviderName() {
|
||||||
return (
|
if (process.env.COMMERCE_PROVIDER) return process.env.COMMERCE_PROVIDER
|
||||||
process.env.COMMERCE_PROVIDER ||
|
else if (process.env.BIGCOMMERCE_STOREFRONT_API_URL) return 'bigcommerce'
|
||||||
(process.env.BIGCOMMERCE_STOREFRONT_API_URL
|
else if (process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN) return 'shopify'
|
||||||
? 'bigcommerce'
|
else if (process.env.AQUILACMS_URL) return 'aquilacms'
|
||||||
: process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN
|
else return null
|
||||||
? 'shopify'
|
|
||||||
: null)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function withCommerceConfig(nextConfig = {}) {
|
function withCommerceConfig(nextConfig = {}) {
|
||||||
|
@ -8,7 +8,13 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { Fetcher, SWRHook, MutationHook } from './utils/types'
|
import { Fetcher, SWRHook, MutationHook } from './utils/types'
|
||||||
import type { FetchCartInput } from './cart/use-cart'
|
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> | {}>({})
|
const Commerce = createContext<CommerceContextValue<any> | {}>({})
|
||||||
|
|
||||||
@ -36,6 +42,9 @@ export type Provider = CommerceConfig & {
|
|||||||
useLogin?: MutationHook<any, any, any>
|
useLogin?: MutationHook<any, any, any>
|
||||||
useLogout?: MutationHook<any, any, any>
|
useLogout?: MutationHook<any, any, any>
|
||||||
}
|
}
|
||||||
|
orders?: {
|
||||||
|
useOrders?: SWRHook<Order[] | null, any, any>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CommerceProps<P extends Provider> = {
|
export type CommerceProps<P extends Provider> = {
|
||||||
|
@ -151,6 +151,20 @@ export type RemoveCartItemHandlerBody = Partial<RemoveCartItemBody> & {
|
|||||||
cartId?: string
|
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
|
* Temporal types
|
||||||
*/
|
*/
|
||||||
|
3
pages/api/bigcommerce/orders/index.ts
Normal file
3
pages/api/bigcommerce/orders/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import ordersApi from '@framework/api/orders'
|
||||||
|
|
||||||
|
export default ordersApi()
|
@ -1,9 +1,10 @@
|
|||||||
import type { GetStaticPropsContext } from 'next'
|
import type { GetStaticPropsContext } from 'next'
|
||||||
import { Bag } from '@components/icons'
|
import { Bag } from '@components/icons'
|
||||||
import { Layout } from '@components/common'
|
import { Layout } from '@components/common'
|
||||||
import { Container, Text } from '@components/ui'
|
import { Button, Container, Text } from '@components/ui'
|
||||||
import { getConfig } from '@framework/api'
|
import { getConfig } from '@framework/api'
|
||||||
import getAllPages from '@framework/common/get-all-pages'
|
import getAllPages from '@framework/common/get-all-pages'
|
||||||
|
import { useOrders } from '../framework/aquilacms/orders'
|
||||||
|
|
||||||
export async function getStaticProps({
|
export async function getStaticProps({
|
||||||
preview,
|
preview,
|
||||||
@ -17,19 +18,46 @@ export async function getStaticProps({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Orders() {
|
export default function Orders() {
|
||||||
|
const { data: orders } = useOrders()
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Text variant="pageHeading">My Orders</Text>
|
<Text variant="pageHeading">My Orders</Text>
|
||||||
<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">
|
<div className="flex flex-col">
|
||||||
<Bag className="absolute" />
|
{orders?.map((o) => (
|
||||||
</span>
|
<div className="flex p-5">
|
||||||
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
<div className="flex-1 justify-center items-center">{o.code}</div>
|
||||||
No orders found
|
<div className="flex-1 justify-center items-center">
|
||||||
</h2>
|
{o.createdAt}
|
||||||
<p className="text-accents-6 px-10 text-center pt-2">
|
</div>
|
||||||
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
<div className="flex-1 justify-center items-center">
|
||||||
</p>
|
{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>
|
||||||
|
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
||||||
|
No orders found
|
||||||
|
</h2>
|
||||||
|
<p className="text-accents-6 px-10 text-center pt-2">
|
||||||
|
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user