Vue Storefront is now Alokai! Learn More
Re-Order

SAP Commerce Cloud: Re-Order

SAP Re-Order module allows customers to easily place a new order for the same or similar products that they have previously purchased from an ecommerce store. This module can help increase customer loyalty, retention and revenue by offering convenience and personalization.

Features

As a customer, gain instant access to the Re-Order process, designed to simplify and expedite your re-ordering journey:

  • Modal with re-order functionality baked in.
  • Instant visible information about state of reordering, notifications and tag on product card in cart.

The Re-Order module can be used a additional feature for already existing ordering flow.

Installation

Add the module files

To install the module, you need an enterprise license and credentials. Contact your Customer Support Manager if you're already a customer. If you're not a customer yet, contact our sales team.

From the root of your project run the following command:

npx @vsf-enterprise/storefront-cli add-module re-order -e [sapcc,sapcc-b2b]

Follow the instructions in the command line to complete the installation. To make sure the installation is finished, go to the apps/storefront-middleware/sf-modules folder and check if there's a folder named re-order inside.

Middleware Extension

This module adds additional, SAP-specific middleware methods. We need to install Re-Order extension in the Middleware configuration.

// integrations/sapcc/config.ts

import type { MiddlewareConfig } from "@vsf-enterprise/sapcc-api";
import type { ApiClientExtension, Integration } from "@vue-storefront/middleware";
import { multistoreExtension, unifiedApiExtension } from "./extensions";
import { reOrderExtensionFactory } from "@sf-modules-middleware/re-order"; 
// ...

export const config = {
  location: "@vsf-enterprise/sapcc-api/server",
  configuration: {
    // ...
  },
  extensions: (extensions: ApiClientExtension[]) => [
    ...extensions,
    unifiedApiExtension,
    ...(IS_MULTISTORE_ENABLED === "true" ? [multistoreExtension] : []),
    reOrderExtensionFactory(),   ],
} satisfies Integration<MiddlewareConfig>;

Then, export the type of the new extension in the types.ts file in root directory of the Middleware.

// types.ts

export {
  type UnifiedEndpoints,
} from "./integrations/sapcc/types";

export type { ReOrderEndpoints } from "@sf-modules-middleware/re-order"; 

Frontend Implementation

1. Extend SDK configuration

First, you need to add the newly installed extension to the SDK config. To do so, edit the sdk/sdk.config.ts file in your Next.js Storefront directory.

// sdk/sdk.config.ts

import { contentfulModule } from '@vsf-enterprise/contentful-sdk';
import { CreateSdkOptions, createSdk } from '@vue-storefront/next';
import type { UnifiedEndpoints } from 'storefront-middleware/types'; import type {   UnifiedEndpoints,   ReOrderEndpoints, } from 'storefront-middleware/types'; 
//...

export const { getSdk } = createSdk(options, ({ buildModule, middlewareModule, middlewareUrl, getRequestHeaders }) => ({
  unified: buildModule(middlewareModule<UnifiedEndpoints>, {
    apiUrl: `${middlewareUrl}/commerce`,
    defaultRequestConfig: {
      headers: getRequestHeaders(),
    },
  }),
  reorder: buildModule(middlewareModule<ReOrderEndpoints>, {     apiUrl: `${middlewareUrl}/commerce/re-order`,     defaultRequestConfig: {       headers: getRequestHeaders(),     },   }),   contentful: buildModule(contentfulModule, {
    apiUrl: `${middlewareUrl}/cntf`,
  }),
}));

export type Sdk = ReturnType<typeof getSdk>;

2. Add Re-Order modal into your order details

In your current order details page add ReOrderConfirmationModal modal for reordering with OrderButton button with style matching order details page. Button component is already existing in project and can be imported from ~/components.

// components/OrderDetailsModal/OrderDetails.tsx

import { ConfirmationModal as ReOrderConfirmationModal } from '@sf-modules/re-order'; import { SfIconShoppingCart, useDisclosure } from '@storefront-ui/react'; import { OrderButton } from '~/components'; 
export function OrderDetails() {
  const { isOpen: reOrderModalOpen, open: openReOrderModal, close: closeReOrderModal } = useDisclosure(); 
  return (
        ...
      </div>
    </DescriptionList>
    <div className="flex flex-col gap-2 pt-10 mt-6 border-t border-neutral-200">
      ...
      <OrderButton slotPrefix={<SfIconShoppingCart />} onClick={openReOrderModal}>        Reorder      </OrderButton>      ...
    </div>
    <ReOrderConfirmationModal open={reOrderModalOpen} onCancel={closeReOrderModal} onConfirm={closeReOrderModal} />     ...
  );
}

Additionally if smaller quantity tag wants to be visible in product card section, which is CartProductCardWrapper, then desiredQuantity property has to be set with wantedQuantities[id] value.

// components/CartPageContent/CartPageContent.tsx

import { useReOrderProducts } from '@sf-modules/re-order'; 
export function CartPageContent() {
  const { wantedQuantities } = useReOrderProducts(); 
  return (
    ...
    <ul className="col-span-7 mb-10 md:mb-0">
      {cart.lineItems.map(
        ({ id, productId, attributes, image, name, unitPrice, quantity, slug, totalPrice, quantityLimit }) => (
          <CartProductCardWrapper
            key={id}
            attributes={attributes}
            id={id}
            productId={productId}
            imageUrl={image?.url}
            imageAlt={image?.alt}
            name={name ?? ''}
            price={formatPrice(unitPrice?.value!)}
            totalPrice={formatPrice(totalPrice as SfMoney)}
            specialPrice={unitPrice?.isDiscounted ? formatPrice(unitPrice?.regularPrice) : undefined}
            minValue={1}
            maxValue={quantityLimit || Infinity}
            value={quantity}
            slug={slug}
            desiredQuantity={wantedQuantities[id]}          />
        ),
      )}
    </ul>
    ...
  );
}

And inside CartProductCardWrapper.tsx additional work has to be done for removing smaller quantity tag from card once product is updated.

// components/ui/CartProductCardWrapper/CartProductCardWrapper.tsx

import { useReOrderProducts } from '@sf-modules/re-order'; 
export function CartProductCardWrapper() {
  const { removeWantedQuantities } = useReOrderProducts(); 
  return (
    <CartProductCard
      {...props}
      onUpdate={(quantity) => {
        updateCartQuantity.mutate({ quantity });
        removeWantedQuantities(id);       }}
      onRemove={() => {
        removeCartLineItem.mutate();
        removeWantedQuantities(id);       }}
      disabled={updateCartQuantity.isLoading || removeCartLineItem.isLoading}
    />
  );
}

With these steps, your Re-Order feature is now effectively integrated with SAP Commerce Cloud. You've just provided a practical solution for your customers who want a hassle-free and efficient reordering process!