datatables CRUD javascript functions ajax

 $(document).ready(function () {

  function initResellersTable() {

      const table = $('#resellers-table').DataTable({

          processing: true,

          serverSide: true,

          ajax: {

              url: '/api/resellers',

              type: 'GET',

              data: function (d) {

                  // Add any additional parameters to the request here

                  // console.log('Data sent to server:', d);

                  return $.extend({}, d, {

                      offset: d.start,

                      limit: d.length,

                      search: d.search,

                      sort: d.order && d.order.length > 0 ? {

                          [d.columns[d.order[0].column].data]: d.order[0].dir

                      } : undefined

                  });

              },

              dataSrc: function (json) {

                  // console.log('Data received from server:', json);

                  return json.data;

              }

          },

          columns: [

              {

                  data: 'name',

                  render: function (data) {

                  return `<span class="fw-bold">${data}</span>`;

              }

              },

              { data: 'companyName' },

              { data: 'email' },

              { data: 'phone' },

              {

                  data: 'status',

                  render: function (data, type, row) {

                      let badgeClass = data === 'active' ? 'badge badge-success-soft' : 'badge badge-danger-soft';

                      return `<span class="${badgeClass}">${data}</span>`;

                  }

              },

              {

                  data: null,

                  orderable: false,

                  render: function (data, type, row) {

                      return `

              <div>

              <div class="dropdown">

                  <a

                  class="btn btn-ghost btn-icon btn-sm rounded-circle"

                  href="#!"

                  role="button"

                  data-bs-toggle="dropdown"

                  aria-expanded="false"

                  >

                  <i class="bi bi-three-dots-vertical icon-xs"></i>

                  </a>

                  <div class="dropdown-menu">

                  <a class="dropdown-item d-flex align-items-center" href="#!" onclick="viewReseller(${row.id})">

                      <i class="bi bi-eye me-2 icon-xs"></i>View

                  </a>

                  <a class="dropdown-item d-flex align-items-center" href="#!" onclick="editReseller(${row.id})">

                      <i class="bi bi-pencil me-2 icon-xs"></i>Edit

                  </a>

                  <a class="dropdown-item d-flex align-items-center" href="#!" onclick="deleteReseller(${row.id}, '${row.name}')">

                      <i class="bi bi-trash me-2 icon-xs"></i>Delete

                  </a>

                  </div>

              </div>

              </div>`;

                  }

              }

          ],

          language: {

              search: '',

              searchPlaceholder: 'Search...'

          },

          order: [] // Remove default sorting

      });


      $('#resellers-table_filter input').removeClass().addClass('form-control');

      $('#resellers-table_length select').removeClass().addClass('form-select');

  }


  if ($.fn.dataTable) {

      initResellersTable();

  } else {

      console.error('DataTables is not defined');

  }

});


