Front-End SDK Overview

Ec-react (also known as the frontend sdk) allows developers to easily integrate with Socotra Insurance Suite. This SDK is written in TypeScript and React and provides an easy entry point to interacting with the system via components, utilities, and schemas.

These components, schemas and utilities are compatible with any React application including server side frameworks like Next.JS and Gatsby.

Getting Started

This SDK contains three individual packages for building and managing React applications for use in the Socotra Insurance Suite.

  • @socotra/ec-react-components: A React component library for generating forms and other components for EC.

  • @socotra/ec-react-utils: A set of utility functions for integrating ec-react-components with API responses.

  • @socotra/ec-react-schemas: Zod schemas for validating requests and responses from EC.

In addition to the published packages, Socotra has 2 sample projects available by request.

  • @socotra/sandbox: Vite / React / TypeScript / Tailwind implementation of the SDK with custom styles applied to the components from @socotra/ec-react-components

  • @socotra/vanilla-sandbox: Vite / React / TypeScript implementation of the SDK with a simple stylesheet applied.

Installation

Add all packages to your existing project

npm i @socotra/ec-react-schemas @socotra/ec-react-utils @socotra/ec-react-components

Schemas

@socotra/ec-react-schemas is a package of zod schemas and TypeScript types for typing requests and responses from Enterprise Core.

Installation

Add all packages to your existing project

npm i @socotra/ec-react-schemas

Example Usage

After installation, import schemas from the root of the package as needed. In the example below, we use the AccountRequest type and accountResponseSchema to validate the data coming in and out of EC while we create a new account.

import {
  AccountRequest,
  accountResponseSchema,
} from '@socotra/ec-react-schemas';

export async function createAccount({
  data,
  tenantLocator,
}: {
  // Ensures the data being sent is correctly shaped for the accounts API
  data: AccountRequest;
  tenantLocator: string;
}) {
  const response = await fetch(`/policy/${tenantLocator}/accounts`, {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json',
    },
  });

  // Ensures that response.json() is exactly what is defined by accountResposeSchema
  const account = accountResponseSchema.parse(await response.json());

  // account is now typed as AccountResponse
  return account;
}

List of Schemas

Config

Schemas and types that define the Data Model returned by EC.

Exported Schemas
  • accountConfigRecordSchema

  • accountConfigSchema

  • dataModelSchema

  • dataTypeConfigSchema

  • dataTypesRecordSchema

  • elementConfigRecordSchema

  • elementConfigSchema

  • fieldConfigRecordSchema

  • fieldConfigSchema

  • productConfigSchema

  • productConfigRecordSchema

  • coverageTermSchema

  • coverageTermsRecordSchema

  • coverageTermOptionSchema

  • quantifiersSchema

  • optionalQuantifiersSchema

  • delinquencyPlanSchema

  • delinquencyPlanRecordsSchema

  • delinquencyLevelSchema

  • advanceLapseToSchema

  • autoRenewalPlanSchema

Exported Types
  • AccountConfigRecord

  • AccountConfig

  • DataModel

  • DataTypeConfigRecord

  • DataTypeConfig

  • ElementConfigRecord

  • ElementConfig

  • FieldConfigRecord

  • FieldConfig

  • ProductConfigRecord

  • ProductConfig

  • TenantBaseConfig

  • CoverageTermOption

  • CoverageTermsConfigRecord

  • CoverageTermsConfig

  • Quantifiers

  • OptionalQuantifiers

  • DelinquencyPlan

  • AutoRenewalPlan

Quote

Schemas and types used to validate and type requests and responses to the Quote API in EC. Also has types and schemas for a quote’s element, exported as well.

Exported Schemas
  • quoteResponseSchema

  • quoteStateEnumSchema

  • quoteDurationBasisEnumSchema

  • quoteBillingLevelEnumSchema

  • quoteBillingTriggerEnumSchema

  • quoteRequestSchema

  • elementRequestSchema

  • elementResponseSchema

  • Exported Types

  • QuoteResponse

  • QuoteState

  • QuoteDurationBasis

  • QuoteRequest

  • ElementRequest

  • ElementResponse

Account

Schemas and types used to validate and type requests and responses to the Accounts API in EC.

Exported Schemas
  • accountResponseSchema

  • accountRequestSchema

  • accountBillingLevelEnumSchema

  • accountStateEnumSchema

  • Exported Types

  • AccountResponse

  • AccountRequest

  • AccountStateEnum

  • AccountBillingLevelEnum

Policy

Schemas and types used to validate and type requests and responses to the Policy API in EC.

