uas-web-22412056/Widuri-Client/script.js
2025-07-15 15:20:21 +07:00

291 lines
8.5 KiB
JavaScript

// Global variables
let inventory = [];
let currentEditId = null;
let apiBaseUrl = 'http://localhost:11000/api'; // Replace with your actual API URL
// DOM elements
const inventoryTableBody = document.getElementById('inventoryTableBody');
const addBtn = document.getElementById('addBtn');
const refreshBtn = document.getElementById('refreshBtn');
const searchInput = document.getElementById('searchInput');
const modal = document.getElementById('modal');
const modalTitle = document.getElementById('modalTitle');
const itemForm = document.getElementById('itemForm');
const cancelBtn = document.getElementById('cancelBtn');
const closeBtn = document.querySelector('.close');
const loading = document.getElementById('loading');
const error = document.getElementById('error');
const errorMessage = document.getElementById('errorMessage');
// Stats elements
const totalItems = document.getElementById('totalItems');
const totalValue = document.getElementById('totalValue');
const lowStock = document.getElementById('lowStock');
// API functions
async function fetchInventory() {
try {
showLoading(true);
hideError();
const response = await fetch(`${apiBaseUrl}/read`);
const result = await response.json();
if (result.status === 'Berhasil') {
inventory = result.data || [];
renderInventoryTable();
updateStats();
} else {
throw new Error(result.message || 'Failed to fetch inventory');
}
} catch (err) {
console.error('Error fetching inventory:', err);
showError(`Failed to load inventory: ${err.message}`);
inventory = [];
renderInventoryTable();
} finally {
showLoading(false);
}
}
async function createItem(item) {
try {
const response = await fetch(`${apiBaseUrl}/create`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(item)
});
const result = await response.json();
if (result.status === 'Berhasil') {
await fetchInventory(); // Refresh the list
return true;
} else {
throw new Error(result.message || 'Failed to create item');
}
} catch (err) {
console.error('Error creating item:', err);
showError(`Failed to create item: ${err.message}`);
return false;
}
}
async function updateItem(id, item) {
item.key = id; // Ensure the item has the ID for update
try {
const response = await fetch(`${apiBaseUrl}/update`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(item)
});
const result = await response.json();
if (result.status === 'Berhasil') {
await fetchInventory(); // Refresh the list
return true;
} else {
throw new Error(result.message || 'Failed to update item');
}
} catch (err) {
console.error('Error updating item:', err);
showError(`Failed to update item: ${err.message}`);
return false;
}
}
async function deleteItem(id) {
try {
const response = await fetch(`${apiBaseUrl}/delete`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ key: id })
});
const result = await response.json();
if (result.status === 'Berhasil') {
await fetchInventory(); // Refresh the list
return true;
} else {
throw new Error(result.message || 'Failed to delete item');
}
} catch (err) {
console.error('Error deleting item:', err);
showError(`Failed to delete item: ${err.message}`);
return false;
}
}
// UI functions
function renderInventoryTable(items = inventory) {
inventoryTableBody.innerHTML = '';
if (items.length === 0) {
const row = document.createElement('tr');
row.innerHTML = `
<td colspan="6" style="text-align: center; padding: 40px; color: #7f8c8d;">
No items found
</td>
`;
inventoryTableBody.appendChild(row);
return;
}
items.forEach(item => {
const row = document.createElement('tr');
const totalItemValue = (item.price * item.qty).toFixed(2);
const quantityClass = item.qty <= 10 ? 'low-stock' : '';
row.innerHTML = `
<td>${item.id}</td>
<td>${item.name}</td>
<td class="price">$${item.price.toFixed(2)}</td>
<td class="quantity ${quantityClass}">${item.qty}</td>
<td class="price">$${totalItemValue}</td>
<td class="actions">
<button class="btn btn-warning" onclick="editItem(${item.id})">Edit</button>
<button class="btn btn-danger" onclick="deleteItemConfirm(${item.id})">Delete</button>
</td>
`;
inventoryTableBody.appendChild(row);
});
}
function updateStats() {
const total = inventory.length;
const value = inventory.reduce((sum, item) => sum + (item.price * item.qty), 0);
const lowStockCount = inventory.filter(item => item.qty <= 10).length;
totalItems.textContent = total;
totalValue.textContent = `$${value.toFixed(2)}`;
lowStock.textContent = lowStockCount;
}
function showLoading(show) {
loading.style.display = show ? 'block' : 'none';
}
function showError(message) {
errorMessage.textContent = message;
error.style.display = 'block';
}
function hideError() {
error.style.display = 'none';
}
function showModal(title = 'Add New Item') {
modalTitle.textContent = title;
modal.style.display = 'block';
}
function hideModal() {
modal.style.display = 'none';
itemForm.reset();
currentEditId = null;
}
function filterItems(searchTerm) {
const filtered = inventory.filter(item =>
item.name.toLowerCase().includes(searchTerm.toLowerCase())
);
renderInventoryTable(filtered);
}
// Event handlers
function editItem(id) {
const item = inventory.find(item => item.id === id);
if (item) {
currentEditId = id;
document.getElementById('itemName').value = item.name;
document.getElementById('itemPrice').value = item.price;
document.getElementById('itemQty').value = item.qty;
showModal('Edit Item');
}
}
function deleteItemConfirm(id) {
const item = inventory.find(item => item.id === id);
if (item && confirm(`Are you sure you want to delete "${item.name}"?`)) {
deleteItem(id);
}
}
// Event listeners
addBtn.addEventListener('click', () => {
showModal('Add New Item');
});
refreshBtn.addEventListener('click', fetchInventory);
searchInput.addEventListener('input', (e) => {
filterItems(e.target.value);
});
closeBtn.addEventListener('click', hideModal);
cancelBtn.addEventListener('click', hideModal);
// Close modal when clicking outside
window.addEventListener('click', (e) => {
if (e.target === modal) {
hideModal();
}
});
// Form submission
itemForm.addEventListener('submit', async (e) => {
e.preventDefault();
const name = document.getElementById('itemName').value.trim();
const price = parseFloat(document.getElementById('itemPrice').value);
const qty = parseInt(document.getElementById('itemQty').value);
if (!name || isNaN(price) || isNaN(qty)) {
alert('Please fill in all fields correctly');
return;
}
const item = { name, price, qty };
let success = false;
if (currentEditId) {
success = await updateItem(currentEditId, item);
} else {
success = await createItem(item);
}
if (success) {
hideModal();
}
});
// Initialize the application
document.addEventListener('DOMContentLoaded', () => {
fetchInventory();
});
// For demo purposes - if API is not available, use mock data
function loadMockData() {
inventory = [
{ id: 1, name: 'Laptop', price: 999.99, qty: 15 },
{ id: 2, name: 'Mouse', price: 29.99, qty: 50 },
{ id: 3, name: 'Keyboard', price: 79.99, qty: 8 },
{ id: 4, name: 'Monitor', price: 299.99, qty: 12 },
{ id: 5, name: 'Headphones', price: 149.99, qty: 3 }
];
renderInventoryTable();
updateStats();
}
// Uncomment the line below to use mock data for testing
// loadMockData();