vlocity-dc-main/vlocity-dc-main.js

/*************************************************************************
 *
 * VLOCITY, INC. CONFIDENTIAL
 * __________________
 *
 *  [2014] - [2020] Vlocity, Inc.
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Vlocity, Inc. and its suppliers,
 * if any. The intellectual and technical concepts contained
 * herein are proprietary to Vlocity, Inc. and its suppliers and may be
 * covered by U.S. and Foreign Patents, patents in process, and are
 * protected by trade secret or copyright law. Dissemination of this
 * information and reproduction, modification or reverse-engineering
 * of this material, is prohibited unless prior written permission
 * is obtained from Vlocity, Inc.
 *
 */
import { LitElement, html } from "lit-element";
import { installRouter } from "pwa-helpers/router.js";
import "../vlocity-dc-global-header/vlocity-dc-global-header.js";
import "../vlocity-dc-home-page/vlocity-dc-home-page.js";
import "../vlocity-dc-offer-config/vlocity-dc-offer-config.js";
import "../vlocity-dc-offer-addons/vlocity-dc-offer-addons.js";
import "../vlocity-dc-shopping-cart/vlocity-dc-shopping-cart.js";
import "../vlocity-dc-checkout/vlocity-dc-checkout.js";
import "../vlocity-dc-my-account/vlocity-dc-my-account.js";
import { digitalCommerceSDKInstance } from "../vlocity-dc-utils/vlocity-dc-sdk-utils";
import { DCCustomLabels } from "../vlocity-dc-utils/vlocity-dc-custom-labels";
import VlocityDCBaseComponent from "../vlocity-dc-base-component/vlocity-dc-base-component";

/**
 * @class VlocityDCMain
 * @extends {VlocityDCBaseComponent} Extends the VlocityDCBaseComponent base class
 *
 * @classdesc
 * vlocity-dc-main is the container component which has the internal navigation logic between different screens/phases
 *
 * @example
 * Sample Usage -
 *
 * Include the component in your template by adding vlocity-dc-main custom tag
 *
 * <vlocity-dc-main></vlocity-dc-main>
 *
 *  KEY INFO -
 *
 *  events fired : none
 *
 *  events registered :
 *
 *                | Event Name                         | Event source component                                                                                  | Callback Function      |
 *                |------------------------------------|---------------------------------------------------------------------------------------------------------|------------------------|
 *                |                                    | Mutiple Event Sources:                                                                                  |                        |
 *                |                                    |      | Component Name                        | Description                                         |    |                        |
 *                | vlocity-dc-route-navigation        |      |---------------------------------------|-----------------------------------------------------|    | customNavigation()     |
 *                |                                    |      | vlocity-dc-assets-list                | Event for navigation                                |    |                        |
 *                |                                    |      | vlocity-dc-checkout                   |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-global-header              |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-offer-addons               |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-offer-config               |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-offer-group-selections     |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-offer-list                 |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-shopping-cart              |                                                     |    |                        |
 *                |                                    |      | vlocity-dc-totalbar                   |                                                     |    |                        |
 *                |                                    |                                                                                                         |                        |
 *                |                                    | Mutiple Event Sources:                                                                                  |                        |
 *                |                                    |      | Component Name                        | Description                                         |    |                        |
 *                | vlocity-dc-update-catalog-code     |      |---------------------------------------|-----------------------------------------------------|    | updateCatalogCode()    |
 *                |                                    |      | vlocity-dc-catalog                    | Event for updating catalog code                     |    |                        |
 *                |                                    |      | vlocity-dc-child-catalog              |                                                     |    |                        |
 *                |                                    |                                                                                                         |                        |
 *                | vlocity-dc-login-complete          | vlocity-dc-signin                                                                                       | handleUserLogin()      |
 *                |                                    |                                                                                                         |                        |
 *                | vlocity-dc-sign-out                | vlocity-dc-global-header                                                                                | handleUserLogin()      |
 *                |                                    |                                                                                                         |                        |
 *
 *
 *  Dependency - vlocity-dc-main is an independent component and has no dependency on parent component.
 *  It is commonly used as a container component where main screens/phases navigation logic resides
 *
 *                | Parent Component | Expected Children Components |
 *                |------------------|------------------------------|
 *                | none             | vlocity-dc-global-header     |
 *                |                  | vlocity-dc-home-page         |
 *                |                  | vlocity-dc-offer-config      |
 *                |                  | vlocity-dc-offer-addons      |
 *                |                  | vlocity-dc-shopping-cart     |
 *                |                  | vlocity-dc-checkout          |
 *                |                  | vlocity-dc-my-account        |
 *
 */
