grid.js CRUD expressJS ejs template engine


const apiUrl = '<%= apiUrl %>/resellers';

const token = '<%= token %>';

let grid;


function refreshGrid() {

  fetch(apiUrl, {

    headers: {

      'Authorization': `Bearer ${token}`,

      'Content-Type': 'application/json'

    }

  })

  .then(response => response.json())

  .then(data => {

    grid.updateConfig({

      data: data.data.map(item => [

        item.name,

        item.province,

        item.city,

        item.phone,

        item.status,

        item

      ]),

      total: data.total

    }).forceRender();

  })

  .catch(error => {

    console.error('Error refreshing grid:', error);

  });

}


grid = new gridjs.Grid({

  columns: [

    "Name", 

    "Province", 

    "City", 

    "Phone", 

    {

      name: "Status",

      sort: false,

      formatter: (cell) => {

        const className = cell === 'active' ? 'badge badge-outline-success' : 'badge badge-outline-danger';

        return gridjs.html(`<span class="${className}">${cell}</span>`);

      }

    },

    {

      name: "Action",

      sort: false,

      formatter: (cell, row) => {

        const rowData = JSON.stringify(cell);

        return gridjs.html(`

          <div class="dropdown text-center">

            <button class="btn btn-sm btn-outline-primary dropdown-toggle" type="button" id="dropdownMenuSizeButton3" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Action </button>

            <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">

              <li><a class="dropdown-item" href="#" onclick='showEditModal(${rowData})'><i class="fa fa-edit"></i> Edit</a></li>

              <li><a class="dropdown-item" href="#" onclick='showDeleteModal(${rowData})'><i class="fa fa-trash"></i> Delete</a></li>

              <li><a class="dropdown-item" href="#" onclick='showDetailModal(${cell.id})'><i class="fa fa-info-circle"></i> Details</a></li>

            </ul>

          </div>

        `);

      }

    }

  ],

  server: {

    url: apiUrl,

    headers: {

      'Authorization': `Bearer ${token}`,

      'Content-Type': 'application/json'

    },

    then: data => data.data.map(item => [

      item.name,

      item.province,

      item.city,

      item.phone,

      item.status,

      item

    ]),

    total: data => data.total

  },

  pagination: {

    limit: 10,

    server: {

      url: (prev, page, limit) => {

        const url = new URL(prev);

        url.searchParams.set('limit', limit);

        url.searchParams.set('offset', page * limit);

        return url.toString();

      }

    }

  },

  search: {

    server: {

      url: (prev, keyword) => {

        const url = new URL(prev);

        url.searchParams.set('search', keyword);

        return url.toString();

      }

    }

  },

  sort: {

    multiColumn: true,

    server: {

      url: (prev, columns) => {

        const url = new URL(prev);

        columns.forEach(col => {

          const columnName = ['name', 'province', 'city', 'phone', 'status'][col.index];

          const direction = col.direction === 1 ? 'asc' : 'desc';

          url.searchParams.set(`sort[${columnName}]`, direction);

        });

        return url.toString();

      }

    }

  },


  className: {

  table: 'table'

}



});


grid.render(document.getElementById("gridjs"));


function showDeleteModal(data) {

  // Fill the modal with relevant information

  document.getElementById('deleteModalLabel').innerText = `Delete Record: ${data.name}`;

  document.getElementById('confirmDeleteBtn').setAttribute('onclick', `deleteRecord(${data.id})`);

  // Show the modal

  new bootstrap.Modal(document.getElementById('deleteModal')).show();

}


function deleteRecord(id) {

const apiUrl = `<%= apiUrl %>/resellers/${id}`; // Pastikan ini benar

const token = '<%= token %>'; // Pastikan ini benar

fetch(apiUrl, {

  method: 'DELETE',

  headers: {

    'Authorization': `Bearer ${token}`,

    'Content-Type': 'application/json'

  }

})

.then(response => {

  if (!response.ok) {

    throw new Error('Network response was not ok ' + response.statusText);

  }

  return response.json();

})

.then(data => {

  console.log('Record deleted successfully:', data);

  

  // Menyisipkan pesan sukses ke dalam elemen HTML

  let successMessageElement = document.getElementById('successMessage');

  successMessageElement.textContent = 'Record deleted successfully!';

  

  // Show success toast

  let successToast = new bootstrap.Toast(document.getElementById('successToast'));

  successToast.show();

  

  // Close modal

  let modal = document.getElementById('deleteModal');

  let modalBootstrap = bootstrap.Modal.getInstance(modal);

  modalBootstrap.hide();


  refreshGrid();

})

.catch(error => {

  console.error('There was a problem with the fetch operation:', error);

  

  // Menyisipkan pesan error ke dalam elemen HTML

  let errorMessageElement = document.getElementById('errorMessage');

  errorMessageElement.textContent = 'Error: ' + error.message;

  

  // Show error toast

  let errorToast = new bootstrap.Toast(document.getElementById('errorToast'));

  errorToast.show();

});


}


function showDetailModal(id) {

  fetchDetails(id);

}


