unit AddCustomer;

interface

uses
  System.SysUtils, System.Generics.Collections, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
  WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
  WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
  ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
  Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, WEBLib.Grids;

type
  TFViewAddCustomer = class(TWebForm)
    dtpStartDate: TWebDateTimePicker;
    dtpEndDate: TWebDateTimePicker;
    edtShortName: TWebDBEdit;
    edtName: TWebDBEdit;
    edtBillAddress: TWebDBEdit;
    edtBillCity: TWebDBEdit;
    edtBillState: TWebDBEdit;
    edtBillZip: TWebDBEdit;
    edtBillContact: TWebDBEdit;
    edtPhone: TWebDBEdit;
    edtFax: TWebDBEdit;
    edtRep: TWebDBEdit;
    btnSave: TWebButton;
    btnCancel: TWebButton;
    btnDelete: TWebButton;
    btnClose: TWebButton;
    btnEdit: TWebButton;
    pnlMessage: TWebPanel;
    lblMessage: TWebLabel;
    btnCloseNotification: TWebButton;
    XDataWebClient1: TXDataWebClient;
    WebDataSource1: TWebDataSource;
    XDataWebDataSet1: TXDataWebDataSet;
    XDataWebDataSet1SHORT_NAME: TStringField;
    XDataWebDataSet1NAME: TStringField;
    XDataWebDataSet1BILL_ADDRESS: TStringField;
    XDataWebDataSet1BILL_CITY: TStringField;
    edtCustomerID: TWebDBEdit;
    edtQBID: TWebDBEdit;
    wdbtcAddresses: TWebDBTableControl;
    wdsShipTo: TWebDataSource;
    xdwdsShipTo: TXDataWebDataSet;
    XDataWebDataSet1BILL_STATE: TStringField;
    XDataWebDataSet1BILL_CONTACT: TStringField;
    XDataWebDataSet1BILL_ZIP: TStringField;
    XDataWebDataSet1START_DATE: TStringField;
    XDataWebDataSet1END_DATE: TStringField;
    XDataWebDataSet1QB_LIST_ID: TStringField;
    XDataWebDataSet1FAX: TStringField;
    XDataWebDataSet1PHONE: TStringField;
    XDataWebDataSet1REP_USER_ID: TIntegerField;
    XDataWebDataSet1CUSTOMER_ID: TIntegerField;
    edtShippingAddress: TWebEdit;
    edtShippingState: TWebEdit;
    edtShippingContact: TWebEdit;
    edtShippingZip: TWebEdit;
    edtShippingCity: TWebEdit;
    xdwdsShipToADDRESS: TStringField;
    xdwdsShipToship_id: TStringField;
    xdwdsShipToshipping_address: TStringField;
    xdwdsShipTocity: TStringField;
    xdwdsShipTostate: TStringField;
    xdwdsShipTozip: TStringField;
    xdwdsShipTocontact: TStringField;
    memoShipBlock: TWebMemo;
    memoAddressBlock: TWebMemo;
    btnAdd: TWebButton;
    btnShipSave: TWebButton;
    btnShipCancel: TWebButton;
    btnShipDelete: TWebButton;
    btnShipEdit: TWebButton;
    btnShipAdd: TWebButton;
    btn_confirm_delete: TWebButton;
    tmrReturn: TWebTimer;
    edtFirstLine: TWebEdit;
    procedure WebFormShow(Sender: TObject);
    procedure btnCloseNotificationClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnCancelClick(Sender: TObject);
    procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
    procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
    procedure btnCloseClick(Sender: TObject);
    procedure btnEditClick(Sender: TObject);
    procedure wdbtcAddressesDblClickCell(Sender: TObject; ACol, ARow: Integer);
    procedure btnClearClick(Sender: TObject);
    procedure memoAddressBlockChange(Sender: TObject);
    procedure AddressEditMode();
    procedure edtShippingAddressChange(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
    procedure btn_confirm_deleteClick(Sender: TObject);
    procedure tmrReturnTimer(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure btnShipAddClick(Sender: TObject);
    procedure btnShipEditClick(Sender: TObject);
    procedure btnShipSaveClick(Sender: TObject);
    procedure btnShipDeleteClick(Sender: TObject);
  private
    { Private declarations }

    procedure HideNotification();
    procedure ShowNotification(Notification: string);
    procedure ViewMode();
    procedure EditMode();
    [async] procedure GetCustomer();
    [async] procedure SendCustomerToServer();
    [async] procedure SendAddressToServer();
    [async] procedure DelAddress();
    function VerifyCustomer(): boolean;
    function VerifyAddress(): boolean;
    procedure Clear();
  var
    customerID: string;
    notification: string;
    mode: string;
    shipmode: string;
  public
    { Public declarations }
     class function CreateForm(AElementID, customerInfo, info: string): TWebForm;
  end;

var
  FViewAddCustomer: TFViewAddCustomer;

implementation

{$R *.dfm}

uses View.Main, View.Customers;

procedure TFViewAddCustomer.Clear();
begin
  edtShippingAddress.Text := '';
  edtShippingCity.Text := '';
  edtShippingState.Text := '';
  edtShippingZip.Text := '';
  edtShippingContact.Text := '';
  memoShipBlock.Text := '';
  edtFirstLine.Text := '';
end;

procedure TFViewAddCustomer.DelAddress;
var
  Response: TXDataClientResponse;
  notification: TJSObject;
begin
  Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelShippingAddress',
              [xdwdsShipTo.FieldByName('ship_id').AsString, customerID]));
  notification := TJSObject(Response.Result);
  ShowNotification(string(notification['status']));
  xdwdsShipTo.Close;
  xdwdsShipTo.SetJSONData(notification['ADDRESS']);
  xdwdsShipTo.Open;
  asm
    endSpinner();
  end;