export default class VlocityDCMain extends VlocityDCBaseComponent {
  constructor() {
    super();
    this.digitalCommerceSDK = digitalCommerceSDKInstance().digitalCommerce;
    this.digitalCommerceTranslation = digitalCommerceSDKInstance().digitalCommerceTranslation;
    this.datasource = this.digitalCommerceSDK.datasource;
    this.language = digitalCommerceSDKInstance().digitalCommerce.language
      ? digitalCommerceSDKInstance().digitalCommerce.language
      : "en_US";
    this.page = "";
    this.parentCatalogCode = "";
    this.catalogCode = "";
    this.offerCode = "";
    this.urlAttributes = "";
    this.promoList = [];
    this.checkoutPaymentUrl = document
      .querySelector("[name=vlocity-dc-payment-url][value]")
      .getAttribute("value");
    this.dueToday = "";
    this.dueMonthly = "";
    this.userInfo = sessionStorage.getItem("userInfo") || {};
    this.orderId = "";
    this.isLoggedIn = sessionStorage.getItem("isLoggedIn") || false;
    this.isAsset = false;
    this.cartResponse = null;
    this.cartContextKey = sessionStorage.getItem("cartContextKey") || "";
  }

  template() {
    return html`
      <link type="text/css" rel="stylesheet" href="${this.ndsLibPath}" />
      <!-- Global header -->
      ${this.page !== "" && !this.page.match(/^checkOut*/)
        ? html`
            <vlocity-dc-global-header
              isLoggedIn="${this.isLoggedIn}"
            ></vlocity-dc-global-header>
          `
        : ""}
      <!-- pages -->
      <!-- home view -->
      ${this.page === "home" || this.page === ""
        ? html`
            <vlocity-dc-home-page
              parentCatalogCode="${this.parentCatalogCode}"
              catalogCode="${this.catalogCode}"
              name="home"
              class="active"
            ></vlocity-dc-home-page>
          `
        : html``}
      ${this.page !== "" && this.page.match(/^config*/)
        ? html`
            <vlocity-dc-offer-config
              name="config"
              catalogCode="${this.catalogCode}"
              offerCode="${this.offerCode}"
              urlParams="${this.urlAttributes}"
              class="active"
            >
            </vlocity-dc-offer-config>
          `
        : html``}
      ${this.page !== "" && this.page.match(/^addons*/)
        ? html`
            <vlocity-dc-offer-addons
              name="addons"
              class="active"
              catalogCode="${this.catalogCode}"
              offerCode="${this.offerCode}"
              .promoList="${this.promoList}"
            ></vlocity-dc-offer-addons>
          `
        : html``}
      ${this.page !== "" && this.page.match(/^shoppingcart*/)
        ? html`
            <vlocity-dc-shopping-cart
              isAsset="${this.isAsset}"
              isLoggedIn="${this.isLoggedIn}"
              catalogCode="${this.catalogCode}"
              cartContextKey="${this.cartContextKey}"
              .cartResponse="${this.cartResponse}"
            ></vlocity-dc-shopping-cart>
          `
        : html``}
      ${this.page !== "" && this.page.match(/^checkOut*/)
        ? html`
            <vlocity-dc-checkout
              isLoggedIn="${this.isLoggedIn}"
              dueToday=${this.dueToday}
              dueMonthly=${this.dueMonthly}
              catalogCode=${this.catalogCode}
              cartContextKey="${this.cartContextKey}"
              checkoutPaymentUrl=${this.checkoutPaymentUrl}
              .userInfo="${this.userInfo}"
              orderId=${this.orderId}
            ></vlocity-dc-checkout>
          `
        : html``}
      ${this.page !== "" &&
        this.page.match(/^account*/) &&
        html`
          <vlocity-dc-my-account></vlocity-dc-my-account>
        `}
    `;
  }
  static get properties() {
    return {
      page: String,
      parentCatalogCode: String,
      catalogCode: String,
      offerCode: String,
      isLoggedIn: Boolean,
      isAsset: Boolean,
      cartContextKey: String,
      userInfo: String,
      cartResponse: Object
    };
  }

  static get is() {
    return "vlocity-dc-main";
  }

  /**
   * Method to create render root
   * @memberof VlocityDCMain
   */
  createRenderRoot() {
    return this;
  }

  /**
   * Method to render template
   * @memberof VlocityDCMain
   */
  render() {
    return this.template();
  }