function createReseller() {


  const formContent = `

<div class="row">

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

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-person"></i></span>

    <input type="text" class="form-control" id="create-name" name="name" placeholder="Name">

    <div class="invalid-feedback" id="error-create-name"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-envelope"></i></span>

    <input type="email" class="form-control" id="create-email" name="email" placeholder="Email">

    <div class="invalid-feedback" id="error-create-email"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-lock"></i></span>

    <input type="password" class="form-control" id="create-password" name="password" placeholder="Password">

    <div class="invalid-feedback" id="error-create-password"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-lock-fill"></i></span>

    <input type="password" class="form-control" id="create-confirmPassword" name="confirmPassword" placeholder="Confirm Password">

    <div class="invalid-feedback" id="error-create-confirmPassword"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-card-text"></i></span>

    <input type="text" class="form-control" id="create-nib" name="nib" placeholder="NIB">

    <div class="invalid-feedback" id="error-create-nib"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-credit-card"></i></span>

    <input type="text" class="form-control" id="create-npwp" name="npwp" placeholder="NPWP">

    <div class="invalid-feedback" id="error-create-npwp"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-building"></i></span>

    <input type="text" class="form-control" id="create-companyName" name="companyName" placeholder="Company">

    <div class="invalid-feedback" id="error-create-companyName"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-geo-alt"></i></span>

    <input type="text" class="form-control" id="create-address" name="address" placeholder="Address">

    <div class="invalid-feedback" id="error-create-address"></div>

  </div>

</div>

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

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-map"></i></span>

    <input type="text" class="form-control" id="create-province" name="province" placeholder="Province">

    <div class="invalid-feedback" id="error-create-province"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-map"></i></span>

    <input type="text" class="form-control" id="create-city" name="city" placeholder="City">

    <div class="invalid-feedback" id="error-create-city"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-map"></i></span>

    <input type="text" class="form-control" id="create-zipCode" name="zipCode" placeholder="Zip Code">

    <div class="invalid-feedback" id="error-create-zipCode"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-telephone"></i></span>

    <input type="text" class="form-control" id="create-phone" name="phone" placeholder="Phone">

    <div class="invalid-feedback" id="error-create-phone"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-compass"></i></span>

    <input type="text" class="form-control" id="create-latitude" name="latitude" placeholder="Latitude">

    <div class="invalid-feedback" id="error-create-latitude"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-compass"></i></span>

    <input type="text" class="form-control" id="create-longitude" name="longitude" placeholder="Longitude">

    <div class="invalid-feedback" id="error-create-longitude"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-toggle-on"></i></span>

    <select class="form-select" id="create-status" name="status">

      <option value="active">Active</option>

      <option value="inActive">Inactive</option>

    </select>

    <div class="invalid-feedback" id="error-create-status"></div>

  </div>

  <div class="mb-3 input-group">

    <span class="input-group-text"><i class="bi bi-receipt"></i></span>

    <select class="form-select" id="create-invoiceGenerationMethod" name="invoiceGenerationMethod">

    <option value="automatic">Automatic</option>

      <option value="manual">Manual</option>

    </select>

    <div class="invalid-feedback" id="error-create-invoiceGenerationMethod"></div>

  </div>

</div>

</div>

`;


  // Set form content to modal

  $('#createResellerForm').html(formContent);


  // Show the modal

  $('#createModal').modal('show');


  $('#createResellerForm').off('submit').on('submit', function (event) {

      event.preventDefault();


      $('#createResellerForm .is-invalid').removeClass('is-invalid');

      $('#createResellerForm .invalid-feedback').text('');


      // loading button

      const $submitButton = $('#createModal .btn-primary');

      const originalButtonText = $submitButton.html();

      $submitButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...');

      $submitButton.prop('disabled', true);


      const formData = $(this).serialize();


      $.ajax({

          url: '/api/resellers',

          type: 'POST',

          data: formData,

          success: function (response) {

              $('#createModal').modal('hide');

              $('#resellers-table').DataTable().ajax.reload();

              showToast('success', 'Reseller created successfully');

          },

          error: function (error) {

              console.error('AJAX error:', error);

              const errors = error.responseJSON.message;

              if (Array.isArray(errors)) {

                  errors.forEach(err => {

                      $(`#error-create-${err.path}`).text(err.msg);

                      $(`#create-${err.path}`).addClass('is-invalid');

                  });

              } else {

                  showToast('danger', 'Failed to create reseller');

              }

          },

          complete: function () {

              $submitButton.html(originalButtonText);

              $submitButton.prop('disabled', false);

          }

      });

  });

}


function viewReseller(id) {

  $('#viewModal').modal('show');

  $.ajax({

      url: `/api/resellers/${id}`,

      type: 'GET',

      success: function (response) {

          // console.log('AJAX success:', response);

          const data = response.data;

          $('#view-name').text(data.name);

          $('#view-email').text(data.email);

          $('#view-phone').text(data.phone);

          $('#view-companyName').text(data.companyName);

          $('#view-status').text(data.status);

          $('#view-nib').text(data.nib);

          $('#view-npwp').text(data.npwp);

          $('#view-address').text(data.address);

          $('#view-province').text(data.province);

          $('#view-city').text(data.city);

          $('#view-zipCode').text(data.zipCode);

          $('#view-invoiceGenerationMethod').text(data.invoiceGenerationMethod);

          $('#view-latitude').text(data.latitude);

          $('#view-longitude').text(data.longitude);

          $('#view-createdAt').text(new Date(data.createdAt).toLocaleString());

          $('#view-updatedAt').text(new Date(data.updatedAt).toLocaleString());

      },

      error: function (error) {

          $('#viewModalContent').html('<p>Error fetching details</p>');

      }

  });

}


let originalData = {};