end;

procedure TFViewAddCustomer.SendAddressToServer;
var
  Field: TField;
  AddressJSON: TJSONObject;
  Response: TXDataClientResponse;
  notification: TJSObject;
  ship_block: string;
begin
  AddressJSON := TJSONObject.Create;

  AddressJSON.AddPair('address', edtShippingAddress.Text);
  AddressJSON.AddPair('city', edtShippingcity.Text);
  AddressJSON.AddPair('state', edtShippingstate.Text);
  AddressJSON.AddPair('zip', edtShippingzip.Text);
  AddressJSON.AddPair('contact', edtShippingContact.Text);
  AddressJSON.AddPair('customer_id', customerID);

  ship_block := edtFirstLine.Text + slinebreak +
                edtName.Text + slinebreak +
                edtShippingContact.Text + slinebreak +
                edtShippingAddress.Text + slinebreak +
                edtShippingCity.Text + ', ' + edtShippingState.Text + ' ' + edtShippingZip.Text;
  AddressJSON.AddPair('ship_block', ship_block);

  if shipmode = 'EDIT' then
    AddressJSON.AddPair('customer_ship_id', xdwdsShipTo.FieldByName('ship_id').AsString);

  AddressJSON.AddPair('mode', shipmode);

  Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddShippingAddress',
              [AddressJSON.ToString]));

  notification := TJSObject(Response.Result);
  ShowNotification(string(notification['status']));
  xdwdsShipTo.Close;
  xdwdsShipTo.SetJSONData(notification['ADDRESS']);
  xdwdsShipTo.Open;
end;

procedure TFViewAddCustomer.btnAddClick(Sender: TObject);
begin
  FViewMain.ViewAddCustomer('', '');
end;

procedure TFViewAddCustomer.btnCancelClick(Sender: TObject);
begin
  document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?';
  document.getElementById('btn_confirm_cancel').innerText := 'No';
  document.getElementById('btn_confirm_delete').innerText := 'Yes';
  asm
    var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
    keyboard: false });
    confirmationModal.show();
  end;
end;

procedure TFViewAddCustomer.btnClearClick(Sender: TObject);
begin
  Clear();
end;

procedure TFViewAddCustomer.btnCloseClick(Sender: TObject);
begin
  FViewMain.ShowForm(TFViewCustomers)
end;

procedure TFViewAddCustomer.btnCloseNotificationClick(Sender: TObject);
begin
  HideNotification();
end;

procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject);
begin
  ShowMessage('Deleting Customers Is Not Yet Available');
end;

procedure TFViewAddCustomer.btnEditClick(Sender: TObject);
begin
  EditMode();
end;

procedure TFViewAddCustomer.edtShippingAddressChange(Sender: TObject);
begin
  AddressEditMode();
end;