function fetchDetails(id) {

  const apiUrl = `<%= apiUrl %>/resellers/${id}`;

  const token = '<%= token %>';


  fetch(apiUrl, {

    method: 'GET',

    headers: {

      'Authorization': `Bearer ${token}`,

      'Content-Type': 'application/json'

    }

  })

  .then(response => {

    if (!response.ok) {

      throw new Error('Network response was not ok ' + response.statusText);

    }

    return response.json();

  })

  .then(data => {

    const userDetails = data.data;

    document.getElementById('detailModalLabel').innerText = `Details Reseller`;

    document.getElementById('detailContent').innerHTML = `


            <div class="row">

              <div class="col-md-6">

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-account-outline"></i> Name:</label>

                  <div>${userDetails.name}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-card-account-details-outline"></i> NIB:</label>

                  <div>${userDetails.nib}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-card-account-details-outline"></i> NPWP:</label>

                  <div>${userDetails.npwp}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-domain"></i> Company:</label>

                  <div>${userDetails.companyName}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-map-marker"></i> Latitude:</label>

                  <div>${userDetails.latitude}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-map-marker"></i> Longitude:</label>

                  <div>${userDetails.longitude}</div>

                </div>


                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-phone"></i> Phone:</label>

                  <div>${userDetails.phone}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-map-marker"></i> Address:</label>

                  <div>${userDetails.address}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-map-marker"></i> Province:</label>

                  <div>${userDetails.province}</div>

                </div>

                              </div>

              <div class="col-md-6">

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-map-marker"></i> City:</label>

                  <div>${userDetails.city}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-map-marker"></i> Zip Code:</label>

                  <div>${userDetails.zipCode}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-account-check"></i> Status:</label>

                  <div>${userDetails.status}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-receipt"></i> Invoice Method:</label>

                  <div>${userDetails.invoiceGenerationMethod}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-email"></i> Email:</label>

                  <div>${userDetails.email}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-account-star"></i> Role:</label>

                  <div>${userDetails.role}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-clock"></i> Created At:</label>

                  <div>${userDetails.createdAt}</div>

                </div>

                <div class="mb-3 d-flex align-items-start">

                  <label class="form-label me-2"><i class="mdi mdi-history"></i> Updated At:</label>

                  <div>${userDetails.updatedAt}</div>

                </div>

              </div>



    `;

    new bootstrap.Modal(document.getElementById('detailModal')).show();

  })

  .catch(error => {

    console.error('There was a problem with the fetch operation:', error);

  });

}


function showEditModal(data) {

  const rowData = data;

  document.getElementById('editModalLabel').innerText = `Edit Record ${rowData.name}`;

  document.getElementById('editId').value = rowData.id;

  document.getElementById('editName').value = rowData.name;

  document.getElementById('editNIB').value = rowData.nib;

  document.getElementById('editNPWP').value = rowData.npwp;

  document.getElementById('editCompanyName').value = rowData.companyName;

  document.getElementById('editLatitude').value = rowData.latitude;

  document.getElementById('editLongitude').value = rowData.longitude;

  document.getElementById('editPhone').value = rowData.phone;

  document.getElementById('editAddress').value = rowData.address;

  document.getElementById('editProvince').value = rowData.province;

  document.getElementById('editCity').value = rowData.city;

  document.getElementById('editZipCode').value = rowData.zipCode;

  document.getElementById('editStatus').value = rowData.status;

  document.getElementById('editInvoiceGenerationMethod').value = rowData.invoiceGenerationMethod;

  document.getElementById('editEmail').value = rowData.email;


  // Mengatur event listener untuk saveChangesBtn

  document.getElementById('saveChangesBtn').addEventListener('click', updateRecord);


  // Menampilkan modal

  new bootstrap.Modal(document.getElementById('editModal')).show();

}


function updateRecord() {

  const id = document.getElementById('editId').value;

  const data = {

    name: document.getElementById('editName').value,

    nib: document.getElementById('editNIB').value,

    npwp: document.getElementById('editNPWP').value,

    companyName: document.getElementById('editCompanyName').value,

    latitude: document.getElementById('editLatitude').value,

    longitude: document.getElementById('editLongitude').value,

    phone: document.getElementById('editPhone').value,

    address: document.getElementById('editAddress').value,

    province: document.getElementById('editProvince').value,

    city: document.getElementById('editCity').value,

    zipCode: document.getElementById('editZipCode').value,

    status: document.getElementById('editStatus').value,

    invoiceGenerationMethod: document.getElementById('editInvoiceGenerationMethod').value,

    email: document.getElementById('editEmail').value

  };


  const apiUrl = `<%= apiUrl %>/resellers/${id}`; // Pastikan ini benar

  const token = '<%= token %>'; // Pastikan ini benar


  fetch(apiUrl, {

    method: 'PUT',

    headers: {

      'Authorization': `Bearer ${token}`,

      'Content-Type': 'application/json'

    },

    body: JSON.stringify(data)

  })

  .then(response => {

    if (!response.ok) {

      throw new Error('Network response was not ok ' + response.statusText);

    }

    return response.json();

  })

  .then(data => {

    console.log('Record updated successfully:', data);

    

    // Menyisipkan pesan sukses ke dalam elemen HTML

    let successMessageElement = document.getElementById('successMessage');

    successMessageElement.textContent = 'Record updated successfully!';

    

    // Show success toast

    let successToast = new bootstrap.Toast(document.getElementById('successToast'));

    successToast.show();

    

    // Close modal

    let modal = document.getElementById('editModal');

    let modalBootstrap = bootstrap.Modal.getInstance(modal);

    modalBootstrap.hide();

    

    refreshGrid();

})

.catch(error => {

    console.error('There was a problem with the fetch operation:', error);

    

    // Menyisipkan pesan error ke dalam elemen HTML

    let errorMessageElement = document.getElementById('errorMessage');

    errorMessageElement.textContent = 'Error: ' + error.message;

    

    // Show error toast

    let errorToast = new bootstrap.Toast(document.getElementById('errorToast'));

    errorToast.show();

});


}