Exported Schemas
  • policyResponseSchema

  • policyDurationBasisEnumSchema

  • policyBillingLevelEnumSchema

  • policyBillingTriggerEnumSchema

  • transactionCategoryEnumSchema

  • transactionSnapshotResponseSchema

  • documentStateEnumSchema

  • documentReferenceTypeEnumSchema,

  • documentSummarySchema

  • elementSummarySchema

  • subsegmentSummarySchema

  • termSummarySchema

  • policySnapshotResponseSchema

Exported Types
  • PolicyResponse

  • PolicyDurationBasis

  • PolicyBillingLevel

  • PolicyBillingTrigger

  • TransactionSnapshotResponse

  • TransactionCategory

  • DocumentState

  • DocumentReference

  • DocumentSummary

  • ElementSummary

  • SubsegmentSummary

  • TermSummary

  • PolicySnapshotResponse

Shared

Schemas and types shared by multiple schemas.

Exported Schemas
  • validationResultSchema

  • currencyEnumSchema

  • timezoneEnumSchema

  • anchorModeEnumSchema

  • anchorTypeEnumSchema

  • billingLevelEnumSchema

  • cadenceEnumSchema

  • dayOfWeekEnumSchema

  • weekOfMonthEnumSchema

  • preferencesResponseSchema

Exported Types
  • ValidationResult

  • ValidationItem

  • CurrencyType

  • TimezoneType

  • AnchorMode

  • AnchorType

  • BillingLevel

  • DayOfWeek

  • WeekOfMonth

  • PreferencesResponse

Components

@socotra/ec-react-components is a package of customizable React components ready for installation.

Typical Installation

  1. Install dependencies

npm i @socotra/ec-react-components
  1. At the root of your react Application, import the style sheet for the components

import '@socotra/ec-react-components/dist/style.css';

Installation With Tailwind and Custom Theme

  1. Install dependencies

npm i @socotra/ec-react-components
  1. Install Tailwind and the container queries plugin

npm install -D tailwindcss @tailwindcss/container-queries
npx tailwindcss init
  1. Add the paths to all of your template files in your tailwind.config.js file.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  1. Add @socotra/ec-react-components to your content path array in your tailwind.config.js file

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
    "./node_modules/@socotra/ec-react-components/dist/**/*.js",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  1. Add tailwind container query plugin to your plugins array in your tailwind.config.js file

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
    "./node_modules/@socotra/ec-react-components/dist/**/*.js",
  ],
  theme: {
    extend: {},
  },
  plugins: [require('@tailwindcss/container-queries')],
}
  1. Add the @tailwind directives for each of Tailwind’s layers to your ./src/index.css file.

@tailwind base;
@tailwind components;
@tailwind utilities;
  1. Create a theme via a theme builder and click Copy Code

  2. Paste copied code under the tailwind directives of your ./src/index.css file

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 224 71.4% 4.1%;
    --card: 0 0% 100%;
    --card-foreground: 224 71.4% 4.1%;
    --popover: 0 0% 100%;
    --popover-foreground: 224 71.4% 4.1%;
    --primary: 262.1 83.3% 57.8%;
    --primary-foreground: 210 20% 98%;
    --secondary: 220 14.3% 95.9%;
    --secondary-foreground: 220.9 39.3% 11%;
    --muted: 220 14.3% 95.9%;
    --muted-foreground: 220 8.9% 46.1%;
    --accent: 220 14.3% 95.9%;
    --accent-foreground: 220.9 39.3% 11%;
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 210 20% 98%;
    --border: 220 13% 91%;
    --input: 220 13% 91%;
    --ring: 262.1 83.3% 57.8%;
    --radius: 1rem;
    --chart-1: 12 76% 61%;
    --chart-2: 173 58% 39%;
    --chart-3: 197 37% 24%;
    --chart-4: 43 74% 66%;
    --chart-5: 27 87% 67%;
  }

  .dark {
    --background: 224 71.4% 4.1%;
    --foreground: 210 20% 98%;
    --card: 224 71.4% 4.1%;
    --card-foreground: 210 20% 98%;
    --popover: 224 71.4% 4.1%;
    --popover-foreground: 210 20% 98%;
    --primary: 263.4 70% 50.4%;
    --primary-foreground: 210 20% 98%;
    --secondary: 215 27.9% 16.9%;
    --secondary-foreground: 210 20% 98%;
    --muted: 215 27.9% 16.9%;
    --muted-foreground: 217.9 10.6% 64.9%;
    --accent: 215 27.9% 16.9%;
    --accent-foreground: 210 20% 98%;
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 210 20% 98%;
    --border: 215 27.9% 16.9%;
    --input: 215 27.9% 16.9%;
    --ring: 263.4 70% 50.4%;
    --chart-1: 220 70% 50%;
    --chart-2: 160 60% 45%;
    --chart-3: 30 80% 55%;
    --chart-4: 280 65% 60%;
    --chart-5: 340 75% 55%;
  }
}

