264 lines
10 KiB
JavaScript
264 lines
10 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
// --- Constants ---
|
|
const API_BASE = 'api/';
|
|
const addAssetForm = document.getElementById('addAssetForm');
|
|
const editAssetForm = document.getElementById('editAssetForm');
|
|
const assetsTableBody = document.getElementById('assets-table-body');
|
|
const loadingIndicator = document.getElementById('loading-indicator');
|
|
const notificationToastEl = document.getElementById('notificationToast');
|
|
const notificationToast = new bootstrap.Toast(notificationToastEl);
|
|
const editAssetModalEl = document.getElementById('editAssetModal');
|
|
const editAssetModal = new bootstrap.Modal(editAssetModalEl);
|
|
|
|
// --- Functions ---
|
|
|
|
/**
|
|
* Shows a toast notification.
|
|
* @param {string} title - The title of the toast.
|
|
* @param {string} body - The body message of the toast.
|
|
* @param {string} type - 'success' or 'error'.
|
|
*/
|
|
function showToast(title, body, type = 'success') {
|
|
const toastHeader = notificationToastEl.querySelector('.toast-header');
|
|
|
|
toastHeader.classList.remove('bg-success', 'text-white', 'bg-danger', 'text-white');
|
|
|
|
if (type === 'success') {
|
|
toastHeader.classList.add('bg-success', 'text-white');
|
|
} else if (type === 'error') {
|
|
toastHeader.classList.add('bg-danger', 'text-white');
|
|
}
|
|
|
|
document.getElementById('toast-title').textContent = title;
|
|
document.getElementById('toast-body').textContent = body;
|
|
notificationToast.show();
|
|
}
|
|
|
|
/**
|
|
* Fetches data from the API.
|
|
* @param {string} endpoint - The API endpoint to fetch from.
|
|
* @param {object} options - Optional fetch options.
|
|
* @returns {Promise<any>} - The JSON response.
|
|
*/
|
|
async function fetchApi(endpoint, options = {}) {
|
|
try {
|
|
const response = await fetch(API_BASE + endpoint, options);
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({ message: 'Gagal memuat detail error.' }));
|
|
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error(`Error fetching ${endpoint}:`, error);
|
|
showToast('Error', `Terjadi kesalahan: ${error.message}`, 'error');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Populates select dropdowns for both add and edit modals.
|
|
*/
|
|
async function populateSelectOptions() {
|
|
const data = await fetchApi('get_options.php');
|
|
if (!data) return;
|
|
|
|
const selects = [
|
|
{ el: document.getElementById('id_kategori'), data: data.kategori, placeholder: 'Pilih Kategori...', name: 'nama_kategori' },
|
|
{ el: document.getElementById('id_kantor_lokasi'), data: data.kantor, placeholder: 'Pilih Lokasi...', name: 'nama_kantor' },
|
|
{ el: document.getElementById('edit_id_kategori'), data: data.kategori, placeholder: 'Pilih Kategori...', name: 'nama_kategori' },
|
|
{ el: document.getElementById('edit_id_kantor_lokasi'), data: data.kantor, placeholder: 'Pilih Lokasi...', name: 'nama_kantor' }
|
|
];
|
|
|
|
selects.forEach(s => {
|
|
if (s.el) {
|
|
s.el.innerHTML = `<option value="">${s.placeholder}</option>`;
|
|
s.data.forEach(item => {
|
|
s.el.innerHTML += `<option value="${item.id}">${item[s.name]}</option>`;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Fetches assets and renders them in the table.
|
|
*/
|
|
async function loadAssets() {
|
|
loadingIndicator.style.display = 'block';
|
|
assetsTableBody.innerHTML = '';
|
|
|
|
const assets = await fetchApi('get_assets.php');
|
|
|
|
loadingIndicator.style.display = 'none';
|
|
|
|
if (assets && assets.length > 0) {
|
|
assets.forEach(asset => {
|
|
const row = `
|
|
<tr>
|
|
<td>${asset.kode_aset}</td>
|
|
<td>${asset.nama_aset}</td>
|
|
<td>${asset.nama_kategori}</td>
|
|
<td>${asset.nama_kantor}</td>
|
|
<td><span class="status-badge status-${asset.status.toLowerCase()}">${asset.status}</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary btn-edit" data-asset-id="${asset.id}" title="Edit">
|
|
<i data-feather="edit-2" class="feather-sm"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-danger btn-delete" data-asset-id="${asset.id}" title="Hapus">
|
|
<i data-feather="trash-2" class="feather-sm"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
assetsTableBody.innerHTML += row;
|
|
});
|
|
} else if (assets) {
|
|
assetsTableBody.innerHTML = '<tr><td colspan="6" class="text-center">Belum ada data aset.</td></tr>';
|
|
} else {
|
|
assetsTableBody.innerHTML = '<tr><td colspan="6" class="text-center text-danger">Gagal memuat data aset.</td></tr>';
|
|
}
|
|
feather.replace();
|
|
}
|
|
|
|
/**
|
|
* Handles the submission of the 'Add Asset' form.
|
|
*/
|
|
async function handleAddAssetSubmit(event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
if (!addAssetForm.checkValidity()) {
|
|
addAssetForm.classList.add('was-validated');
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData(addAssetForm);
|
|
const submitButton = addAssetForm.querySelector('button[type="submit"]');
|
|
submitButton.disabled = true;
|
|
submitButton.innerHTML = '''<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Menyimpan...''';
|
|
|
|
const result = await fetchApi('add_asset.php', { method: 'POST', body: formData });
|
|
|
|
if (result && result.success) {
|
|
showToast('Sukses', 'Aset baru berhasil ditambahkan.');
|
|
addAssetForm.reset();
|
|
addAssetForm.classList.remove('was-validated');
|
|
bootstrap.Modal.getInstance(document.getElementById('addAssetModal')).hide();
|
|
loadAssets();
|
|
} else if (result) {
|
|
showToast('Error', result.message, 'error');
|
|
}
|
|
|
|
submitButton.disabled = false;
|
|
submitButton.innerHTML = 'Simpan Aset';
|
|
}
|
|
|
|
/**
|
|
* Opens the edit modal and populates it with asset data.
|
|
* @param {number} assetId - The ID of the asset to edit.
|
|
*/
|
|
async function openEditModal(assetId) {
|
|
const asset = await fetchApi(`get_asset.php?id=${assetId}`);
|
|
if (!asset) return;
|
|
|
|
document.getElementById('edit_id').value = asset.id;
|
|
document.getElementById('edit_nama_aset').value = asset.nama_aset;
|
|
document.getElementById('edit_id_kategori').value = asset.id_kategori;
|
|
document.getElementById('edit_id_kantor_lokasi').value = asset.id_kantor_lokasi;
|
|
document.getElementById('edit_spesifikasi').value = asset.spesifikasi;
|
|
document.getElementById('edit_tanggal_pembelian').value = asset.tanggal_pembelian;
|
|
document.getElementById('edit_harga_pembelian').value = asset.harga_pembelian;
|
|
document.getElementById('edit_vendor').value = asset.vendor;
|
|
document.getElementById('edit_status').value = asset.status;
|
|
|
|
editAssetModal.show();
|
|
}
|
|
|
|
/**
|
|
* Handles the submission of the 'Edit Asset' form.
|
|
*/
|
|
async function handleEditAssetSubmit(event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
if (!editAssetForm.checkValidity()) {
|
|
editAssetForm.classList.add('was-validated');
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData(editAssetForm);
|
|
const submitButton = editAssetForm.querySelector('button[type="submit"]');
|
|
submitButton.disabled = true;
|
|
submitButton.innerHTML = '''<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Menyimpan...''';
|
|
|
|
const result = await fetchApi('update_asset.php', { method: 'POST', body: formData });
|
|
|
|
if (result && result.success) {
|
|
showToast('Sukses', 'Aset berhasil diperbarui.');
|
|
editAssetModal.hide();
|
|
loadAssets();
|
|
} else if (result) {
|
|
showToast('Error', result.message, 'error');
|
|
}
|
|
|
|
submitButton.disabled = false;
|
|
submitButton.innerHTML = 'Simpan Perubahan';
|
|
}
|
|
|
|
/**
|
|
* Handles the deletion of an asset.
|
|
* @param {number} assetId - The ID of the asset to delete.
|
|
*/
|
|
async function handleDeleteAsset(assetId) {
|
|
if (!confirm('Anda yakin ingin menghapus aset ini? Tindakan ini tidak dapat dibatalkan.')) {
|
|
return;
|
|
}
|
|
|
|
const result = await fetchApi('delete_asset.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ id: assetId })
|
|
});
|
|
|
|
if (result && result.success) {
|
|
showToast('Sukses', 'Aset berhasil dihapus.');
|
|
loadAssets();
|
|
} else if (result) {
|
|
showToast('Error', result.message, 'error');
|
|
}
|
|
}
|
|
|
|
|
|
// --- Initializations ---
|
|
|
|
feather.replace();
|
|
populateSelectOptions();
|
|
loadAssets();
|
|
|
|
// --- Event Listeners ---
|
|
addAssetForm.addEventListener('submit', handleAddAssetSubmit);
|
|
editAssetForm.addEventListener('submit', handleEditAssetSubmit);
|
|
|
|
assetsTableBody.addEventListener('click', function(event) {
|
|
const editButton = event.target.closest('.btn-edit');
|
|
const deleteButton = event.target.closest('.btn-delete');
|
|
|
|
if (editButton) {
|
|
const assetId = editButton.dataset.assetId;
|
|
openEditModal(assetId);
|
|
}
|
|
|
|
if (deleteButton) {
|
|
const assetId = deleteButton.dataset.assetId;
|
|
handleDeleteAsset(assetId);
|
|
}
|
|
});
|
|
|
|
// Add feather icon class for easier styling
|
|
document.querySelectorAll('i[data-feather]').forEach(el => {
|
|
if(el.classList.contains('feather-sm')) return;
|
|
const iconName = el.getAttribute('data-feather');
|
|
el.classList.add(`icon-${iconName}`);
|
|
});
|
|
|
|
}); |