From 1720bd698cc3c4f1b93312e9f9ae8c27f54c1d56 Mon Sep 17 00:00:00 2001 From: Gonzalo Pozzo Date: Wed, 22 Sep 2021 21:20:58 -0300 Subject: [PATCH] Implement custom checkout (#487) * Implement custom checkout core * Fix elements on core * Add files to providers * Adapt providers * Update types * Update shopify file * Format files --- .../CheckoutSidebarView.tsx | 61 ++++--- .../PaymentMethodView/PaymentMethodView.tsx | 168 +++++++++++------- .../checkout/PaymentWidget/PaymentWidget.tsx | 13 +- .../checkout/ShippingView/ShippingView.tsx | 156 ++++++++++------ .../ShippingWidget/ShippingWidget.tsx | 13 +- .../api/endpoints/checkout/index.ts | 4 +- .../{checkout.ts => submit-checkout.ts} | 4 +- .../api/endpoints/customer/address.ts | 1 + .../api/endpoints/customer/card.ts | 1 + .../bigcommerce/checkout/use-checkout.tsx | 14 ++ .../customer/address/use-add-item.tsx | 15 ++ .../customer/card/use-add-item.tsx | 15 ++ framework/commerce/api/endpoints/checkout.ts | 24 ++- .../api/endpoints/customer/address.ts | 65 +++++++ .../commerce/api/endpoints/customer/card.ts | 65 +++++++ .../{customer.ts => customer/index.ts} | 9 +- framework/commerce/api/index.ts | 4 + framework/commerce/checkout/use-checkout.ts | 34 ++++ .../commerce/checkout/use-submit-checkout.tsx | 23 +++ .../customer/address/use-add-item.tsx | 21 +++ .../customer/address/use-addresses.tsx | 34 ++++ .../customer/address/use-remove-item.tsx | 21 +++ .../customer/address/use-update-item.tsx | 21 +++ .../commerce/customer/card/use-add-item.tsx | 21 +++ .../commerce/customer/card/use-cards.tsx | 34 ++++ .../customer/card/use-remove-item.tsx | 21 +++ .../customer/card/use-update-item.tsx | 21 +++ framework/commerce/index.tsx | 17 ++ framework/commerce/types/checkout.ts | 59 +++++- framework/commerce/types/customer/address.ts | 93 ++++++++++ framework/commerce/types/customer/card.ts | 96 ++++++++++ .../types/{customer.ts => customer/index.ts} | 3 + framework/commerce/utils/types.ts | 4 +- .../local/api/endpoints/customer/address.ts | 1 + .../local/api/endpoints/customer/card.ts | 1 + framework/local/checkout/use-checkout.tsx | 14 ++ .../local/customer/address/use-add-item.tsx | 15 ++ .../local/customer/card/use-add-item.tsx | 15 ++ .../saleor/api/endpoints/checkout/index.ts | 8 +- framework/saleor/api/endpoints/customer.ts | 1 - .../saleor/api/endpoints/customer/address.ts | 1 + .../saleor/api/endpoints/customer/card.ts | 1 + .../saleor/api/endpoints/customer/index.ts | 1 + framework/saleor/checkout/use-checkout.tsx | 14 ++ .../saleor/customer/address/use-add-item.tsx | 15 ++ .../saleor/customer/card/use-add-item.tsx | 15 ++ .../shopify/api/endpoints/checkout/index.ts | 4 +- .../{checkout.ts => submit-checkout.ts} | 4 +- framework/shopify/api/endpoints/customer.ts | 1 - .../shopify/api/endpoints/customer/address.ts | 1 + .../shopify/api/endpoints/customer/card.ts | 1 + .../shopify/api/endpoints/customer/index.ts | 1 + framework/shopify/checkout/use-checkout.tsx | 14 ++ .../shopify/customer/address/use-add-item.tsx | 15 ++ .../shopify/customer/card/use-add-item.tsx | 15 ++ .../swell/api/endpoints/checkout/index.ts | 4 +- framework/swell/api/endpoints/customer.ts | 1 - .../swell/api/endpoints/customer/address.ts | 1 + .../swell/api/endpoints/customer/card.ts | 1 + .../swell/api/endpoints/customer/index.ts | 1 + framework/swell/checkout/use-checkout.tsx | 14 ++ .../swell/customer/address/use-add-item.tsx | 15 ++ .../swell/customer/card/use-add-item.tsx | 15 ++ .../vendure/api/endpoints/checkout/index.ts | 4 +- .../vendure/api/endpoints/customer/address.ts | 1 + .../vendure/api/endpoints/customer/card.ts | 1 + framework/vendure/checkout/use-checkout.tsx | 14 ++ .../vendure/customer/address/use-add-item.tsx | 15 ++ .../vendure/customer/card/use-add-item.tsx | 15 ++ pages/api/customer/address.ts | 4 + pages/api/customer/card.ts | 4 + pages/api/{customer.ts => customer/index.ts} | 0 72 files changed, 1232 insertions(+), 191 deletions(-) rename framework/bigcommerce/api/endpoints/checkout/{checkout.ts => submit-checkout.ts} (95%) create mode 100644 framework/bigcommerce/api/endpoints/customer/address.ts create mode 100644 framework/bigcommerce/api/endpoints/customer/card.ts create mode 100644 framework/bigcommerce/checkout/use-checkout.tsx create mode 100644 framework/bigcommerce/customer/address/use-add-item.tsx create mode 100644 framework/bigcommerce/customer/card/use-add-item.tsx create mode 100644 framework/commerce/api/endpoints/customer/address.ts create mode 100644 framework/commerce/api/endpoints/customer/card.ts rename framework/commerce/api/endpoints/{customer.ts => customer/index.ts} (75%) create mode 100644 framework/commerce/checkout/use-checkout.ts create mode 100644 framework/commerce/checkout/use-submit-checkout.tsx create mode 100644 framework/commerce/customer/address/use-add-item.tsx create mode 100644 framework/commerce/customer/address/use-addresses.tsx create mode 100644 framework/commerce/customer/address/use-remove-item.tsx create mode 100644 framework/commerce/customer/address/use-update-item.tsx create mode 100644 framework/commerce/customer/card/use-add-item.tsx create mode 100644 framework/commerce/customer/card/use-cards.tsx create mode 100644 framework/commerce/customer/card/use-remove-item.tsx create mode 100644 framework/commerce/customer/card/use-update-item.tsx create mode 100644 framework/commerce/types/customer/address.ts create mode 100644 framework/commerce/types/customer/card.ts rename framework/commerce/types/{customer.ts => customer/index.ts} (87%) create mode 100644 framework/local/api/endpoints/customer/address.ts create mode 100644 framework/local/api/endpoints/customer/card.ts create mode 100644 framework/local/checkout/use-checkout.tsx create mode 100644 framework/local/customer/address/use-add-item.tsx create mode 100644 framework/local/customer/card/use-add-item.tsx delete mode 100644 framework/saleor/api/endpoints/customer.ts create mode 100644 framework/saleor/api/endpoints/customer/address.ts create mode 100644 framework/saleor/api/endpoints/customer/card.ts create mode 100644 framework/saleor/api/endpoints/customer/index.ts create mode 100644 framework/saleor/checkout/use-checkout.tsx create mode 100644 framework/saleor/customer/address/use-add-item.tsx create mode 100644 framework/saleor/customer/card/use-add-item.tsx rename framework/shopify/api/endpoints/checkout/{checkout.ts => submit-checkout.ts} (88%) delete mode 100644 framework/shopify/api/endpoints/customer.ts create mode 100644 framework/shopify/api/endpoints/customer/address.ts create mode 100644 framework/shopify/api/endpoints/customer/card.ts create mode 100644 framework/shopify/api/endpoints/customer/index.ts create mode 100644 framework/shopify/checkout/use-checkout.tsx create mode 100644 framework/shopify/customer/address/use-add-item.tsx create mode 100644 framework/shopify/customer/card/use-add-item.tsx delete mode 100644 framework/swell/api/endpoints/customer.ts create mode 100644 framework/swell/api/endpoints/customer/address.ts create mode 100644 framework/swell/api/endpoints/customer/card.ts create mode 100644 framework/swell/api/endpoints/customer/index.ts create mode 100644 framework/swell/checkout/use-checkout.tsx create mode 100644 framework/swell/customer/address/use-add-item.tsx create mode 100644 framework/swell/customer/card/use-add-item.tsx create mode 100644 framework/vendure/api/endpoints/customer/address.ts create mode 100644 framework/vendure/api/endpoints/customer/card.ts create mode 100644 framework/vendure/checkout/use-checkout.tsx create mode 100644 framework/vendure/customer/address/use-add-item.tsx create mode 100644 framework/vendure/customer/card/use-add-item.tsx create mode 100644 pages/api/customer/address.ts create mode 100644 pages/api/customer/card.ts rename pages/api/{customer.ts => customer/index.ts} (100%) diff --git a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx b/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx index fb562e7af..13a523288 100644 --- a/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx +++ b/components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx @@ -1,30 +1,39 @@ -import cn from 'classnames' import Link from 'next/link' import { FC } from 'react' import CartItem from '@components/cart/CartItem' import { Button, Text } from '@components/ui' import { useUI } from '@components/ui/context' +import SidebarLayout from '@components/common/SidebarLayout' import useCart from '@framework/cart/use-cart' import usePrice from '@framework/product/use-price' +import useCheckout from '@framework/checkout/use-checkout' import ShippingWidget from '../ShippingWidget' import PaymentWidget from '../PaymentWidget' -import SidebarLayout from '@components/common/SidebarLayout' import s from './CheckoutSidebarView.module.css' const CheckoutSidebarView: FC = () => { - const { setSidebarView } = useUI() - const { data } = useCart() + const { setSidebarView, closeSidebar } = useUI() + const { data: cartData } = useCart() + const { data: checkoutData, submit: onCheckout } = useCheckout() + + async function handleSubmit(event: React.ChangeEvent) { + event.preventDefault() + + await onCheckout() + + closeSidebar() + } const { price: subTotal } = usePrice( - data && { - amount: Number(data.subtotalPrice), - currencyCode: data.currency.code, + cartData && { + amount: Number(cartData.subtotalPrice), + currencyCode: cartData.currency.code, } ) const { price: total } = usePrice( - data && { - amount: Number(data.totalPrice), - currencyCode: data.currency.code, + cartData && { + amount: Number(cartData.totalPrice), + currencyCode: cartData.currency.code, } ) @@ -38,22 +47,31 @@ const CheckoutSidebarView: FC = () => { Checkout - setSidebarView('PAYMENT_VIEW')} /> - setSidebarView('SHIPPING_VIEW')} /> + setSidebarView('PAYMENT_VIEW')} + /> + setSidebarView('SHIPPING_VIEW')} + />
    - {data!.lineItems.map((item: any) => ( + {cartData!.lineItems.map((item: any) => ( ))}
-
+
  • Subtotal @@ -74,14 +92,15 @@ const CheckoutSidebarView: FC = () => {
{/* Once data is correcly filled */} - {/* */} -
- + ) } diff --git a/components/checkout/PaymentMethodView/PaymentMethodView.tsx b/components/checkout/PaymentMethodView/PaymentMethodView.tsx index a5f6f4b51..972073756 100644 --- a/components/checkout/PaymentMethodView/PaymentMethodView.tsx +++ b/components/checkout/PaymentMethodView/PaymentMethodView.tsx @@ -1,83 +1,129 @@ import { FC } from 'react' import cn from 'classnames' + +import useAddCard from '@framework/customer/card/use-add-item' import { Button, Text } from '@components/ui' import { useUI } from '@components/ui/context' -import s from './PaymentMethodView.module.css' import SidebarLayout from '@components/common/SidebarLayout' +import s from './PaymentMethodView.module.css' + +interface Form extends HTMLFormElement { + cardHolder: HTMLInputElement + cardNumber: HTMLInputElement + cardExpireDate: HTMLInputElement + cardCvc: HTMLInputElement + firstName: HTMLInputElement + lastName: HTMLInputElement + company: HTMLInputElement + streetNumber: HTMLInputElement + zipCode: HTMLInputElement + city: HTMLInputElement + country: HTMLSelectElement +} + const PaymentMethodView: FC = () => { const { setSidebarView } = useUI() + const addCard = useAddCard() + + async function handleSubmit(event: React.ChangeEvent
) { + event.preventDefault() + + await addCard({ + cardHolder: event.target.cardHolder.value, + cardNumber: event.target.cardNumber.value, + cardExpireDate: event.target.cardExpireDate.value, + cardCvc: event.target.cardCvc.value, + firstName: event.target.firstName.value, + lastName: event.target.lastName.value, + company: event.target.company.value, + streetNumber: event.target.streetNumber.value, + zipCode: event.target.zipCode.value, + city: event.target.city.value, + country: event.target.country.value, + }) + + setSidebarView('CHECKOUT_VIEW') + } return ( - setSidebarView('CHECKOUT_VIEW')}> -
- Payment Method -
-
- - -
-
-
- - + + setSidebarView('CHECKOUT_VIEW')}> +
+ Payment Method +
+
+ +
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
- - +
+
+
+ + +
+
+ + +
-
-
-
-
- - +
+ +
-
- - +
+ +
-
-
- - -
-
- - -
-
- - -
-
-
- - +
+ +
-
- - +
+
+ + +
+
+ + +
+
+
+ +
-
-
- -
-
-
- -
- +
+ +
+ + ) } diff --git a/components/checkout/PaymentWidget/PaymentWidget.tsx b/components/checkout/PaymentWidget/PaymentWidget.tsx index e1892934e..9b496bb44 100644 --- a/components/checkout/PaymentWidget/PaymentWidget.tsx +++ b/components/checkout/PaymentWidget/PaymentWidget.tsx @@ -1,14 +1,15 @@ import { FC } from 'react' import s from './PaymentWidget.module.css' -import { ChevronRight, CreditCard } from '@components/icons' +import { ChevronRight, CreditCard, Check } from '@components/icons' interface ComponentProps { onClick?: () => any + isValid?: boolean } -const PaymentWidget: FC = ({ onClick }) => { - /* Shipping Address - Only available with checkout set to true - +const PaymentWidget: FC = ({ onClick, isValid }) => { + /* Shipping Address + Only available with checkout set to true - This means that the provider does offer checkout functionality. */ return (
@@ -19,9 +20,7 @@ const PaymentWidget: FC = ({ onClick }) => { {/* VISA #### #### #### 2345 */}
-
- -
+
{isValid ? : }
) } diff --git a/components/checkout/ShippingView/ShippingView.tsx b/components/checkout/ShippingView/ShippingView.tsx index 1d03a2aac..ed82bc8a2 100644 --- a/components/checkout/ShippingView/ShippingView.tsx +++ b/components/checkout/ShippingView/ShippingView.tsx @@ -1,77 +1,117 @@ import { FC } from 'react' import cn from 'classnames' -import s from './ShippingView.module.css' + import Button from '@components/ui/Button' import { useUI } from '@components/ui/context' import SidebarLayout from '@components/common/SidebarLayout' +import useAddAddress from '@framework/customer/address/use-add-item' + +import s from './ShippingView.module.css' + +interface Form extends HTMLFormElement { + cardHolder: HTMLInputElement + cardNumber: HTMLInputElement + cardExpireDate: HTMLInputElement + cardCvc: HTMLInputElement + firstName: HTMLInputElement + lastName: HTMLInputElement + company: HTMLInputElement + streetNumber: HTMLInputElement + zipCode: HTMLInputElement + city: HTMLInputElement + country: HTMLSelectElement +} const PaymentMethodView: FC = () => { const { setSidebarView } = useUI() + const addAddress = useAddAddress() + + async function handleSubmit(event: React.ChangeEvent
) { + event.preventDefault() + + await addAddress({ + type: event.target.type.value, + firstName: event.target.firstName.value, + lastName: event.target.lastName.value, + company: event.target.company.value, + streetNumber: event.target.streetNumber.value, + apartments: event.target.streetNumber.value, + zipCode: event.target.zipCode.value, + city: event.target.city.value, + country: event.target.country.value, + }) + + setSidebarView('CHECKOUT_VIEW') + } return ( - setSidebarView('CHECKOUT_VIEW')}> -
-

- Shipping -

-
-
- - Same as billing address -
-
- - - Use a different shipping address - -
-
-
-
- - + + setSidebarView('CHECKOUT_VIEW')}> +
+

+ Shipping +

+
+
+ + Same as billing address
-
- - +
+ + + Use a different shipping address +
-
-
- - -
-
- - -
-
- - -
-
-
- - +
+
+
+ + +
+
+ + +
-
- - +
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
-
-
- -
-
-
- -
- +
+ +
+ + ) } diff --git a/components/checkout/ShippingWidget/ShippingWidget.tsx b/components/checkout/ShippingWidget/ShippingWidget.tsx index b072178b0..557a69a8b 100644 --- a/components/checkout/ShippingWidget/ShippingWidget.tsx +++ b/components/checkout/ShippingWidget/ShippingWidget.tsx @@ -1,15 +1,16 @@ import { FC } from 'react' import s from './ShippingWidget.module.css' -import { ChevronRight, MapPin } from '@components/icons' +import { ChevronRight, MapPin, Check } from '@components/icons' import cn from 'classnames' interface ComponentProps { onClick?: () => any + isValid?: boolean } -const ShippingWidget: FC = ({ onClick }) => { - /* Shipping Address - Only available with checkout set to true - +const ShippingWidget: FC = ({ onClick, isValid }) => { + /* Shipping Address + Only available with checkout set to true - This means that the provider does offer checkout functionality. */ return (
@@ -23,9 +24,7 @@ const ShippingWidget: FC = ({ onClick }) => { San Franssisco, California */}
-
- -
+
{isValid ? : }
) } diff --git a/framework/bigcommerce/api/endpoints/checkout/index.ts b/framework/bigcommerce/api/endpoints/checkout/index.ts index eaba32e47..99263bdb7 100644 --- a/framework/bigcommerce/api/endpoints/checkout/index.ts +++ b/framework/bigcommerce/api/endpoints/checkout/index.ts @@ -2,13 +2,13 @@ import { GetAPISchema, createEndpoint } from '@commerce/api' import checkoutEndpoint from '@commerce/api/endpoints/checkout' import type { CheckoutSchema } from '../../../types/checkout' import type { BigcommerceAPI } from '../..' -import checkout from './checkout' +import submitCheckout from './submit-checkout' export type CheckoutAPI = GetAPISchema export type CheckoutEndpoint = CheckoutAPI['endpoint'] -export const handlers: CheckoutEndpoint['handlers'] = { checkout } +export const handlers: CheckoutEndpoint['handlers'] = { submitCheckout } const checkoutApi = createEndpoint({ handler: checkoutEndpoint, diff --git a/framework/bigcommerce/api/endpoints/checkout/checkout.ts b/framework/bigcommerce/api/endpoints/checkout/submit-checkout.ts similarity index 95% rename from framework/bigcommerce/api/endpoints/checkout/checkout.ts rename to framework/bigcommerce/api/endpoints/checkout/submit-checkout.ts index 15c834557..5c135df36 100644 --- a/framework/bigcommerce/api/endpoints/checkout/checkout.ts +++ b/framework/bigcommerce/api/endpoints/checkout/submit-checkout.ts @@ -5,7 +5,7 @@ import { uuid } from 'uuidv4' const fullCheckout = true -const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ +const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({ req, res, config, @@ -87,4 +87,4 @@ const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ res.end() } -export default checkout +export default submitCheckout diff --git a/framework/bigcommerce/api/endpoints/customer/address.ts b/framework/bigcommerce/api/endpoints/customer/address.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/bigcommerce/api/endpoints/customer/address.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/bigcommerce/api/endpoints/customer/card.ts b/framework/bigcommerce/api/endpoints/customer/card.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/bigcommerce/api/endpoints/customer/card.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/bigcommerce/checkout/use-checkout.tsx b/framework/bigcommerce/checkout/use-checkout.tsx new file mode 100644 index 000000000..942f85b83 --- /dev/null +++ b/framework/bigcommerce/checkout/use-checkout.tsx @@ -0,0 +1,14 @@ +import { SWRHook } from '@commerce/utils/types' +import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout' + +export default useCheckout as UseCheckout + +export const handler: SWRHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ useData }) => + async (input) => ({}), +} diff --git a/framework/bigcommerce/customer/address/use-add-item.tsx b/framework/bigcommerce/customer/address/use-add-item.tsx new file mode 100644 index 000000000..ac9dcd5cf --- /dev/null +++ b/framework/bigcommerce/customer/address/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/bigcommerce/customer/card/use-add-item.tsx b/framework/bigcommerce/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7e3afa9c5 --- /dev/null +++ b/framework/bigcommerce/customer/card/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/commerce/api/endpoints/checkout.ts b/framework/commerce/api/endpoints/checkout.ts index b39239a6a..b00bce284 100644 --- a/framework/commerce/api/endpoints/checkout.ts +++ b/framework/commerce/api/endpoints/checkout.ts @@ -1,25 +1,39 @@ import type { CheckoutSchema } from '../../types/checkout' +import type { GetAPISchema } from '..' + import { CommerceAPIError } from '../utils/errors' import isAllowedOperation from '../utils/is-allowed-operation' -import type { GetAPISchema } from '..' const checkoutEndpoint: GetAPISchema< any, CheckoutSchema >['endpoint']['handler'] = async (ctx) => { - const { req, res, handlers } = ctx + const { req, res, handlers, config } = ctx if ( !isAllowedOperation(req, res, { - GET: handlers['checkout'], + GET: handlers['getCheckout'], + POST: handlers['submitCheckout'], }) ) { return } + const { cookies } = req + const cartId = cookies[config.cartCookie] + try { - const body = null - return await handlers['checkout']({ ...ctx, body }) + // Create checkout + if (req.method === 'GET') { + const body = { ...req.body, cartId } + return await handlers['getCheckout']?.({ ...ctx, body }) + } + + // Create checkout + if (req.method === 'POST') { + const body = { ...req.body, cartId } + return await handlers['submitCheckout']({ ...ctx, body }) + } } catch (error) { console.error(error) diff --git a/framework/commerce/api/endpoints/customer/address.ts b/framework/commerce/api/endpoints/customer/address.ts new file mode 100644 index 000000000..d5ede697a --- /dev/null +++ b/framework/commerce/api/endpoints/customer/address.ts @@ -0,0 +1,65 @@ +import type { CustomerAddressSchema } from '../../../types/customer/address' +import type { GetAPISchema } from '../..' + +import { CommerceAPIError } from '../../utils/errors' +import isAllowedOperation from '../../utils/is-allowed-operation' + +const customerShippingEndpoint: GetAPISchema< + any, + CustomerAddressSchema +>['endpoint']['handler'] = async (ctx) => { + const { req, res, handlers, config } = ctx + + if ( + !isAllowedOperation(req, res, { + GET: handlers['getAddresses'], + POST: handlers['addItem'], + PUT: handlers['updateItem'], + DELETE: handlers['removeItem'], + }) + ) { + return + } + + const { cookies } = req + + // Cart id might be usefull for anonymous shopping + const cartId = cookies[config.cartCookie] + + try { + // Return customer addresses + if (req.method === 'GET') { + const body = { cartId } + return await handlers['getAddresses']({ ...ctx, body }) + } + + // Create or add an item to customer addresses list + if (req.method === 'POST') { + const body = { ...req.body, cartId } + return await handlers['addItem']({ ...ctx, body }) + } + + // Update item in customer addresses list + if (req.method === 'PUT') { + const body = { ...req.body, cartId } + return await handlers['updateItem']({ ...ctx, body }) + } + + // Remove an item from customer addresses list + if (req.method === 'DELETE') { + const body = { ...req.body, cartId } + return await handlers['removeItem']({ ...ctx, body }) + } + } catch (error) { + console.error(error) + + const message = + error instanceof CommerceAPIError + ? 'An unexpected error ocurred with the Commerce API' + : 'An unexpected error ocurred' + + res.status(500).json({ data: null, errors: [{ message }] }) + } +} + +export default customerShippingEndpoint diff --git a/framework/commerce/api/endpoints/customer/card.ts b/framework/commerce/api/endpoints/customer/card.ts new file mode 100644 index 000000000..ad268cbb9 --- /dev/null +++ b/framework/commerce/api/endpoints/customer/card.ts @@ -0,0 +1,65 @@ +import type { CustomerCardSchema } from '../../../types/customer/card' +import type { GetAPISchema } from '../..' + +import { CommerceAPIError } from '../../utils/errors' +import isAllowedOperation from '../../utils/is-allowed-operation' + +const customerCardEndpoint: GetAPISchema< + any, + CustomerCardSchema +>['endpoint']['handler'] = async (ctx) => { + const { req, res, handlers, config } = ctx + + if ( + !isAllowedOperation(req, res, { + GET: handlers['getCards'], + POST: handlers['addItem'], + PUT: handlers['updateItem'], + DELETE: handlers['removeItem'], + }) + ) { + return + } + + const { cookies } = req + + // Cart id might be usefull for anonymous shopping + const cartId = cookies[config.cartCookie] + + try { + // Create or add a card + if (req.method === 'GET') { + const body = { ...req.body } + return await handlers['getCards']({ ...ctx, body }) + } + + // Create or add an item to customer cards + if (req.method === 'POST') { + const body = { ...req.body, cartId } + return await handlers['addItem']({ ...ctx, body }) + } + + // Update item in customer cards + if (req.method === 'PUT') { + const body = { ...req.body, cartId } + return await handlers['updateItem']({ ...ctx, body }) + } + + // Remove an item from customer cards + if (req.method === 'DELETE') { + const body = { ...req.body, cartId } + return await handlers['removeItem']({ ...ctx, body }) + } + } catch (error) { + console.error(error) + + const message = + error instanceof CommerceAPIError + ? 'An unexpected error ocurred with the Commerce API' + : 'An unexpected error ocurred' + + res.status(500).json({ data: null, errors: [{ message }] }) + } +} + +export default customerCardEndpoint diff --git a/framework/commerce/api/endpoints/customer.ts b/framework/commerce/api/endpoints/customer/index.ts similarity index 75% rename from framework/commerce/api/endpoints/customer.ts rename to framework/commerce/api/endpoints/customer/index.ts index 6372c494f..eb2a048b7 100644 --- a/framework/commerce/api/endpoints/customer.ts +++ b/framework/commerce/api/endpoints/customer/index.ts @@ -1,7 +1,8 @@ -import type { CustomerSchema } from '../../types/customer' -import { CommerceAPIError } from '../utils/errors' -import isAllowedOperation from '../utils/is-allowed-operation' -import type { GetAPISchema } from '..' +import type { CustomerSchema } from '../../../types/customer' +import type { GetAPISchema } from '../..' + +import { CommerceAPIError } from '../../utils/errors' +import isAllowedOperation from '../../utils/is-allowed-operation' const customerEndpoint: GetAPISchema< any, diff --git a/framework/commerce/api/index.ts b/framework/commerce/api/index.ts index 32fe8cf80..716c11ed5 100644 --- a/framework/commerce/api/index.ts +++ b/framework/commerce/api/index.ts @@ -9,6 +9,8 @@ import type { SignupSchema } from '../types/signup' import type { ProductsSchema } from '../types/product' import type { WishlistSchema } from '../types/wishlist' import type { CheckoutSchema } from '../types/checkout' +import type { CustomerCardSchema } from '../types/customer/card' +import type { CustomerAddressSchema } from '../types/customer/address' import { defaultOperations, OPERATIONS, @@ -25,6 +27,8 @@ export type APISchemas = | ProductsSchema | WishlistSchema | CheckoutSchema + | CustomerCardSchema + | CustomerAddressSchema export type GetAPISchema< C extends CommerceAPI, diff --git a/framework/commerce/checkout/use-checkout.ts b/framework/commerce/checkout/use-checkout.ts new file mode 100644 index 000000000..0fe74cb28 --- /dev/null +++ b/framework/commerce/checkout/use-checkout.ts @@ -0,0 +1,34 @@ +import type { SWRHook, HookFetcherFn } from '../utils/types' +import type { GetCheckoutHook } from '../types/checkout' + +import Cookies from 'js-cookie' + +import { useHook, useSWRHook } from '../utils/use-hook' +import { Provider, useCommerce } from '..' + +export type UseCheckout< + H extends SWRHook> = SWRHook +> = ReturnType + +export const fetcher: HookFetcherFn = async ({ + options, + input: { cartId }, + fetch, +}) => { + return cartId ? await fetch(options) : null +} + +const fn = (provider: Provider) => provider.checkout?.useCheckout! + +const useCheckout: UseCheckout = (input) => { + const hook = useHook(fn) + const { cartCookie } = useCommerce() + const fetcherFn = hook.fetcher ?? fetcher + const wrapper: typeof fetcher = (context) => { + context.input.cartId = Cookies.get(cartCookie) + return fetcherFn(context) + } + return useSWRHook({ ...hook, fetcher: wrapper })(input) +} + +export default useCheckout diff --git a/framework/commerce/checkout/use-submit-checkout.tsx b/framework/commerce/checkout/use-submit-checkout.tsx new file mode 100644 index 000000000..a5d865002 --- /dev/null +++ b/framework/commerce/checkout/use-submit-checkout.tsx @@ -0,0 +1,23 @@ +import type { HookFetcherFn, MutationHook } from '../utils/types' +import type { SubmitCheckoutHook } from '../types/checkout' +import type { Provider } from '..' + +import { useHook, useMutationHook } from '../utils/use-hook' +import { mutationFetcher } from '../utils/default-fetcher' + +export type UseSubmitCheckout< + H extends MutationHook< + SubmitCheckoutHook + > = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider.checkout?.useSubmitCheckout! + +const useSubmitCheckout: UseSubmitCheckout = (...args) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(...args) +} + +export default useSubmitCheckout diff --git a/framework/commerce/customer/address/use-add-item.tsx b/framework/commerce/customer/address/use-add-item.tsx new file mode 100644 index 000000000..94c45142e --- /dev/null +++ b/framework/commerce/customer/address/use-add-item.tsx @@ -0,0 +1,21 @@ +import type { HookFetcherFn, MutationHook } from '../../utils/types' +import type { AddItemHook } from '../../types/customer/address' +import type { Provider } from '../..' + +import { useHook, useMutationHook } from '../../utils/use-hook' +import { mutationFetcher } from '../../utils/default-fetcher' + +export type UseAddItem< + H extends MutationHook> = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider.customer?.address?.useAddItem! + +const useAddItem: UseAddItem = (...args) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(...args) +} + +export default useAddItem diff --git a/framework/commerce/customer/address/use-addresses.tsx b/framework/commerce/customer/address/use-addresses.tsx new file mode 100644 index 000000000..7fc12924c --- /dev/null +++ b/framework/commerce/customer/address/use-addresses.tsx @@ -0,0 +1,34 @@ +import type { SWRHook, HookFetcherFn } from '../../utils/types' +import type { GetAddressesHook } from '../../types/customer/address' + +import Cookies from 'js-cookie' + +import { useHook, useSWRHook } from '../../utils/use-hook' +import { Provider, useCommerce } from '../..' + +export type UseAddresses< + H extends SWRHook> = SWRHook +> = ReturnType + +export const fetcher: HookFetcherFn = async ({ + options, + input: { cartId }, + fetch, +}) => { + return cartId ? await fetch(options) : null +} + +const fn = (provider: Provider) => provider.customer?.address?.useAddresses! + +const useAddresses: UseAddresses = (input) => { + const hook = useHook(fn) + const { cartCookie } = useCommerce() + const fetcherFn = hook.fetcher ?? fetcher + const wrapper: typeof fetcher = (context) => { + context.input.cartId = Cookies.get(cartCookie) + return fetcherFn(context) + } + return useSWRHook({ ...hook, fetcher: wrapper })(input) +} + +export default useAddresses diff --git a/framework/commerce/customer/address/use-remove-item.tsx b/framework/commerce/customer/address/use-remove-item.tsx new file mode 100644 index 000000000..820a65dad --- /dev/null +++ b/framework/commerce/customer/address/use-remove-item.tsx @@ -0,0 +1,21 @@ +import type { HookFetcherFn, MutationHook } from '../../utils/types' +import type { RemoveItemHook } from '../../types/customer/address' +import type { Provider } from '../..' + +import { useHook, useMutationHook } from '../../utils/use-hook' +import { mutationFetcher } from '../../utils/default-fetcher' + +export type UseRemoveItem< + H extends MutationHook> = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider.customer?.address?.useRemoveItem! + +const useRemoveItem: UseRemoveItem = (input) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(input) +} + +export default useRemoveItem diff --git a/framework/commerce/customer/address/use-update-item.tsx b/framework/commerce/customer/address/use-update-item.tsx new file mode 100644 index 000000000..d05882296 --- /dev/null +++ b/framework/commerce/customer/address/use-update-item.tsx @@ -0,0 +1,21 @@ +import type { HookFetcherFn, MutationHook } from '../../utils/types' +import type { UpdateItemHook } from '../../types/customer/address' +import type { Provider } from '../..' + +import { useHook, useMutationHook } from '../../utils/use-hook' +import { mutationFetcher } from '../../utils/default-fetcher' + +export type UseUpdateItem< + H extends MutationHook> = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider.customer?.address?.useUpdateItem! + +const useUpdateItem: UseUpdateItem = (input) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(input) +} + +export default useUpdateItem diff --git a/framework/commerce/customer/card/use-add-item.tsx b/framework/commerce/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7b4ffdb17 --- /dev/null +++ b/framework/commerce/customer/card/use-add-item.tsx @@ -0,0 +1,21 @@ +import type { HookFetcherFn, MutationHook } from '../../utils/types' +import type { AddItemHook } from '../../types/customer/card' +import type { Provider } from '../..' + +import { useHook, useMutationHook } from '../../utils/use-hook' +import { mutationFetcher } from '../../utils/default-fetcher' + +export type UseAddItem< + H extends MutationHook> = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider.customer?.card?.useAddItem! + +const useAddItem: UseAddItem = (...args) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(...args) +} + +export default useAddItem diff --git a/framework/commerce/customer/card/use-cards.tsx b/framework/commerce/customer/card/use-cards.tsx new file mode 100644 index 000000000..57099504f --- /dev/null +++ b/framework/commerce/customer/card/use-cards.tsx @@ -0,0 +1,34 @@ +import type { SWRHook, HookFetcherFn } from '../../utils/types' +import type { GetCardsHook } from '../../types/customer/card' + +import Cookies from 'js-cookie' + +import { useHook, useSWRHook } from '../../utils/use-hook' +import { Provider, useCommerce } from '../..' + +export type UseCards< + H extends SWRHook> = SWRHook +> = ReturnType + +export const fetcher: HookFetcherFn = async ({ + options, + input: { cartId }, + fetch, +}) => { + return cartId ? await fetch(options) : null +} + +const fn = (provider: Provider) => provider.customer?.card?.useCards! + +const useCards: UseCards = (input) => { + const hook = useHook(fn) + const { cartCookie } = useCommerce() + const fetcherFn = hook.fetcher ?? fetcher + const wrapper: typeof fetcher = (context) => { + context.input.cartId = Cookies.get(cartCookie) + return fetcherFn(context) + } + return useSWRHook({ ...hook, fetcher: wrapper })(input) +} + +export default useCards diff --git a/framework/commerce/customer/card/use-remove-item.tsx b/framework/commerce/customer/card/use-remove-item.tsx new file mode 100644 index 000000000..1d85fa636 --- /dev/null +++ b/framework/commerce/customer/card/use-remove-item.tsx @@ -0,0 +1,21 @@ +import type { HookFetcherFn, MutationHook } from '../../utils/types' +import type { RemoveItemHook } from '../../types/customer/card' +import type { Provider } from '../..' + +import { useHook, useMutationHook } from '../../utils/use-hook' +import { mutationFetcher } from '../../utils/default-fetcher' + +export type UseRemoveItem< + H extends MutationHook> = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider.customer?.card?.useRemoveItem! + +const useRemoveItem: UseRemoveItem = (input) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(input) +} + +export default useRemoveItem diff --git a/framework/commerce/customer/card/use-update-item.tsx b/framework/commerce/customer/card/use-update-item.tsx new file mode 100644 index 000000000..cd8837d7f --- /dev/null +++ b/framework/commerce/customer/card/use-update-item.tsx @@ -0,0 +1,21 @@ +import type { HookFetcherFn, MutationHook } from '../../utils/types' +import type { UpdateItemHook } from '../../types/customer/card' +import type { Provider } from '../..' + +import { useHook, useMutationHook } from '../../utils/use-hook' +import { mutationFetcher } from '../../utils/default-fetcher' + +export type UseUpdateItem< + H extends MutationHook> = MutationHook +> = ReturnType + +export const fetcher: HookFetcherFn = mutationFetcher + +const fn = (provider: Provider) => provider?.customer?.card?.useUpdateItem! + +const useUpdateItem: UseUpdateItem = (input) => { + const hook = useHook(fn) + return useMutationHook({ fetcher, ...hook })(input) +} + +export default useUpdateItem diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx index dd740809f..eaa878a9e 100644 --- a/framework/commerce/index.tsx +++ b/framework/commerce/index.tsx @@ -15,6 +15,7 @@ import type { Signup, Login, Logout, + Checkout, } from '@commerce/types' import type { Fetcher, SWRHook, MutationHook } from './utils/types' @@ -29,6 +30,10 @@ export type Provider = CommerceConfig & { useUpdateItem?: MutationHook useRemoveItem?: MutationHook } + checkout?: { + useCheckout?: SWRHook + useSubmitCheckout?: MutationHook + } wishlist?: { useWishlist?: SWRHook useAddItem?: MutationHook @@ -36,6 +41,18 @@ export type Provider = CommerceConfig & { } customer?: { useCustomer?: SWRHook + card?: { + useCards?: SWRHook + useAddItem?: MutationHook + useUpdateItem?: MutationHook + useRemoveItem?: MutationHook + } + address?: { + useAddresses?: SWRHook + useAddItem?: MutationHook + useUpdateItem?: MutationHook + useRemoveItem?: MutationHook + } } products?: { useSearch?: SWRHook diff --git a/framework/commerce/types/checkout.ts b/framework/commerce/types/checkout.ts index 9e3c7ecfa..ea28926a8 100644 --- a/framework/commerce/types/checkout.ts +++ b/framework/commerce/types/checkout.ts @@ -1,10 +1,57 @@ -export type CheckoutSchema = { +import type { UseSubmitCheckout } from '../checkout/use-submit-checkout' +import type { Address } from './customer/address' +import type { Card } from './customer/card' + +// Index +export type Checkout = unknown; + +export type CheckoutTypes = { + card?: Card + address?: Address + checkout?: Checkout + hasPayment?: boolean + hasShipping?: boolean +} + +export type SubmitCheckoutHook = { + data: T + input?: T + fetcherInput: T + body: { item: T } + actionInput: T +} + +export type GetCheckoutHook = { + data: T['checkout'] | null + input: {} + fetcherInput: { cartId?: string } + swrState: { isEmpty: boolean } + mutations: { submit: UseSubmitCheckout } +} + +export type CheckoutHooks = { + submitCheckout: SubmitCheckoutHook + getCheckout: GetCheckoutHook +} + +export type GetCheckoutHandler = + GetCheckoutHook & { + body: { cartId: string } + } + +export type SubmitCheckoutHandler = + SubmitCheckoutHook & { + body: { cartId: string } + } + +export type CheckoutHandlers = { + getCheckout?: GetCheckoutHandler + submitCheckout: SubmitCheckoutHandler +} + +export type CheckoutSchema = { endpoint: { options: {} - handlers: { - checkout: { - data: null - } - } + handlers: CheckoutHandlers } } diff --git a/framework/commerce/types/customer/address.ts b/framework/commerce/types/customer/address.ts new file mode 100644 index 000000000..5b6ca4b49 --- /dev/null +++ b/framework/commerce/types/customer/address.ts @@ -0,0 +1,93 @@ +export interface Address { + id: string; + mask: string; +} + +export interface AddressFields { + type: string; + firstName: string; + lastName: string; + company: string; + streetNumber: string; + apartments: string; + zipCode: string; + city: string; + country: string; +} + +export type CustomerAddressTypes = { + address?: Address; + fields: AddressFields; +} + +export type GetAddressesHook = { + data: T['address'] | null + input: {} + fetcherInput: { cartId?: string } + swrState: { isEmpty: boolean } +} + +export type AddItemHook = { + data: T['address'] + input?: T['fields'] + fetcherInput: T['fields'] + body: { item: T['fields'] } + actionInput: T['fields'] +} + +export type UpdateItemHook = { + data: T['address'] | null + input: { item?: T['fields']; wait?: number } + fetcherInput: { itemId: string; item: T['fields'] } + body: { itemId: string; item: T['fields'] } + actionInput: T['fields'] & { id: string } +} + +export type RemoveItemHook = { + data: T['address'] | null + input: { item?: T['fields'] } + fetcherInput: { itemId: string } + body: { itemId: string } + actionInput: { id: string } +} + +export type CustomerAddressHooks = { + getAddresses: GetAddressesHook + addItem: AddItemHook + updateItem: UpdateItemHook + removeItem: RemoveItemHook +} + +export type AddresssHandler = GetAddressesHook & { + body: { cartId?: string } +} + +export type AddItemHandler = AddItemHook & { + body: { cartId: string } +} + +export type UpdateItemHandler = + UpdateItemHook & { + data: T['address'] + body: { cartId: string } + } + +export type RemoveItemHandler = + RemoveItemHook & { + body: { cartId: string } + } + + +export type CustomerAddressHandlers = { + getAddresses: GetAddressesHook + addItem: AddItemHandler + updateItem: UpdateItemHandler + removeItem: RemoveItemHandler +} + +export type CustomerAddressSchema = { + endpoint: { + options: {} + handlers: CustomerAddressHandlers + } +} diff --git a/framework/commerce/types/customer/card.ts b/framework/commerce/types/customer/card.ts new file mode 100644 index 000000000..a8731411f --- /dev/null +++ b/framework/commerce/types/customer/card.ts @@ -0,0 +1,96 @@ +export interface Card { + id: string; + mask: string; + provider: string; +} + +export interface CardFields { + cardHolder: string; + cardNumber: string; + cardExpireDate: string; + cardCvc: string; + firstName: string; + lastName: string; + company: string; + streetNumber: string; + zipCode: string; + city: string; + country: string; +} + +export type CustomerCardTypes = { + card?: Card; + fields: CardFields; +} + +export type GetCardsHook = { + data: T['card'] | null + input: {} + fetcherInput: { cartId?: string } + swrState: { isEmpty: boolean } +} + +export type AddItemHook = { + data: T['card'] + input?: T['fields'] + fetcherInput: T['fields'] + body: { item: T['fields'] } + actionInput: T['fields'] +} + +export type UpdateItemHook = { + data: T['card'] | null + input: { item?: T['fields']; wait?: number } + fetcherInput: { itemId: string; item: T['fields'] } + body: { itemId: string; item: T['fields'] } + actionInput: T['fields'] & { id: string } +} + +export type RemoveItemHook = { + data: T['card'] | null + input: { item?: T['fields'] } + fetcherInput: { itemId: string } + body: { itemId: string } + actionInput: { id: string } +} + +export type CustomerCardHooks = { + getCards: GetCardsHook + addItem: AddItemHook + updateItem: UpdateItemHook + removeItem: RemoveItemHook +} + +export type CardsHandler = GetCardsHook & { + body: { cartId?: string } +} + +export type AddItemHandler = AddItemHook & { + body: { cartId: string } +} + +export type UpdateItemHandler = + UpdateItemHook & { + data: T['card'] + body: { cartId: string } + } + +export type RemoveItemHandler = + RemoveItemHook & { + body: { cartId: string } + } + + +export type CustomerCardHandlers = { + getCards: GetCardsHook + addItem: AddItemHandler + updateItem: UpdateItemHandler + removeItem: RemoveItemHandler +} + +export type CustomerCardSchema = { + endpoint: { + options: {} + handlers: CustomerCardHandlers + } +} diff --git a/framework/commerce/types/customer.ts b/framework/commerce/types/customer/index.ts similarity index 87% rename from framework/commerce/types/customer.ts rename to framework/commerce/types/customer/index.ts index ba90acdf4..70c437c29 100644 --- a/framework/commerce/types/customer.ts +++ b/framework/commerce/types/customer/index.ts @@ -1,3 +1,6 @@ +export * as Card from "./card" +export * as Address from "./address" + // TODO: define this type export type Customer = any diff --git a/framework/commerce/utils/types.ts b/framework/commerce/utils/types.ts index 751cea4a5..2bca30852 100644 --- a/framework/commerce/utils/types.ts +++ b/framework/commerce/utils/types.ts @@ -87,6 +87,8 @@ export type HookSchemaBase = { export type SWRHookSchemaBase = HookSchemaBase & { // Custom state added to the response object of SWR swrState?: {} + // Instances of MutationSchemaBase that the hook returns for better DX + mutations?: Record['useHook']>> } export type MutationSchemaBase = HookSchemaBase & { @@ -102,7 +104,7 @@ export type SWRHook = { context: SWRHookContext ): HookFunction< H['input'] & { swrOptions?: SwrOptions }, - ResponseState & H['swrState'] + ResponseState & H['swrState'] & H['mutations'] > fetchOptions: HookFetcherOptions fetcher?: HookFetcherFn diff --git a/framework/local/api/endpoints/customer/address.ts b/framework/local/api/endpoints/customer/address.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/local/api/endpoints/customer/address.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/local/api/endpoints/customer/card.ts b/framework/local/api/endpoints/customer/card.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/local/api/endpoints/customer/card.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/local/checkout/use-checkout.tsx b/framework/local/checkout/use-checkout.tsx new file mode 100644 index 000000000..942f85b83 --- /dev/null +++ b/framework/local/checkout/use-checkout.tsx @@ -0,0 +1,14 @@ +import { SWRHook } from '@commerce/utils/types' +import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout' + +export default useCheckout as UseCheckout + +export const handler: SWRHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ useData }) => + async (input) => ({}), +} diff --git a/framework/local/customer/address/use-add-item.tsx b/framework/local/customer/address/use-add-item.tsx new file mode 100644 index 000000000..ac9dcd5cf --- /dev/null +++ b/framework/local/customer/address/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/local/customer/card/use-add-item.tsx b/framework/local/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7e3afa9c5 --- /dev/null +++ b/framework/local/customer/card/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/saleor/api/endpoints/checkout/index.ts b/framework/saleor/api/endpoints/checkout/index.ts index f15672435..385283ea7 100644 --- a/framework/saleor/api/endpoints/checkout/index.ts +++ b/framework/saleor/api/endpoints/checkout/index.ts @@ -6,11 +6,7 @@ export type CheckoutAPI = GetAPISchema export type CheckoutEndpoint = CheckoutAPI['endpoint'] -const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ - req, - res, - config, -}) => { +const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({ req, res, config }) => { try { const html = ` @@ -47,7 +43,7 @@ const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ } } -export const handlers: CheckoutEndpoint['handlers'] = { checkout } +export const handlers: CheckoutEndpoint['handlers'] = { submitCheckout } const checkoutApi = createEndpoint({ handler: checkoutEndpoint, diff --git a/framework/saleor/api/endpoints/customer.ts b/framework/saleor/api/endpoints/customer.ts deleted file mode 100644 index d09c976c3..000000000 --- a/framework/saleor/api/endpoints/customer.ts +++ /dev/null @@ -1 +0,0 @@ -export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/customer/address.ts b/framework/saleor/api/endpoints/customer/address.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/saleor/api/endpoints/customer/address.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/saleor/api/endpoints/customer/card.ts b/framework/saleor/api/endpoints/customer/card.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/saleor/api/endpoints/customer/card.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/saleor/api/endpoints/customer/index.ts b/framework/saleor/api/endpoints/customer/index.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/saleor/api/endpoints/customer/index.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/saleor/checkout/use-checkout.tsx b/framework/saleor/checkout/use-checkout.tsx new file mode 100644 index 000000000..942f85b83 --- /dev/null +++ b/framework/saleor/checkout/use-checkout.tsx @@ -0,0 +1,14 @@ +import { SWRHook } from '@commerce/utils/types' +import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout' + +export default useCheckout as UseCheckout + +export const handler: SWRHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ useData }) => + async (input) => ({}), +} diff --git a/framework/saleor/customer/address/use-add-item.tsx b/framework/saleor/customer/address/use-add-item.tsx new file mode 100644 index 000000000..ac9dcd5cf --- /dev/null +++ b/framework/saleor/customer/address/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/saleor/customer/card/use-add-item.tsx b/framework/saleor/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7e3afa9c5 --- /dev/null +++ b/framework/saleor/customer/card/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/shopify/api/endpoints/checkout/index.ts b/framework/shopify/api/endpoints/checkout/index.ts index 5d78f451b..72b86cae2 100644 --- a/framework/shopify/api/endpoints/checkout/index.ts +++ b/framework/shopify/api/endpoints/checkout/index.ts @@ -2,13 +2,13 @@ import { GetAPISchema, createEndpoint } from '@commerce/api' import checkoutEndpoint from '@commerce/api/endpoints/checkout' import type { CheckoutSchema } from '../../../types/checkout' import type { ShopifyAPI } from '../..' -import checkout from './checkout' +import submitCheckout from './submit-checkout' export type CheckoutAPI = GetAPISchema export type CheckoutEndpoint = CheckoutAPI['endpoint'] -export const handlers: CheckoutEndpoint['handlers'] = { checkout } +export const handlers: CheckoutEndpoint['handlers'] = { submitCheckout } const checkoutApi = createEndpoint({ handler: checkoutEndpoint, diff --git a/framework/shopify/api/endpoints/checkout/checkout.ts b/framework/shopify/api/endpoints/checkout/submit-checkout.ts similarity index 88% rename from framework/shopify/api/endpoints/checkout/checkout.ts rename to framework/shopify/api/endpoints/checkout/submit-checkout.ts index 0c340a129..97ac77381 100644 --- a/framework/shopify/api/endpoints/checkout/checkout.ts +++ b/framework/shopify/api/endpoints/checkout/submit-checkout.ts @@ -6,7 +6,7 @@ import { import associateCustomerWithCheckoutMutation from '../../../utils/mutations/associate-customer-with-checkout' import type { CheckoutEndpoint } from '.' -const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ +const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({ req, res, config, @@ -35,4 +35,4 @@ const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ } } -export default checkout +export default submitCheckout diff --git a/framework/shopify/api/endpoints/customer.ts b/framework/shopify/api/endpoints/customer.ts deleted file mode 100644 index d09c976c3..000000000 --- a/framework/shopify/api/endpoints/customer.ts +++ /dev/null @@ -1 +0,0 @@ -export default function (_commerce: any) {} diff --git a/framework/shopify/api/endpoints/customer/address.ts b/framework/shopify/api/endpoints/customer/address.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/shopify/api/endpoints/customer/address.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/shopify/api/endpoints/customer/card.ts b/framework/shopify/api/endpoints/customer/card.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/shopify/api/endpoints/customer/card.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/shopify/api/endpoints/customer/index.ts b/framework/shopify/api/endpoints/customer/index.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/shopify/api/endpoints/customer/index.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/shopify/checkout/use-checkout.tsx b/framework/shopify/checkout/use-checkout.tsx new file mode 100644 index 000000000..942f85b83 --- /dev/null +++ b/framework/shopify/checkout/use-checkout.tsx @@ -0,0 +1,14 @@ +import { SWRHook } from '@commerce/utils/types' +import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout' + +export default useCheckout as UseCheckout + +export const handler: SWRHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ useData }) => + async (input) => ({}), +} diff --git a/framework/shopify/customer/address/use-add-item.tsx b/framework/shopify/customer/address/use-add-item.tsx new file mode 100644 index 000000000..ac9dcd5cf --- /dev/null +++ b/framework/shopify/customer/address/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/shopify/customer/card/use-add-item.tsx b/framework/shopify/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7e3afa9c5 --- /dev/null +++ b/framework/shopify/customer/card/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/swell/api/endpoints/checkout/index.ts b/framework/swell/api/endpoints/checkout/index.ts index ab17a3767..9847d8420 100644 --- a/framework/swell/api/endpoints/checkout/index.ts +++ b/framework/swell/api/endpoints/checkout/index.ts @@ -3,7 +3,7 @@ import { CheckoutSchema } from '@commerce/types/checkout' import { SWELL_CHECKOUT_URL_COOKIE } from '../../../const' import checkoutEndpoint from '@commerce/api/endpoints/checkout' -const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ +const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({ req, res, config, @@ -17,7 +17,7 @@ const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ res.redirect('/cart') } } -export const handlers: CheckoutEndpoint['handlers'] = { checkout } +export const handlers: CheckoutEndpoint['handlers'] = { submitCheckout } export type CheckoutAPI = GetAPISchema export type CheckoutEndpoint = CheckoutAPI['endpoint'] diff --git a/framework/swell/api/endpoints/customer.ts b/framework/swell/api/endpoints/customer.ts deleted file mode 100644 index d09c976c3..000000000 --- a/framework/swell/api/endpoints/customer.ts +++ /dev/null @@ -1 +0,0 @@ -export default function (_commerce: any) {} diff --git a/framework/swell/api/endpoints/customer/address.ts b/framework/swell/api/endpoints/customer/address.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/swell/api/endpoints/customer/address.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/swell/api/endpoints/customer/card.ts b/framework/swell/api/endpoints/customer/card.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/swell/api/endpoints/customer/card.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/swell/api/endpoints/customer/index.ts b/framework/swell/api/endpoints/customer/index.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/swell/api/endpoints/customer/index.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/swell/checkout/use-checkout.tsx b/framework/swell/checkout/use-checkout.tsx new file mode 100644 index 000000000..942f85b83 --- /dev/null +++ b/framework/swell/checkout/use-checkout.tsx @@ -0,0 +1,14 @@ +import { SWRHook } from '@commerce/utils/types' +import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout' + +export default useCheckout as UseCheckout + +export const handler: SWRHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ useData }) => + async (input) => ({}), +} diff --git a/framework/swell/customer/address/use-add-item.tsx b/framework/swell/customer/address/use-add-item.tsx new file mode 100644 index 000000000..ac9dcd5cf --- /dev/null +++ b/framework/swell/customer/address/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/swell/customer/card/use-add-item.tsx b/framework/swell/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7e3afa9c5 --- /dev/null +++ b/framework/swell/customer/card/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/vendure/api/endpoints/checkout/index.ts b/framework/vendure/api/endpoints/checkout/index.ts index 00c17f993..f138af6be 100644 --- a/framework/vendure/api/endpoints/checkout/index.ts +++ b/framework/vendure/api/endpoints/checkout/index.ts @@ -3,7 +3,7 @@ import { CommerceAPI, createEndpoint, GetAPISchema } from '@commerce/api' import { CheckoutSchema } from '@commerce/types/checkout' import checkoutEndpoint from '@commerce/api/endpoints/checkout' -const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ +const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({ req, res, config, @@ -48,7 +48,7 @@ export type CheckoutAPI = GetAPISchema export type CheckoutEndpoint = CheckoutAPI['endpoint'] -export const handlers: CheckoutEndpoint['handlers'] = { checkout } +export const handlers: CheckoutEndpoint['handlers'] = { submitCheckout } const checkoutApi = createEndpoint({ handler: checkoutEndpoint, diff --git a/framework/vendure/api/endpoints/customer/address.ts b/framework/vendure/api/endpoints/customer/address.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/vendure/api/endpoints/customer/address.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/vendure/api/endpoints/customer/card.ts b/framework/vendure/api/endpoints/customer/card.ts new file mode 100644 index 000000000..491bf0ac9 --- /dev/null +++ b/framework/vendure/api/endpoints/customer/card.ts @@ -0,0 +1 @@ +export default function noopApi(...args: any[]): void {} diff --git a/framework/vendure/checkout/use-checkout.tsx b/framework/vendure/checkout/use-checkout.tsx new file mode 100644 index 000000000..942f85b83 --- /dev/null +++ b/framework/vendure/checkout/use-checkout.tsx @@ -0,0 +1,14 @@ +import { SWRHook } from '@commerce/utils/types' +import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout' + +export default useCheckout as UseCheckout + +export const handler: SWRHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ useData }) => + async (input) => ({}), +} diff --git a/framework/vendure/customer/address/use-add-item.tsx b/framework/vendure/customer/address/use-add-item.tsx new file mode 100644 index 000000000..ac9dcd5cf --- /dev/null +++ b/framework/vendure/customer/address/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/framework/vendure/customer/card/use-add-item.tsx b/framework/vendure/customer/card/use-add-item.tsx new file mode 100644 index 000000000..7e3afa9c5 --- /dev/null +++ b/framework/vendure/customer/card/use-add-item.tsx @@ -0,0 +1,15 @@ +import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' +import { MutationHook } from '@commerce/utils/types' + +export default useAddItem as UseAddItem + +export const handler: MutationHook = { + fetchOptions: { + query: '', + }, + async fetcher({ input, options, fetch }) {}, + useHook: + ({ fetch }) => + () => + async () => ({}), +} diff --git a/pages/api/customer/address.ts b/pages/api/customer/address.ts new file mode 100644 index 000000000..5815ea462 --- /dev/null +++ b/pages/api/customer/address.ts @@ -0,0 +1,4 @@ +import customerAddressApi from '@framework/api/endpoints/customer/address' +import commerce from '@lib/api/commerce' + +export default customerAddressApi(commerce) diff --git a/pages/api/customer/card.ts b/pages/api/customer/card.ts new file mode 100644 index 000000000..6f88b8c74 --- /dev/null +++ b/pages/api/customer/card.ts @@ -0,0 +1,4 @@ +import customerCardApi from '@framework/api/endpoints/customer/card' +import commerce from '@lib/api/commerce' + +export default customerCardApi(commerce) diff --git a/pages/api/customer.ts b/pages/api/customer/index.ts similarity index 100% rename from pages/api/customer.ts rename to pages/api/customer/index.ts