procedure TFViewAddCustomer.EditMode;
begin
  FViewMain.change := true;
  btnAdd.Enabled := false;
  btnDelete.Enabled := false;
  btnClose.Enabled := false;
  btnSave.Enabled := true;
  btnCancel.Enabled := True;
  btnEdit.Enabled := false;

  // Disable Shipping Address Editting
  edtShippingAddress.Enabled := false;
  edtShippingCity.Enabled := false;
  edtShippingState.Enabled := false;
  edtShippingZip.Enabled := false;
  edtShippingContact.Enabled := false;
  edtFirstLine.Enabled := false;

  btnShipDelete.Enabled := false;
  btnShipSave.Enabled := false;
  btnShipCancel.Enabled := false;
  btnShipEdit.Enabled := false;
  btnShipAdd.Enabled := false;

end;

procedure TFViewAddCustomer.AddressEditMode;
begin
  FViewMain.change := true;
  btnDelete.Enabled := false;
  btnClose.Enabled := false;
  btnSave.Enabled := false;
  btnCancel.Enabled := false;
  btnEdit.Enabled := false;
  btnAdd.Enabled := false;

  btnShipDelete.Enabled := false;
  btnShipSave.Enabled := true;
  btnShipCancel.Enabled := true;
  btnShipEdit.Enabled := false;
  btnShipAdd.Enabled := false;

  edtShippingAddress.Enabled := true;
  edtShippingCity.Enabled := true;
  edtShippingState.Enabled := true;
  edtShippingZip.Enabled := true;
  edtShippingContact.Enabled := true;
  edtFirstLine.Enabled := true;

  edtName.Enabled := false;
  edtShortName.Enabled := false;
  edtBillAddress.Enabled := false;
  edtBillCity.Enabled := false;
  edtBillState.Enabled := false;
  edtBillZip.Enabled := false;
  edtBillContact.Enabled := false;
  dtpStartDate.Enabled := false;
  dtpEndDate.Enabled := false;
  edtFax.Enabled := false;
  edtPhone.enabled := false;
  edtRep.Enabled := false;
end;

procedure TFViewAddCustomer.ViewMode;
begin
  btnAdd.Enabled := true;
  btnDelete.Enabled := true;
  btnClose.Enabled := true;
  btnSave.Enabled := false;
  btnCancel.Enabled := false;
  btnEdit.Enabled := true;
  FViewMain.change := false;

  btnShipAdd.Enabled := true;
  btnShipDelete.Enabled := true;
  btnShipSave.Enabled := false;
  btnShipCancel.Enabled := false;
  btnShipEdit.Enabled := true;
  FViewMain.change := false;

  // Make Sure Customer is editable
  edtName.Enabled := true;
  edtShortName.Enabled := true;
  edtBillAddress.Enabled := true;
  edtBillCity.Enabled := true;
  edtBillState.Enabled := true;
  edtBillZip.Enabled := true;
  edtBillContact.Enabled := true;
  dtpStartDate.Enabled := true;
  dtpEndDate.Enabled := true;
  edtFax.Enabled := true;
  edtPhone.enabled := true;
  edtRep.Enabled := true;

end;

procedure TFViewAddCustomer.wdbtcAddressesDblClickCell(Sender: TObject; ACol,
  ARow: Integer);
begin
  xdwdsShipTo.Locate('ship_id', wdbtcAddresses.Cells[0, ARow], []);
  edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString;
  edtShippingCity.Text := xdwdsShipTo.FieldByName('city').AsString;
  edtShippingState.Text := xdwdsShipTo.FieldByName('state').AsString;
  edtShippingZip.Text := xdwdsShipTo.FieldByName('zip').AsString;
  edtShippingContact.Text := xdwdsShipTo.FieldByName('contact').AsString;
  memoShipBlock.Text := xdwdsShipTo.FieldByName('ADDRESS').AsString;
  edtFirstLine.Text := memoShipBlock.Lines[0];
end;

procedure TFViewAddCustomer.SendCustomerToServer();
var
  customerJSON: TJSONObject;
  Field: TField;
  Response: TXDataClientResponse;
  notification: TJSObject;
  input: TJSHTMLElement;
  msg: string;