The exported components take into account the various colors from the variables set above and have dark and light mode variants. To adjust the primary color beyond what is available in the theme builder, change the primary HSL code to whatever is required by your application.

Example Usage

After installation, import components from the root of the package as needed.

In the example below, we import various types and schemas from @socotra/ec-react-schemas and then use those to write an interface for a component that uses the QuoteForm.

The result is a fully functional form that makes a request to EC when the submit button is pressed.

import { useState } from 'react';
import { QuoteForm } from '@socotra/ec-react-components';
import {
  DataModel,
  DataTypeConfigRecord,
  QuoteRequest,
  QuoteResponse,
  quoteResponseSchema,
} from '@socotra/ec-react-schemas';

interface Props {
  quote: QuoteResponse;
  dataTypes: DataTypeConfigRecord;
  dataModel: DataModel;
}

export const UpdateQuoteForm = (props: Props) => {
  const [quote, setQuote] = useState<QuoteResponse>(props.quote);

  const handleUpdateQuote = async (updatedQuote: QuoteRequest) => {
    const response = await fetch('/policy/{tenantLocator}/quotes/{locator}', {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(updatedQuote),
    });

    if (!response.ok) {
      throw new Error('Failed to update quote');
    }

    const quote = quoteResponseSchema.parse(await response.json());

    setQuote(quote);
  };

  return (
    <QuoteForm
      quote={quote}
      dataTypes={props.dataTypes}
      dataModel={props.dataModel}
      handleSubmit={handleUpdateQuote}
    />
  );
};

Components

AccountForm

The account form takes a data model, account type, and an account and renders a form that when submitted creates an AccountRequest.

The following props are required:

/**
* The resolved data model for **all** accounts retrieved from the data model
response */
accountsModel: AccountConfigRecord;
/**
* The account type to use for the form, used to pick the correct data model from
the accountsModel */
accountType: keyof AccountConfigRecord;
/**
* The custom data types for the configuration that may be referenced by the
account's data model */
dataTypes: DataTypeConfigRecord;
/**
* The function to call when the form is submitted. It will create an AccountRequest
from the form data. */
handleSubmit: (data: AccountRequest) => void;

The following props are optional:

/**
* The account object to put the form in update mode
*/
account?: AccountResponse;
/**
* Set to true when the form is submitting to set fields to readonly and disable
the submit button */
isSubmitting?: boolean;
/**
* Disables the form
*/
disabled?: boolean;
/**
* Prevents the form from resetting when disabled
* default is true
*/
/**
* Prevents the form from resetting when changing from enabled to disabled
* Default is true
*/
preventFormResetOnDisabled?: boolean;
/**
* Hides the submit button
* Default is false
*/
hideSubmitButton?: boolean;
/**
* Whether to validate the form on submit inline
* Default is false
*/
validateOnSubmit?: boolean;
/**
* The text to display on the submit button
*/
submitButtonText?: string;
/**
* ID for the form wrapper, used to submit the form remotely
* */
id?: string;
/**
* Customizing the advanced fields section of the form
**/
advancedOptions?: {
  /**
  * The auto renewal plans for the account
  */
  autoRenewalPlans?: string[];
  /**
  * The delinquency plans available for the account
  */
  delinquencyPlans?: string[];
  /**
  * The excess credit plans available for the account
  */
  excessCreditPlans?: string[];
  /**
  * The shortfall tolerance plans available for the account
  */
  shortfallTolerancePlans?: string[];
  /**
  * The invoice documents available for the account
  */
  invoiceDocument?: string[];
};
/**
* Customize titles
**/
titles?: {
  seeAdvancedDetails?: string;
};

Renders the following (and dynamically adjusts based on the DataModel):

../../_images/account-large-form-fields.png

QuoteForm

The quote form takes a quote, data model, and data types response from the data model, along with a handleSubmit function and renders a form for updating quotes.

The following props are required:

/**
* The quote object
*/
quote: QuoteResponse;
/**
* The resolved data model retrieved from data model response
*/
dataModel: DataModel;
/**
* The custom data types for the configuration that may be referenced by the elementModel
*/
dataTypes: DataTypeConfigRecord;
/**
* The function to call when the form is submitted. It will create an QuoteRequest from the form data.
*/
handleSubmit: (data: QuoteRequest) => void;

