Vue Storefront is now Alokai! Learn More
Register

SAP Commerce Cloud: B2B Register

SAP B2B Registration module consists set of steps that an entity has to follow in order to access or obtain account credentials for purchasing in commerce.

Features

SAP B2B Registration module alters already available registration flow. In B2B process works differently, there is no possibility to set up password, but only send request for an account.

  • Modified registration form for B2B commerce.
  • Modal with success message once registration request is sent.

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 Alokai Sales Team.

From the root of your project run the following command:

npx @vsf-enterprise/storefront-cli add-module register-b2b -e 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 register-b2b inside.

Frontend Implementation

1. Implement register-form

Update the apps/storefront-unified-nextjs/app/[locale]/(auth)/register/components/register-form.tsx with following code

// apps/storefront-unified-nextjs/app/[locale]/(auth)/register/components/register-form.tsx
import { pick } from 'lodash-es';
import { NextIntlClientProvider, useMessages } from 'next-intl';

import RegisterFormClient from './register-form-client';

export default function RegisterForm() {
  const messages = useMessages();

  return (
    <NextIntlClientProvider messages={pick(messages, 'RegisterForm', 'RegisterB2B')}>
      <RegisterFormClient />
    </NextIntlClientProvider>
  );
}

And then create a apps/storefront-unified-nextjs/app/[locale]/(auth)/register/components/register-form-client.tsx file with following code

'use client';

import { isSdkRequestError, isSpecificSdkHttpError } from '@alokai/connect/sdk';
import { SuccessB2BRegisterModal } from '@sf-modules/register-b2b';
import { SfIconError, SfInput, SfTextarea } from '@storefront-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslations } from 'next-intl';
import { type ChangeEvent, useState } from 'react';

import Alert from '@/components/ui/alert';
import Form, { FormLabel, FormSubmit } from '@/components/ui/form';
import { resolveFormData } from '@/helpers/form-data';
import { useSdk } from '@/sdk/alokai-context';
import type { B2BRegisterCustomerArgs } from '@/types';

export default function RegisterFormClient() {
  const sdk = useSdk();
  const t = useTranslations('RegisterForm');
  const queryClient = useQueryClient();
  const { error, isPending, isSuccess, mutate } = useMutation({
    meta: {
      skipErrorNotification: isSdkRequestError,
    },
    mutationFn: async (data: B2BRegisterCustomerArgs) => sdk.b2bRegister.registerCustomer(data),
    onSuccess(data) {
      queryClient.setQueryData(['customer'], data);
      queryClient.invalidateQueries({ queryKey: ['cart'] });
    },
    retry: false,
  });

  const [messageValue, setMessageValue] = useState('');
  const isUserAlreadyExistsError = error?.message.includes('User already exists');
  const characterLimit = 1000;
  const charsCount = characterLimit - messageValue.length;

  const onMessageChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
    const { value } = event.target;
    setMessageValue(value);
  };

  return (
    <>
      <Form
        className="flex flex-col gap-6 rounded-md border-neutral-200 px-0 md:border md:p-6"
        onSubmit={(event) => {
          event.preventDefault();
          mutate(resolveFormData<B2BRegisterCustomerArgs>(event.currentTarget));
        }}
      >
        {isSpecificSdkHttpError(error, { statusCode: 400 }) && (
          <Alert className="mb-4" slotPrefix={<SfIconError className="text-negative-700" />} variant="error">
            {t('requestError')}
          </Alert>
        )}
        <div className="flex flex-col gap-4">
          <label data-testid="first-name-field">
            <FormLabel>{t('firstName')} *</FormLabel>
            <SfInput autoComplete="given-name" data-testid="first-name-input" name="firstName" required size="lg" />
          </label>
          <label data-testid="last-name-field">
            <FormLabel>{t('lastName')} *</FormLabel>
            <SfInput autoComplete="family-name" data-testid="last-name-input" name="lastName" required size="lg" />
          </label>
          <label data-testid="email-field">
            <FormLabel>{t('email')} *</FormLabel>
            <SfInput autoComplete="email" data-testid="email-input" name="email" required size="lg" type="email" />
          </label>
          <label>
            <FormLabel>{t('message')}</FormLabel>
            <SfTextarea
              className="block min-h-[96px] w-full"
              maxLength={characterLimit}
              name="message"
              onInput={onMessageChange}
              placeholder={t('messagePlaceholder')}
              value={messageValue}
            />
            <p className="mt-0.5 text-right text-neutral-500 typography-hint-xs">{charsCount}</p>
            {isUserAlreadyExistsError && (
              <p className="mt-0.5 font-medium text-negative-700 typography-hint-xs">{t('userAlreadyExists')}</p>
            )}
          </label>
        </div>

        <p className="text-neutral-500 typography-text-sm">{t('markRequired')}</p>

        <FormSubmit data-testid="submit-button" pending={isPending} size="lg">
          {t('submit')}
        </FormSubmit>
      </Form>
      {isSuccess && <SuccessB2BRegisterModal />}
    </>
  );
}

2. Add internationalization messages

Update translations for components.

// storefront-unified-nextjs/lang/en/register.json

  // ...
  "RegisterForm": {
    "message": "Message (optional)",     "messagePlaceholder": "Additional information regarding the intended account",     "userAlreadyExists": "User already exists",     // ...
  },
  "RegisterPage": {
    "heading": "Create Account",     "metaTitle": "Create Account",     "heading": "Send Request",     "metaTitle": "Send Request",     // ...
  }
  // ...
// storefront-unified-nextjs/lang/de/register.json

  // ...
  "RegisterForm": {
    "message": "Nachricht (optional)",     "messagePlaceholder": "Zusätzliche Informationen zum beabsichtigten Konto",     "userAlreadyExists": "Benutzer existiert bereits",     // ...
  },
  "RegisterPage": {
    "heading": "Benutzerkonto erstellen",     "metaTitle": "Benutzerkonto erstellen",     "heading": "Anfrage senden",     "metaTitle": "Anfrage senden",     // ...
  }
  // ...

With these steps, your Register-b2b feature is now effectively integrated with SAP Commerce Cloud. You've just provided a practical solution for your customers to register into your Commerce!