Pagination.tsx 3.52 KB
Newer Older
Matija Obreza's avatar
Matija Obreza committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React from 'react';
import FilteredPage, { IPageRequest } from '@genesys/client/model/FilteredPage';
import { history } from './App';

interface IPagination extends React.ClassAttributes<any> {
  loadData: (filter: Record<string, any>, pageR: IPageRequest) => Promise<any>;
  paged: FilteredPage<any>;
  children: React.ReactNode;
}

export default class Pagination extends React.Component<IPagination, any> {
  public componentDidMount() {
    const { paged } = this.props;
    if (paged) {
      this.updateRoute(paged);
    }
  }

  public componentDidUpdate(prevProps: IPagination) {
    const { paged } = this.props;
    if ((paged && !prevProps.paged && paged.filterCode) || paged.filterCode !== prevProps.paged.filterCode) {
      this.updateRoute(paged);
    }
  }

  private toPage = (e: React.MouseEvent) => {
    const { loadData, paged } = this.props;
    const page = +(e.currentTarget as HTMLElement).dataset.page;

    loadData(paged.filter, this.makePageRequest(page))
      .then((data: FilteredPage<any>) => {
        this.updateRoute(data);
      });
  };

  private updateRoute = (page: FilteredPage<any>) => {
    // console.log('updateRoute', page);
    history.push(`/?filter=${page.filterCode}&p=${page.number}`);
  };

  private makePageRequest = (page: number): IPageRequest => {
    const { paged } = this.props;

    return { ...FilteredPage.nextPage(paged), ...{ page } };
  };

  private getPageNumbers = (): number[] => {
    const { paged: { number: current, totalPages, last } } = this.props;
    let base = [-2, -1, 0, 1, 2];

    if (totalPages < 5) {
      switch (totalPages) {
        case 4: {
          base.unshift();
          break;
        }
        case 3: {
          base = base.slice(1, 4);
          break;
        }
        case 2: {
          base = base.slice(2, 4);
          break;
        }
        default: {
          base = [0];
        }
      }
    }

    if (current === 0 || current === 1) {
      return base.map((page, i) => i + 1);
    }
    if (last || current === totalPages - 2) {
      return base.map((page, i) => current + page + (last ? -1 : 0));
    }
    return base.map((page) => current + page + 1);
  };

  private renderPagination = () => {
    const { paged } = this.props;
    const currentPageStyle = { fontWeight: 500, border: 0 };

    return (
      <div style={ { display: 'flex' } }>
        <button style={ { border: 0 } } onClick={ this.toPage } data-page={ 0 } disabled={ paged.number === 0 }>
          { '<< First' }
        </button>
        <button style={ { border: 0 } } onClick={ this.toPage } data-page={ paged.number - 1 } disabled={ paged.number === 0 }>
          { '< Prev' }
        </button>
        { this.getPageNumbers().map((page, i) => (
          <button
            key={ `page-${page}-${i}` }
            style={ paged.number === page - 1 ? currentPageStyle : { border: 0 } }
            disabled={ paged.number === page - 1 }
            onClick={ this.toPage }
            data-page={ page - 1 }
          >
            { page }
          </button>
        )) }
        <button style={ { border: 0 } } onClick={ this.toPage } data-page={ paged.number + 1 } disabled={ paged.last }>
          { 'Next >' }
        </button>
        <button style={ { border: 0 } } onClick={ this.toPage } data-page={ paged.totalPages - 1 } disabled={ paged.last }>
          { 'Last >>' }
        </button>
      </div>
    );
  }

  public render() {
    return (
      <>
        { this.renderPagination() }
        { this.props.children }
        { this.renderPagination() }
      </>
    );
  };
}