The following props are optional:

/**
* Set to true when the form is submitting to set fields to readonly and disable the submit button
*/
isSubmitting?: boolean;
/**
* Disables the form
*/
disabled?: boolean;
/**
* Prevents the form from resetting when changing from enabled to disabled
* Default is true
*/
preventFormResetOnDisabled?: boolean;
/**
* Hides the submit button
* Default is false
*/
hideSubmitButton?: boolean;
/**
* Whether to validate the form on submit inline
* Default is false
*/
validateOnSubmit?: boolean;
/**
* The text to display on the submit button
*/
submitButtonText?: string;
/**
* ID for the form wrapper, used to submit the form remotely
* */
id?: string;
/**
* Titles for the form
*/
titles?: {
  details?: string;
  seeAdvancedDetails?: string;
  coverageTerms?: string;
  currency?: string;
  timezone?: string;
  billingLevel?: string;
  billingTrigger?: string;
  durationBasis?: string;
  delinquencyPlanName?: string;
  autoRenewalPlanName?: string;
};

Renders the following (and dynamically adjusts based on the DataModel):

../../_images/quote-large-form-fields.png

ElementForm

The element form takes an element, an element model, data types, and coverage terms from the DataModel, along with a handleSubmit function, and renders a form that allows for the updating of existing elements.

The following props are required:

/**
* The element object from the quote
*/
element: ElementResponse;
/**
* The resolved data model for the element retrieved from the data model response
*/
elementModel: ElementConfig;
/**
* The custom data types for the configuration that may be referenced by the elementModel
*/
dataTypes: DataTypeConfigRecord;
/**
* The coverage terms configuration that may be referenced by the elementModel
*/
coverageTerms: CoverageTermsConfigRecord;
/**
* The function to call when the form is submitted. It will create an ElementUpdateRequest.
*/
handleSubmit: (data: ElementRequest) => void;

The following props are optional:

/**
* Set to true when the form is submitting to set fields to readonly and disable the submit button
*/
isSubmitting?: boolean;
/**
* Disables the form
*/
disabled?: boolean;
/**
* Prevents the form from resetting when changing from enabled to disabled
* Default is true
*/
preventFormResetOnDisabled?: boolean;
/**
* Hides the submit button
* Default is false
*/
hideSubmitButton?: boolean;
/**
* Whether to validate the form on submit inline
* Default is false
*/
validateOnSubmit?: boolean;
/**
* The text to display on the submit button
*/
submitButtonText?: string;
/**
* ID for the form wrapper, used to submit the form remotely
* */
id?: string;
/**
* Titles for the form
*/
titles?: {
  coverageTerms?: string;
};

Renders the following (and dynamically adjusts based on the DataModel):

../../_images/element-large-form-fields.png

NewPaymentForm

The new payment form takes account’s locator, invoice’s locator, invoice’s balance, currency, data model, along with a handleSubmit function, and renders a form that allows for making a payment for an invoice.

The following props are required:

/**
* Account locator
*/
accountLocator: string;
/**
* Invoice locator
*/
invoiceLocator: string;

/**
* The currency of the invoice
*/
currency: CurrencyType;
/**
* The resolved data model retrieved from data model response
*/
dataModel: DataModel;
/**
* The function to call when the form is submitted. It will create an PaymentRequest from the form data.
*/
handleSubmit: (data: PaymentRequest) => void;
/**
* Invoice balance
*/
invoiceBalance: number;

The following props are optional:

/**
* Set to true when the form is submitting to set fields to readonly and disable the submit button
*/
isSubmitting?: boolean;
/**
* Disables the form
*/
disabled?: boolean;
/**
* Hides the submit button
*/
hideSubmitButton?: boolean;
/**
* Whether to validate the form on submit
*/
validateOnSubmit?: boolean;
/**
* The text to display on the submit button
*/
submitButtonText?: string;
/**
* ID for the form wrapper
* */
id?: string;

/**
* Titles
*/
titles?: {
  formTitle?: string;
} & Partial<GetPaymentFormDefaultFieldsProps['titles']>;

Renders the following (and dynamically adjusts based on the DataModel):

ExistingPaymentForm

The existing payment form takes account’s locator, account’s balance, invoice’s locator, invoice’s balance, currency, along with a handleSubmit function, and renders a form that allows for applying existing account’s balance to an invoice.

The following props are required:

/**
* Account locator
*/
accountLocator: string;
/**
* Invoice locator
*/
invoiceLocator: string;

/**
* The currency of the invoice
*/
currency: CurrencyType;

/**
* Account balance
*/
balance: number;