  connectedCallback() {
    super.connectedCallback();
    installRouter(location =>
      this.navigate(decodeURIComponent(location.pathname))
    );
    this.getLabels(DCCustomLabels, this.language);
    if (this.digitalCommerceSDK) {
      this.customNavigationEventHandler = {
        result: this.customNavigation.bind(this)
      };
      this.updateCatalogCodeEventHandler = {
        result: this.updateCatalogCode.bind(this)
      };
      this.handleUserLoginEventHandler = {
        result: this.handleUserLogin.bind(this)
      };
      this.digitalCommerceSDK.register(
        "vlocity-dc-route-navigation",
        this.customNavigationEventHandler
      );

      this.digitalCommerceSDK.register(
        "vlocity-dc-update-catalog-code",
        this.updateCatalogCodeEventHandler
      );

      this.digitalCommerceSDK.register(
        "vlocity-dc-login-complete",
        this.handleUserLoginEventHandler
      );

      this.digitalCommerceSDK.register(
        "vlocity-dc-sign-out",
        this.handleUserLoginEventHandler
      );
    }
  }

  /**
   * Method to update catalog code
   * @memberof VlocityDCMain
   */
  updateCatalogCode(data) {
    if (data.parentCatalogCode) {
      this.parentCatalogCode = data.parentCatalogCode;
    } else if (data.catalogCode) {
      this.catalogCode = data.catalogCode;
    }
  }

  /**
   * Method to get getLabels from Translation SDK
   * @param {Array} labelList - array of labelKeys
   * @param {String} language - language code
   * @memberof VlocityDCMain
   */
  getLabels(labelList, language) {
    const translationSDK = digitalCommerceSDKInstance()
      .digitalCommerceTranslation;
    const fetchTranslationsInput = translationSDK.createFetchTranslationsInput();
    fetchTranslationsInput.textToTranslate = labelList;
    fetchTranslationsInput.language = language;
    return translationSDK.fetchTranslations(fetchTranslationsInput);
  }

  /**
   * Method to navigate route
   * @param {String} path - route path
   * @memberof VlocityDCMain
   */
  navigate(path) {
    if (path === "/") {
      this.page = "home";
    } else {
      this.page = path.slice(1);
    }
    this.setAttributes(this.page);
    this.render();
  }

  /**
   * Method to push route state
   * @memberof VlocityDCMain
   */
  customNavigation(routeData) {
    window.history.pushState({}, "", routeData.defaultRouteUrl);
    if (routeData.data && routeData.data.promoList) {
      this.promoList = routeData.data.promoList;
    }
    if (routeData.data && routeData.data.paymentInfo) {
      this.dueToday = routeData.data.paymentInfo.dueToday;
      this.dueMonthly = routeData.data.paymentInfo.dueMonthly;
    }
    if (
      routeData.data &&
      routeData.data.userInfo &&
      routeData.data.userInfo.email
    ) {
      this.userInfo = routeData.data.userInfo;
    }
    if (routeData.data && routeData.data.orderId) {
      this.orderId = routeData.data.orderId;
    }
    if (routeData.data && routeData.data.catalogCode) {
      this.catalogCode = routeData.data.catalogCode;
    }
    if (routeData.data && routeData.data.cartResponse) {
      this.cartResponse = routeData.data.cartResponse;
    }
    if (routeData.source === "assets") {
      this.isAsset = true;
    }

    this.navigate(routeData.defaultRouteUrl);
  }

  /**
   * Method to push route state
   * @param {String} path - route path
   * @memberof VlocityDCMain
   */
  setAttributes(path) {
    if (path) {
      const pathArr = this.getParamsFromUrl(path);
      if (pathArr.length >= 3) {
        this.catalogCode = pathArr[1];
        if (pathArr[0] !== "shoppingcart") {
          this.offerCode = pathArr[2];
        } else {
          this.cartContextKey = sessionStorage.getItem("cartContextKey") || "";
        }
        if (pathArr.length === 4) {
          this.urlAttributes = pathArr[3];
        }
      }
    }
  }

  /**
   * Method to split params from URL
   * @memberof VlocityDCMain
   */
  getParamsFromUrl(path) {
    return path.split("/");
  }

  /**
   * Method to handle user login
   * @param {object} data
   * @memberof VlocityDCMain
   */
  handleUserLogin(data) {
    if (data && (data.name || data.email)) {
      this.isLoggedIn = true;
      this.userInfo = {
        email: data.email,
        name: data.name
      };
      sessionStorage.setItem("isLoggedIn", true);
      sessionStorage.setItem("userInfo", this.userInfo);
    } else {
      this.isLoggedIn = false;
      sessionStorage.setItem("isLoggedIn", false);
      sessionStorage.setItem("userInfo", {});
      this.userInfo = {};
    }
  }
}

/**
 *  Register vlocity-dc-main on the CustomElementRegistry using the define().
 */
customElements.define(VlocityDCMain.is, VlocityDCMain);