frontend/orders/modal-products/modal-products-component.js

/** clase modal de productos */
class ModalProductsComponent {

	constructor() {
    this.modalProducts = ordersForm.footer.querySelector('#modal-products');
    this.tbody = this.modalProducts.querySelector('#tbody-products');
    this.pagination = this.modalProducts.querySelector('#pagination-products');
    this.submitButton = this.modalProducts.querySelector('#submit-button');
    this.searchBar = this.modalProducts.querySelector('search-bar-component');

		/**
		 * Listado de productos
		 * @type {Array<Product>}
		*/
		this.products = [];

		/**
		 * Listado de productos seleccionados
		 * @type {Array<Porduct>}
		 */
		this.productsSelected = [];

		/** @type {number} */
    this.page = 1;

		this.modalProductsInstance = new Modal( this.modalProducts, { backdrop: 'static' });

		this.setEvents();
  }

	/** establece el html y eventos del modal */
  setEvents() {

    this.modalProducts.addEventListener('shown.bs.modal', () => {
      this.submitButton.setAttribute('disabled', '');
    });

    this.modalProducts.addEventListener('hide.bs.modal', () => {
      this.productsSelected = [];
    });

    this.pagination.addEventListener('pagination', ( $event ) => {
      this.page = $event.detail.page;
      this.openModalProducts( $event.detail.value );
    });

    this.searchBar.addEventListener('search', ( $event ) => {
      this.searchProduct( $event.detail.value );
    });
  }

  /**
   * despliuega el modal de productos
   * @param  {Array<number>} pagination paginacion de la tabla
   */
  async openModalProducts( pagination = [0, 10] ) {

    try {

      this.products = await ProductosController.listarProductosActivos( pagination );

      // console.log( this.products );

      let totalProducts = await ProductosController.obtenerTotalProductosActivos();

      setPaginationStorage('productsModalTable', { pagination });

      this.renderProducts( totalProducts.totalPaginas, totalProducts.totalRegistros );


      if ( !this.modalProductsInstance._isShown ) {
        this.modalProductsInstance.show();
      }


    } catch ( error ) {
      console.error( error );

    }
  }

  /**
   * renderiza la tabla de productos dentro del modal
   *
   * @param  {number} totalPages numero de paginas
   * @param  {number} totalRegisters numero de registros
   * @param  {boolean} search flag que indica si actualizar el paginador
   */
  renderProducts( totalPages = 0, totalRegisters = 0, search = false ) {

    if ( !search ) {

      this.tbody.innerHTML = '';
      this.pagination._limit = totalPages;
      this.pagination._registers = totalRegisters;
      this.pagination._page = this.page;
    }

    if ( this.products.length > 0 ) {

      showElement( this.pagination );

      this.tbody.innerHTML = this.products.map(( product ) => (`
       <tr class="text-center point" onclick="product_${ product.productoid }.click();">
         <td name="productoid">${ product.productoid }</td>
         <td name="nombre_producto">${ product.nombre }</td>
         <td name="nombre_categoria">${ product.nombre_categoria }</td>
         <td name="quantity">${ product.cantidad }</td>
         <td name="price">${ product.precio ? product.precio : 0 }$</td>
         <td>
          <input
            type="checkbox"
            class="form-check-input point"
            id="product_${ product.productoid }"
            name="product_action"
           	${ this.checkProduct( product ) ? 'checked' : '' }
          />
         </td>
       </tr>
      `)).join('');

      for ( const input of this.tbody.querySelectorAll('input[type="checkbox"]') ) {
        
        input.addEventListener('change', this.handleChange.bind( this ) );
        
        // se crea este listener para dar solucion a la propagacion del evento onclick
        // del input al tr.
        input.addEventListener('click', event => event.stopPropagation() );
      }

   } else {
      hideElement( this.pagination );

      this.tbody.innerHTML = (`
        <tr class="text-center">
         <td colspan="6" class="text-danger">No existen productos disponibles</td>
       </tr>
     `);

    }
  }

	/**
	 * Funcion que maneja la seleccion del producto
	 * @param {*} $event evento change
	*/
  handleChange( $event ) {

    const rowElement = $event.target.parentNode.parentNode;
    const id_product = +rowElement.querySelector('td[name="productoid"]').innerText;

    if ( $event.target.checked ) {

    	let index = this.productsSelected.findIndex(( product ) => product.productoid === id_product );

    	// console.log({ id_product, index });

    	if ( index === -1 ) {

    		let product = this.products.find(( product ) => product.productoid === id_product );
        product = { 
          ...product, 
          precio: product.precio || 0, 
          cantidad_seleccionada: 1 
        };

    		this.productsSelected.push( product );
    	}

    } else {

    	this.productsSelected = this.productsSelected.filter(
    		( product ) => product.productoid !== id_product
    	);

    }

    // activa el boton si el usuario selecciona un producto

    if ( this.productsSelected.length > 0 ) {
      this.submitButton.removeAttribute('disabled');

    } else {
    	this.submitButton.setAttribute('disabled', '');

    }
  }

  /**
   * buscar productos en la BD.
   * @param  {string} search cadena de busqueda
   */
  async searchProduct( search ) {

    const rexp = /^[\w-\d\s]+$/;

    if ( search.length === 0 ) {

      let { pagination } = JSON.parse( sessionStorage.getItem('productsModalTable') );

      return this.openModalProducts( pagination );
    }

    if ( !rexp.test( search ) ) {
      console.log('no concuerda con expresion regular');
      return;

    }

    // search es la busqueda
    this.products = await ProductosController.buscarProducto({ search: '%' + search + '%' });

    this.renderProducts( null, null, true );
  }

	/** cierra el modal de productos */
  closeModalProducts() {

    ordersForm.productsSelected = this.productsSelected;

    this.modalProductsInstance.hide();

    console.log( ordersForm.productsSelected );


    // mandar al formulario de orden
    ordersForm.setProductsTable();
  }

  /**
   * chequea si el producto esta marcado en la orden
   *
   * @param  {Product} product instancia del producto
   * @return {boolean} resultado de la verificacion de la existencia del producto.
	 * Devuelve true si lo encuentra
   */
  checkProduct( product ) {

  	// retorna cuales son los elementos seleccionados y los marca en la lista

  	return this.productsSelected.findIndex(
      productSelect => productSelect.productoid === product.productoid
    ) !== -1;
  }
}

module.exports = {
	ModalProductsComponent
}