begin

  customerJSON := TJSONObject.Create;

  if dtpStartDate.Date <> 0 then
    XDataWebDataSet1START_DATE.Value := DateTimeToStr(dtpStartDate.Date);

  if dtpEndDate.Date <> 0 then
    XDataWebDataSet1END_DATE.Value := DateTimeToStr(dtpEndDate.Date);

  XDataWebDataSet1.First;

  while not XDataWebDataSet1.Eof do
  begin
    for Field in XDataWebDataSet1.Fields do
    begin
      if Field is TStringField then
      begin
        if Field.AsString = '' then
          customerJSON.AddPair(Field.FieldName, '')
        else
          customerJSON.AddPair(Field.FieldName, Field.AsString);  // Add all other fields
      end
      else if Field is TIntegerField then
      begin
        customerJSON.AddPair(Field.FieldName, Field.AsString);
      end;
    end;
    XDataWebDataSet1.Next;
  end;

  customerJSON.AddPair('BILL_ADDRESS_BLOCK', memoAddressBlock.Text);

  customerJSON.AddPair('mode', mode);
  if mode = 'EDIT' then
    customerJSON.AddPair('CUSTOMER_ID', customerID);

  Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCustomer',
              [customerJSON.ToString]));

  notification := TJSObject(Response.Result);
  msg := string(notification['status']);
  ShowNotification(msg);

  if msg.Contains('Failure') then
  begin
    input := TJSHTMLInputElement(document.getElementById('edtcompanyaccountname'));
    input.classList.add('is-invalid');
    input := TJSHTMLInputElement(document.getElementById('shortnamefeedback'));
    input.innerHTML := 'Company Account Name must be Unique.' ;
  end;

end;

procedure TFViewAddCustomer.btnSaveClick(Sender: TObject);
begin
  if VerifyCustomer() then
  begin
    sendCustomerToServer();
    ViewMode();
  end;
end;

procedure TFViewAddCustomer.btnShipAddClick(Sender: TObject);
begin
  shipmode := 'ADD';
  Clear();
  AddressEditMode();
end;

procedure TFViewAddCustomer.btnShipDeleteClick(Sender: TObject);
begin
  document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this address?';
  document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
  document.getElementById('btn_confirm_delete').innerText := 'Delete';
  asm
    var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
    keyboard: false });
    confirmationModal.show();
  end;
end;

procedure TFViewAddCustomer.btnShipEditClick(Sender: TObject);
begin
  shipmode := 'EDIT';
  AddressEditMode();
end;

procedure TFViewAddCustomer.btnShipSaveClick(Sender: TObject);
begin
  if VerifyAddress() then
  begin
    SendAddressToServer();
    Clear();
    ViewMode();
  end;
end;

procedure TFViewAddCustomer.btn_confirm_deleteClick(Sender: TObject);
begin
  if  document.getElementById('btn_confirm_delete').innerText = 'Yes' then
  // checks if the modal is canceling
  begin
    if CustomerID <> '' then
    begin
      FViewMain.ViewAddCustomer(CustomerID, 'Failure:Changes Discarded');
    end
    else
      FViewMain.ShowForm(TFViewCustomers);
  end
  else if document.getElementById('modal_body').innerHTML.Contains('customer') then
  // checks if the user is deleting a customer or a shipping address
  begin
    asm
      var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
      keyboard: false });
      confirmationModal.hide();
      startSpinner();
    end;
    //delCustomer();
    tmrReturn.Enabled := true;
  end
  else
  begin
    asm
      var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
      keyboard: false });
      confirmationModal.hide();
      startSpinner();
    end;
    delAddress();
  end;
end;

class function TFViewAddCustomer.CreateForm(AElementID: string; customerInfo: string; info: string): TWebForm;
begin
  Application.CreateForm(TFViewAddCustomer, AElementID, Result,
    procedure(AForm: TObject)
    begin
      with TFViewAddCustomer(AForm) do
      begin
        TFViewAddCustomer(AForm).customerID := customerInfo;
        TFViewAddCustomer(AForm).notification := info;
      end;
    end
  );

end;

procedure TFViewAddCustomer.GetCustomer;
var
  xdcResponse: TXDataClientResponse;
  customer : TJSObject;
  address: string;
  items: TJSObject;
  ship_block: TStringList;