/**
* The function to call when the form is submitted. It will create an CreditDistributionRequest from the form data.
*/
handleSubmit: (data: CreditDistributionRequest) => void;

/**
* Invoice balance
*/
invoiceBalance: number;

The following props are optional:

/**
* Set to true when the form is submitting to set fields to readonly and disable the submit button
*/
isSubmitting?: boolean;
/**
* Disables the form
*/
disabled?: boolean;
/**
* Hides the submit button
*/
hideSubmitButton?: boolean;
/**
* Whether to validate the form on submit
*/
validateOnSubmit?: boolean;
/**
* The text to display on the submit button
*/
submitButtonText?: string;
/**
* ID for the form wrapper
* */
id?: string;

/**
* Titles
*/
titles?: {
  formTitle?: string;
  balance?: string;
  amountToApply?: string;
  invoiceBalance?: string;
};

Renders the following:

../../_images/payment-large-form-field.png

Utils

@socotra/ec-react-utils is a package of utility functions that assist in the development of apps for EC.

Installation

npm i @socotra/ec-react-utils

Example Usage

After installation, import components from the root of the package as needed.

In the example below, we use extractElementDataModel and extractElementFromQuote to grab the pieces we need to pass to ElementForm

// Server Component
import { ElementCard } from '@/components/element-card';
import {
  extractElementDataModel,
  extractElementFromQuote,
} from '@socotra/ec-react-utils';
import {
  getDataModel,
  getQuote,
} from '@/app/actions/quote-actions';

interface Props {
  params: {
    lang: Locale;
    tenantLocator: string;
    quoteLocator: string;
    elementLocator: string;
    elementType: string;
  };
}

export default async function Page(props: Props) {
  const { lang, tenantLocator, quoteLocator, elementLocator } = props.params;
  const quote = await getQuote(tenantLocator, quoteLocator, lang);
  const dataModel = await getDataModel(tenantLocator);

  const elementDataModel = extractElementDataModel({
    dataModel,
    quote,
    elementLocator,
  });

  const element = extractElementFromQuote(quote, elementLocator);

  return (
    <div className='flex flex-col'>
      <ElementCard
        element={element}
        elementModel={elementDataModel}
        dataTypes={dataModel.dataTypes}
        coverageTerms={dataModel.coverageTerms}
      />
    </div>
  );
}

// Client Component
'use client';
import { useTransition } from 'react';
import { ElementForm } from '@socotra/ec-react-components';
import {
  CoverageTermsConfigRecord,
  DataTypeConfigRecord,
  ElementConfig,
  ElementRequest,
  ElementResponse,
} from '@socotra/ec-react-schemas';


interface ElementCardProps {
  element: ElementResponse;
  dataTypes: DataTypeConfigRecord;
  coverageTerms: CoverageTermsConfigRecord;
  elementModel: ElementConfig;
}

export const ElementCard = ({
  element,
  dataTypes,
  coverageTerms,
  elementModel,
}: ElementCardProps) => {
  const [isSubmitting, startTransition] = useTransition();
  const handleSubmit = async (element: ElementRequest) => {
    ...
  }

  return (
    <ElementForm
      elementModel={elementModel}
      coverageTerms={coverageTerms}
      dataTypes={dataTypes}
      element={element}
      handleSubmit={handleSubmit}
      disabled={isSubmitting}
    />
  );
};

List of Utils

Exported Functions

  • dataModelToJSONSchema

    • Transforms a DataModel to a valid JSON Schema 7 response

  • splitInputAndQuantifier

    • Takes an input name from the config and splits off the quantifier..

    • E.g., “drivers?” becomes { name: “drivers”, quantifier: “?” }

  • getQuoteRequest

    • Used by the QuoteForm internally to transform the form values into a QuoteRequest

  • getDefaultQuoteValues

    • Used by the QuoteForm internally to set default values for the form from a QuoteResponse, ProductConfig, and DataModel

  • getDefaultElementValues

    • Used by the ElementForm internally to set default values for the form from an ElementResponse

  • extractElementDataModel

    • Takes a QuoteResponse, element locator, and DataModel and returns the ElementConfig

  • extractElementFromQuote

    • Takes a QuoteResponse and element locator and returns the ElementResponse

  • extractProductDataModel

    • Takes a DataModel and productName and returns the found ProductConfig

  • extractProductElements

    • Takes a DataModel and ProductConfig and returns a ProductElementMap (shown below)

export interface ProductElementMap {
  coverages: ProductElement;
  exposures: ProductElement;
  policyLines: ProductElement;
  exposureGroups: ProductElement;
}