function editReseller(id) {

$.ajax({

  url: `/api/resellers/${id}`,

  type: 'GET',

  success: function (response) {

    const data = response.data;

    originalData = data;

    const formContent = `

      <div class="row">

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

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-person"></i></span>

            <input type="text" class="form-control" id="edit-name" name="name" value="${data.name}" placeholder="Name" required>

            <div class="invalid-feedback" id="error-edit-name"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-card-text"></i></span>

            <input type="text" class="form-control" id="edit-nib" name="nib" value="${data.nib}" placeholder="NIB" required>

            <div class="invalid-feedback" id="error-edit-nib"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-credit-card"></i></span>

            <input type="text" class="form-control" id="edit-npwp" name="npwp" value="${data.npwp}" placeholder="NPWP" required>

            <div class="invalid-feedback" id="error-edit-npwp"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-building"></i></span>

            <input type="text" class="form-control" id="edit-companyName" name="companyName" value="${data.companyName}" placeholder="Company" required>

            <div class="invalid-feedback" id="error-edit-companyName"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-geo-alt"></i></span>

            <input type="text" class="form-control" id="edit-address" name="address" value="${data.address}" placeholder="Address" required>

            <div class="invalid-feedback" id="error-edit-address"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-map"></i></span>

            <input type="text" class="form-control" id="edit-province" name="province" value="${data.province}" placeholder="Province" required>

            <div class="invalid-feedback" id="error-edit-province"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-map"></i></span>

            <input type="text" class="form-control" id="edit-city" name="city" value="${data.city}" placeholder="City" required>

            <div class="invalid-feedback" id="error-edit-city"></div>

          </div>

        </div>

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

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-map"></i></span>

            <input type="text" class="form-control" id="edit-zipCode" name="zipCode" value="${data.zipCode}" placeholder="Zip Code" required>

            <div class="invalid-feedback" id="error-edit-zipCode"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-telephone"></i></span>

            <input type="text" class="form-control" id="edit-phone" name="phone" value="${data.phone}" placeholder="Phone" required>

            <div class="invalid-feedback" id="error-edit-phone"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-compass"></i></span>

            <input type="text" class="form-control" id="edit-latitude" name="latitude" value="${data.latitude}" placeholder="Latitude" required>

            <div class="invalid-feedback" id="error-edit-latitude"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-compass"></i></span>

            <input type="text" class="form-control" id="edit-longitude" name="longitude" value="${data.longitude}" placeholder="Longitude" required>

            <div class="invalid-feedback" id="error-edit-longitude"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-toggle-on"></i></span>

            <select class="form-select" id="edit-status" name="status" required>

              <option value="active" ${data.status === 'active' ? 'selected' : ''}>Active</option>

              <option value="inActive" ${data.status === 'inActive' ? 'selected' : ''}>Inactive</option>

            </select>

            <div class="invalid-feedback" id="error-edit-status"></div>

          </div>

          <div class="mb-3 input-group">

            <span class="input-group-text"><i class="bi bi-receipt"></i></span>

            <select class="form-select" id="edit-invoiceGenerationMethod" name="invoiceGenerationMethod" required>

              <option value="manual" ${data.invoiceGenerationMethod === 'manual' ? 'selected' : ''}>Manual</option>

              <option value="automatic" ${data.invoiceGenerationMethod === 'automatic' ? 'selected' : ''}>Automatic</option>

            </select>

            <div class="invalid-feedback" id="error-edit-invoiceGenerationMethod"></div>

          </div>

        </div>

      </div>

      `;


    // Set form content to modal

    $('#editResellerForm').html(formContent);

    // Show the modal

    $('#editModal').modal('show');

  },

  error: function (error) {

    console.error('AJAX error:', error);

    alert('Failed to fetch reseller details');

  }

});


$('#editResellerForm').off('submit').on('submit', function (event) {

  event.preventDefault();


  const formData = $(this).serializeArray();

  const updatedData = {};


  // Compare current form values with original data and add only changed values to updatedData

  formData.forEach(({ name, value }) => {

    if (originalData[name] != value) {

      updatedData[name] = value;

    }

  });


  // no change message

  if (Object.keys(updatedData).length === 0) {

    showToast('info', 'No changes detected.');

    $('#editModal').modal('hide');

    return;

  }


  // loading button

  const $submitButton = $('#editModal .btn-primary');

  const originalButtonText = $submitButton.html();

  $submitButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...');

  $submitButton.prop('disabled', true);


  // process edit data

  $.ajax({

    url: `/api/resellers/${id}`,

    type: 'PUT',

    data: updatedData,

    success: function (response) {

      $('#editModal').modal('hide');

      $('#resellers-table').DataTable().ajax.reload(null, false);

      showToast('success', response.message);

    },

    error: function (error) {

      console.error('AJAX error:', error);

      $('#editModal').modal('hide');

      showToast('danger', error.responseJSON.message);

    },

    complete: function () {

      $submitButton.html(originalButtonText);

      $submitButton.prop('disabled', false);

    }

  });

});

}


function deleteReseller(id, name) {

  $('#deleteResellerName').text(name);

  $('#deleteModal').modal('show');

  $('#confirmDelete').off('click').on('click', function () {


      // loading button

      const $submitButton = $('#deleteModal .btn-danger');

      const originalButtonText = $submitButton.html();

      $submitButton.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Loading...');

      $submitButton.prop('disabled', true);


      $.ajax({

          url: `/api/resellers/${id}`,

          type: 'DELETE',

          success: function (response) {

              // console.log('AJAX success:', response);

              $('#resellers-table').DataTable().ajax.reload(null, false);

              showToast('success', response.message);

          },

          error: function (error) {

              console.error('AJAX error:', error);

              $('#deleteModal').modal('hide');

              showToast('danger', error.responseJSON.message);

          },

          complete: function () {

              $submitButton.html(originalButtonText);

              $submitButton.prop('disabled', false);

          }

      });


      // console.log(`Deleting reseller ${id}`);

      $('#deleteModal').modal('hide');

  });

}