begin
  if CustomerID = '' then
  begin
    customerID := '-1';
    mode := 'ADD';
  end
  else
    mode := 'EDIT';
  xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer',
        [customerID]));
  customer :=  TJSObject(xdcResponse.Result);
  XDataWebDataSet1.Close;
  XDataWebDataSet1.SetJsonData(customer);
  XDataWebDataSet1.Open;

  if CustomerID = '-1' then
  begin
    edtCustomerID.Text := '';
  end;

  if XDataWebDataSet1.FieldByName('START_DATE').AsString <> '' then
    dtpStartDate.Date := XDataWebDataSet1.FieldByName('START_DATE').AsDateTime;

  if XDataWebDataSet1.FieldByName('END_DATE').AsString <> '' then
    dtpEndDate.Date := XDataWebDataSet1.FieldByName('End_DATE').AsDateTime;

  xdwdsShipTo.Close;
  xdwdsShipTo.SetJSONData(customer['ADDRESS_LIST']);
  xdwdsShipTo.Open;

  memoAddressBlock.Text :=  string(customer['staff_fields_invoice_to']);

  edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString;
  edtShippingCity.Text := xdwdsShipTo.FieldByName('city').AsString;
  edtShippingState.Text := xdwdsShipTo.FieldByName('state').AsString;
  edtShippingZip.Text := xdwdsShipTo.FieldByName('zip').AsString;
  edtShippingContact.Text := xdwdsShipTo.FieldByName('contact').AsString;
  memoShipBlock.Text := xdwdsShipTo.FieldByName('ADDRESS').AsString;
  edtFirstLine.Text := memoShipBlock.Lines[0];

end;

procedure TFViewAddCustomer.WebFormShow(Sender: TObject);
var
  SQL: string;
begin
  if notification = '' then
    hideNotification()
  else
    showNotification(notification);

  if mode = 'ADD' then
    EditMode()
  else
    ViewMode();

  getCustomer();

  dtpStartDate.Date := 0;
  dtpEndDate.Date := 0;
end;

procedure TFViewAddCustomer.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
  EditMode();
end;

procedure TFViewAddCustomer.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin
  EditMode();
end;

procedure TFViewAddCustomer.HideNotification;
begin
  pnlMessage.ElementHandle.hidden := True;
end;

procedure TFViewAddCustomer.memoAddressBlockChange(Sender: TObject);
begin
  EditMode();
end;

procedure TFViewAddCustomer.ShowNotification(Notification: string);
var
  splitNotification: TArray<string>;
begin
  if Notification <> '' then
  begin
    splitNotification := Notification.Split([':']);
    if(splitNotification[0] = 'Success') then
    begin
      asm
        var messageDiv = document.getElementById('view.login.message');
        messageDiv.classList.remove('alert-danger');
        messageDiv.classList.add('alert-success');
      end;
    end
    else
    begin
      asm
        var messageDiv = document.getElementById('view.login.message');
        messageDiv.classList.remove('alert-success');
        messageDiv.classList.add('alert-danger');
      end;
    end;
    lblMessage.Caption := splitNotification[1];
    pnlMessage.ElementHandle.hidden := False;
  end;
end;

procedure TFViewAddCustomer.tmrReturnTimer(Sender: TObject);
begin
  asm
    endSpinner();
  end;
  tmrReturn.Enabled := false;
  FViewMain.ViewCustomerList('Success:Customer Successfully Deleted');
end;

function TFViewAddCustomer.VerifyCustomer(): boolean;
var
  input: TJSHTMLElement;
begin
  result := true;

  // Company Verification
  input := TJSHTMLInputElement(document.getElementById('edtcompanyname'));
  if edtName.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');


  input := TJSHTMLInputElement(document.getElementById('edtcompanyaccountname'));
  if edtShortName.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');


  // Billing Information Verification
  input := TJSHTMLInputElement(document.getElementById('edtbillingaddress'));
  if edtBillAddress.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtbillingcity'));
  if edtBillCity.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtbillingstate'));
  if edtBillState.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtbillingzip'));
  if edtBillZip.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtbillingcontact'));
  if edtBillContact.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('memoaddressblock'));
  if memoAddressBlock.Lines.Count = 0 then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');
end;

function TFViewAddCustomer.VerifyAddress: Boolean;
var
  input: TJSHTMLElement;
begin
  result := true;
  input := TJSHTMLInputElement(document.getElementById('edtshippingaddress'));
  if edtShippingAddress.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtshippingcity'));
  if edtShippingCity.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtshippingstate'));
  if edtShippingState.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtshippingzip'));
  if edtShippingZip.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtshippingcontact'));
  if edtShippingContact.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtfirstline'));
  if edtFirstLine.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

end;

end.