unit View.Customers;

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,
  XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset,
  WEBLib.Grids;

type
  TFViewCustomers = class(TWebForm)
    lblEntries: TWebLabel;
    btnAddCustomer: TWebButton;
    wdbtcCustomers: TWebDBTableControl;
    wcbPageSize: TWebComboBox;
    pnlMessage: TWebPanel;
    lblMessage: TWebLabel;
    btnCloseNotification: TWebButton;
    XDataWebClient1: TXDataWebClient;
    wdsCustomers: TWebDataSource;
    xdwdsCustomers: TXDataWebDataSet;
    xdwdsCustomersNAME: TStringField;
    xdwdsCustomersSTART_DATE: TStringField;
    procedure WebFormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure GeneratePagination(TotalPages: Integer);
    [async] procedure GetCustomers(searchOptions: string);
    function GenerateSearchOptions(): string;
    procedure HideNotification();
    procedure ShowNotification(Notification: string);

    var
      PageNumber: integer;
      PageSize: integer;
      TotalPages: integer;
      info: string;

  public
    { Public declarations }
  end;

var
  FViewCustomers: TFViewCustomers;

implementation

uses
  XData.Model.Classes, View.Main;

{$R *.dfm}

Procedure TFViewCustomers.WebFormCreate(Sender: TObject);
// Initializes important values:
// PageNumber: What page number the user is on IE 1: 1-10, 2: 11-20 etc
// TotalPages: Total number of pages returned from the search.
// PageSize: Number of entries per page.
var
  today: TDateTime;
begin
  DMConnection.ApiConnection.Connected := True;
  PageNumber := 1;
  TotalPages := 1; // Initial total pages
  wcbPageSize.Text := '500';
  PageSize := 500;
  HideNotification();
  getCustomers(GenerateSearchOptions());
end;

procedure TFViewCustomers.GetCustomers(searchOptions: string);
// retrieves a list of Customers that fit a given search criteria
// searchOptions: search info to be sent to the server
var
  xdcResponse: TXDataClientResponse;
  customerList: TJSObject;
  customerListLength: integer;
  TotalPages: integer;
begin
  if PageNumber > 0 then
  begin
    asm
      startSpinner();
    end;
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', [searchOptions]));
    customerList := TJSObject(xdcResponse.Result);

    // Load data into the dataset
    xdwdsCustomers.Close;
    xdwdsCustomers.SetJsonData(customerList['data']);
    xdwdsCustomers.Open;

    asm
      endSpinner();
    end;

    customerListLength := integer(customerList['count']);
    TotalPages := ( (customerListLength + PageSize - 1) div PageSize);

    if customerListLength = 0 then
    begin
      lblEntries.Caption := 'No entries found';
    end
    else if (PageNumber * PageSize) < customerListLength then
    begin
      lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
                            ' - ' + IntToStr(PageNumber * PageSize) +
                             ' of ' + IntToStr(customerListLength);
    end
    else if (PageNumber * PageSize) >= customerListLength then
    begin
       lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
                            ' - ' + IntToStr(customerListLength) +
                             ' of ' + IntToStr(customerListLength);
    end;

    // Optional: Continue using pagination if needed
    GeneratePagination(TotalPages);
  end;
end;

function TFViewCustomers.GenerateSearchOptions(): string;
// Generates searchOptions for GetOrders.
var
  searchOptions: string;
begin
  searchOptions :=  '&pagenumber=' + IntToStr(PageNumber) +
                    '&pagesize=' + IntToStr(PageSize);

  Result := searchOptions;
end;


procedure TFViewCustomers.HideNotification;
begin
  pnlMessage.ElementHandle.hidden := True;
  info := '';
end;


procedure TFViewCustomers.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 TFViewCustomers.GeneratePagination(TotalPages: Integer);
// Generates pagination for the table.
// TotalPages: Total amount of pages generated by the search
var
  PaginationElement, PageItem, PageLink: TJSHTMLElement;
  I, Start, Finish: Integer;
