From 9df1475c6629d69c0a5ab55f547a74f0debc4e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Le=20Cloerec?= Date: Wed, 7 Apr 2021 16:04:16 +0200 Subject: [PATCH] feat: add useOrders hooks to fetch orders fix: getProviderName return aquilacms if correct env are sets --- commerce.config.json | 1 - .../api/orders/handlers/get-orders.ts | 35 +++++++++++++ framework/aquilacms/api/orders/index.ts | 47 +++++++++++++++++ framework/aquilacms/cart/use-cart.tsx | 3 +- framework/aquilacms/lib/normalize.ts | 17 ++++++- framework/aquilacms/orders/get-all-orders.ts | 14 ------ framework/aquilacms/orders/index.ts | 1 + framework/aquilacms/orders/use-orders.tsx | 39 +++++++++++++++ framework/aquilacms/provider.ts | 3 ++ framework/aquilacms/types.ts | 18 +++++++ framework/commerce/config.js | 15 +++--- framework/commerce/index.tsx | 11 +++- framework/commerce/types.ts | 14 ++++++ pages/api/bigcommerce/orders/index.ts | 3 ++ pages/orders.tsx | 50 +++++++++++++++---- 15 files changed, 232 insertions(+), 39 deletions(-) create mode 100644 framework/aquilacms/api/orders/handlers/get-orders.ts create mode 100644 framework/aquilacms/api/orders/index.ts delete mode 100644 framework/aquilacms/orders/get-all-orders.ts create mode 100644 framework/aquilacms/orders/index.ts create mode 100644 framework/aquilacms/orders/use-orders.tsx create mode 100644 pages/api/bigcommerce/orders/index.ts diff --git a/commerce.config.json b/commerce.config.json index b00f72faf..06b985504 100644 --- a/commerce.config.json +++ b/commerce.config.json @@ -1,5 +1,4 @@ { - "provider": "aquilacms", "features": { "wishlist": false, "customCheckout": false diff --git a/framework/aquilacms/api/orders/handlers/get-orders.ts b/framework/aquilacms/api/orders/handlers/get-orders.ts new file mode 100644 index 000000000..58c5d79b5 --- /dev/null +++ b/framework/aquilacms/api/orders/handlers/get-orders.ts @@ -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 diff --git a/framework/aquilacms/api/orders/index.ts b/framework/aquilacms/api/orders/index.ts new file mode 100644 index 000000000..de938ca47 --- /dev/null +++ b/framework/aquilacms/api/orders/index.ts @@ -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 +} + +const METHODS = ['POST'] + +const ordersApi: AquilacmsApiHandler = 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, {}) diff --git a/framework/aquilacms/cart/use-cart.tsx b/framework/aquilacms/cart/use-cart.tsx index 78ae63fc8..5dbee0a74 100644 --- a/framework/aquilacms/cart/use-cart.tsx +++ b/framework/aquilacms/cart/use-cart.tsx @@ -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({ diff --git a/framework/aquilacms/lib/normalize.ts b/framework/aquilacms/lib/normalize.ts index 13485f4af..3465b9ba9 100644 --- a/framework/aquilacms/lib/normalize.ts +++ b/framework/aquilacms/lib/normalize.ts @@ -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, + } +} diff --git a/framework/aquilacms/orders/get-all-orders.ts b/framework/aquilacms/orders/get-all-orders.ts deleted file mode 100644 index 9085295a7..000000000 --- a/framework/aquilacms/orders/get-all-orders.ts +++ /dev/null @@ -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 diff --git a/framework/aquilacms/orders/index.ts b/framework/aquilacms/orders/index.ts new file mode 100644 index 000000000..93f35b887 --- /dev/null +++ b/framework/aquilacms/orders/index.ts @@ -0,0 +1 @@ +export { default as useOrders } from './use-orders' diff --git a/framework/aquilacms/orders/use-orders.tsx b/framework/aquilacms/orders/use-orders.tsx new file mode 100644 index 000000000..6d30dff31 --- /dev/null +++ b/framework/aquilacms/orders/use-orders.tsx @@ -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 = SWRHook +> = ReturnType + +const fetcher: HookFetcherFn = 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 + +export const handler: SWRHook = { + fetchOptions: { + url: '/api/bigcommerce/orders', + method: 'POST', + }, + async fetcher({ options, fetch }) { + const data = await fetch(options) + return data?.orders ?? null + }, + useHook: ({ useData }) => (input) => { + return useData({ + swrOptions: { + revalidateOnFocus: false, + ...input?.swrOptions, + }, + }) + }, +} diff --git a/framework/aquilacms/provider.ts b/framework/aquilacms/provider.ts index 981ee14f1..bf977d355 100644 --- a/framework/aquilacms/provider.ts +++ b/framework/aquilacms/provider.ts @@ -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 diff --git a/framework/aquilacms/types.ts b/framework/aquilacms/types.ts index aa53b6c98..4da66a8ef 100644 --- a/framework/aquilacms/types.ts +++ b/framework/aquilacms/types.ts @@ -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 +} diff --git a/framework/commerce/config.js b/framework/commerce/config.js index 2dd3284bc..7baca09e8 100644 --- a/framework/commerce/config.js +++ b/framework/commerce/config.js @@ -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 = {}) { diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx index 07bf74a22..12e5aad9f 100644 --- a/framework/commerce/index.tsx +++ b/framework/commerce/index.tsx @@ -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 | {}>({}) @@ -36,6 +42,9 @@ export type Provider = CommerceConfig & { useLogin?: MutationHook useLogout?: MutationHook } + orders?: { + useOrders?: SWRHook + } } export type CommerceProps

= { diff --git a/framework/commerce/types.ts b/framework/commerce/types.ts index 1d72d7563..be9dc4c72 100644 --- a/framework/commerce/types.ts +++ b/framework/commerce/types.ts @@ -151,6 +151,20 @@ export type RemoveCartItemHandlerBody = Partial & { 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 */ diff --git a/pages/api/bigcommerce/orders/index.ts b/pages/api/bigcommerce/orders/index.ts new file mode 100644 index 000000000..9f1a94886 --- /dev/null +++ b/pages/api/bigcommerce/orders/index.ts @@ -0,0 +1,3 @@ +import ordersApi from '@framework/api/orders' + +export default ordersApi() diff --git a/pages/orders.tsx b/pages/orders.tsx index db4ab55b2..887e66e14 100644 --- a/pages/orders.tsx +++ b/pages/orders.tsx @@ -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,19 +18,46 @@ export async function getStaticProps({ } export default function Orders() { + const { data: orders } = useOrders() return ( My Orders -

- - - -

- No orders found -

-

- Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake. -

+ {orders?.length && ( +
+ {orders?.map((o) => ( +
+
{o.code}
+
+ {o.createdAt} +
+
+ {o.price.currency} {o.price.value} +
+ +
+ ))} +
+ )} +
+ {!orders?.length && ( + <> + + + +

+ No orders found +

+

+ Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake. +

+ + )}
)