segunolalive/helloBooks

View on GitHub
client/components/Dashboard/PdfViewer.jsx

Summary

Maintainability
A
0 mins
Test Coverage
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import PDF from 'react-pdf-js';
import { Redirect } from 'react-router-dom';

import Header from '../Header';
import LoginRedirect from '../auth/LoginRedirect';
import Loading from '../common/Loading';
import Notify from '../../actions/Notify';

/**
 * custom pdf viewer
 *
 * @export
 *
 * @class PdfViewer
 *
 * @extends {Component}
 */
export class PdfViewer extends Component {
  state = {};
  /**
   * method called when pdf file is completely fetched
   *
   * @param  {integer} pages   total number of pages in file
   *
   * @return {undefined}       sets state
   */
  onDocumentComplete = (pages) => {
    this.setState({ page: 1, pages });
  }

  /**
   * method called when page is loaded
   *
   * @param  {integer} page   current page
   *
   * @return {undefined}       sets state
   */
  onPageComplete = (page) => {
    this.setState({ page });
  }

  /**
   * document error handler
   *
   * @param {Object}  error
   *
   * @return {JSX}          react-router-dom rea=direct component
   */
  onDocumentError = () => {
    Notify.error('An error occured while fetching book. Try again later');
    this.setState(() => ({ fileError: true }));
  }

  /**
   * navigates to previous page
   *
   * @memberof PdfViewer
   *
   * @return {undefined}       sets state
   */
  handlePrevious = () => {
    this.setState({ page: this.state.page - 1 });
  }

  /**
   * navigates to next page
   *
   * @memberof PdfViewer
   *
   * @return {undefined}       sets state
   */
  handleNext = () => {
    this.setState({ page: this.state.page + 1 });
  }

  /**
   * navigates to specific page
   *
   * @memberof PdfViewer
   *
   * @param {Object} event
   *
   * @return {undefined}       sets state
   */
  setPage = (event) => {
    const entry = Number(event.target.value);
    let currentPage = entry < 1 ? 1 : entry;
    currentPage = entry > this.state.pages ? this.state.pages : entry;
    this.setState({ page: currentPage });
  }

  /**
   * @param {integer}  page
   *
   * @param {integer}  pages
   *
   * @return {JSX}     JSX representation of page navigation
   *
   * @memberof PdfViewer
   */
  renderPagination = (page, pages) => {
    const previousButton = <button
      className="col s5 prev-btn"
      disabled={page === 1}
      onClick={this.handlePrevious}
    >
      <a href="#">
        <span>{page > 1 && 'Previous'}</span>
      </a>
    </button>;
    const nextButton = <button
      className="col s5 next-btn"
      disabled={page === pages}
      onClick={this.handleNext}
    >
      <a href="#">
        <span>{page < pages && 'Next'}</span>
      </a>
    </button>;
    const pageEntry = <div className="col s2 center">
      <input
        className="page-num center"
        type="number"
        value={this.state.page}
        onChange={this.setPage}
        min={1}
        max={this.state.pages}
      />
    </div>;
    return (
      <nav className="center black pdf-nav row">
        <ul className="container">
          {previousButton}
          {pageEntry}
          {nextButton}
        </ul>
      </nav>
    );
  }

  renderPdf = () => {
    const loader = <div className="row">
      <div className="col m6 offset-m3">
        <Loading text='loading pdf . . .' />
      </div>
    </div>;
    const pagination = (this.state.pages) ?
      this.renderPagination(this.state.page, this.state.pages) :
      null;
    return (
      this.props.isLoggedIn ?
        <div>
          <Header />
          {!this.props.bookUrl &&
            <div className="center">
              <h6>Your book was not found. Enjoy our all time favourite</h6>
            </div>}
          <div className="pdf-container">
            <PDF
              file={this.props.bookUrl || BOOK_FALLBACK}
              fillWidth
              loading={loader}
              onDocumentComplete={this.onDocumentComplete}
              onPageComplete={this.onPageComplete}
              page={this.state.page}
              onDocumentError={this.onDocumentError}
            />
            {pagination}
          </div>
        </div> : <LoginRedirect />
    );
  }

  /**
   * renders component to DOM
   *
   * @returns {JSX} JSX representation of component
   *
   * @memberof PdfViewer
   */
  render() {
    return this.state.fileError ?
      <Redirect to="/dashboard" /> :
      this.renderPdf();
  }
}


PdfViewer.propTypes = {
  bookUrl: PropTypes.string.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
};

const mapDispatchToProps = ({ authReducer, bookReducer }) => ({
  bookUrl: bookReducer.bookToRead,
  isLoggedIn: authReducer.isLoggedIn,
});

export default connect(mapDispatchToProps)(PdfViewer);