begin
  PaginationElement := TJSHTMLElement(document.getElementById('pagination'));
  PaginationElement.innerHTML := ''; // Clear existing pagination

  // Previous Button
  PageItem := TJSHTMLElement(document.createElement('li'));
  PageItem.className := 'page-item';
  if PageNumber = 1 then
    PageItem.classList.add('disabled');
  PageLink := TJSHTMLElement(document.createElement('a'));
  PageLink.className := 'page-link';
  PageLink.innerText := 'Previous';
  PageLink.setAttribute('href', 'javascript:void(0)');
  PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
  begin
    if PageNumber > 1 then
    begin
      Dec(PageNumber);
      GetCustomers(GenerateSearchOptions());
    end;
  end);
  PageItem.appendChild(PageLink);
  PaginationElement.appendChild(PageItem);

  // Page Numbers

  if TotalPages <= 7 then
  begin
    for I := 1  to 7 do
    begin
      if I <= TotalPages then
      begin
        PageItem := TJSHTMLElement(document.createElement('li'));
        PageItem.className := 'page-item';
        if I = PageNumber then
          PageItem.classList.add('selected-number'); // Add the selected-number class
        PageLink := TJSHTMLElement(document.createElement('a'));
        PageLink.className := 'page-link';
        PageLink.innerText := IntToStr(I);
        PageLink.setAttribute('href', 'javascript:void(0)');
        PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
        var
          PageNum: Integer;
        begin
          PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
          PageNumber := PageNum;
          GetCustomers(GenerateSearchOptions());
        end);
        PageItem.appendChild(PageLink);
        PaginationElement.appendChild(PageItem);
      end;
    end;
  end
  else
  begin
    if PageNumber <= 4 then
    // If page number is low enough no early elipsis needed
    Begin
      Start := 2;
      Finish := 5;
    End
    else if (PageNumber >= (TotalPages - 3)) then
    // If page number is high enough no late elipsis needed
    begin
      Start := TotalPages - 3;
      Finish := TotalPages - 1;
    end
    else
    begin
      Start := PageNumber - 1;
      Finish := PageNumber + 1;
    end;

    PageItem := TJSHTMLElement(document.createElement('li'));
    PageItem.className := 'page-item';
    if 1 = PageNumber then
      PageItem.classList.add('selected-number'); // Add the selected-number class
    PageLink := TJSHTMLElement(document.createElement('a'));
    PageLink.className := 'page-link';
    PageLink.innerText := '1';
    PageLink.setAttribute('href', 'javascript:void(0)');
    PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
    var
      PageNum: Integer;
    begin
      PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
      PageNumber := PageNum;
      GetCustomers(GenerateSearchOptions());
    end);
    PageItem.appendChild(PageLink);
    PaginationElement.appendChild(PageItem);

    // Adds Elipse to pagination if page number is too big
    if PageNumber > 4 then
    begin
      PageItem := TJSHTMLElement(document.createElement('li'));
      PageItem.className := 'page-item';
      PageItem.classList.add('disabled');
      PageLink := TJSHTMLElement(document.createElement('a'));
      PageLink.className := 'page-link';
      PageLink.innerText := '...';
      PageLink.setAttribute('href', 'javascript:void(0)');
      PageItem.appendChild(PageLink);
      PaginationElement.appendChild(PageItem);
    end;


    // Adds Page, page - 1, and page + 1 to pagination
    for I := Start  to Finish do
    begin
      if ( I > 1) and (I < TotalPages) then
      begin
        PageItem := TJSHTMLElement(document.createElement('li'));
        PageItem.className := 'page-item';
        if I = PageNumber then
          PageItem.classList.add('selected-number'); // Add the selected-number class
        PageLink := TJSHTMLElement(document.createElement('a'));
        PageLink.className := 'page-link';
        PageLink.innerText := IntToStr(I);
        PageLink.setAttribute('href', 'javascript:void(0)');
        PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
        var
          PageNum: Integer;
        begin
          PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
          PageNumber := PageNum;
          GetCustomers(GenerateSearchOptions());
        end);
        PageItem.appendChild(PageLink);
        PaginationElement.appendChild(PageItem);
      end;
    end;

    // adds ellipse if number is too small
    if PageNumber < TotalPages - 4 then
    begin
      PageItem := TJSHTMLElement(document.createElement('li'));
      PageItem.className := 'page-item';
      PageItem.classList.add('disabled');
      PageLink := TJSHTMLElement(document.createElement('a'));
      PageLink.className := 'page-link';
      PageLink.innerText := '...';
      PageLink.setAttribute('href', 'javascript:void(0)');
      PageItem.appendChild(PageLink);
      PaginationElement.appendChild(PageItem);
    end;

    if TotalPages <> 1 then
    begin
      PageItem := TJSHTMLElement(document.createElement('li'));
      PageItem.className := 'page-item';
      if TotalPages = PageNumber then
            PageItem.classList.add('selected-number');
      PageLink := TJSHTMLElement(document.createElement('a'));
      PageLink.className := 'page-link';
      PageLink.innerText := IntToStr(TotalPages);
      PageLink.setAttribute('href', 'javascript:void(0)');
      PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
      var
        PageNum: Integer;
      begin
        PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
        PageNumber := PageNum;
        GetCustomers(generateSearchOptions());
      end);
    end;
    PageItem.appendChild(PageLink);
    PaginationElement.appendChild(PageItem);
  end;

  // Next Button
  PageItem := TJSHTMLElement(document.createElement('li'));
  PageItem.className := 'page-item';
  if PageNumber = TotalPages then
    PageItem.classList.add('disabled');
  PageLink := TJSHTMLElement(document.createElement('a'));
  PageLink.className := 'page-link';
  PageLink.innerText := 'Next';
  PageLink.setAttribute('href', 'javascript:void(0)');
  PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
  begin
    if PageNumber < TotalPages then
    begin
      Inc(PageNumber);
      GetCustomers(GenerateSearchOptions());
    end;
  end);
  PageItem.appendChild(PageLink);
  PaginationElement.appendChild(PageItem);

end;


end.