97 lines
3.5 KiB
JavaScript
97 lines
3.5 KiB
JavaScript
import * as bootstrap from 'bootstrap';
|
|
window.bootstrap = bootstrap;
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
// Initialize all Bootstrap modals
|
|
document.querySelectorAll('.modal').forEach(modalEl => {
|
|
bootstrap.Modal.getOrCreateInstance(modalEl);
|
|
});
|
|
|
|
// Initialize tooltips
|
|
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
|
|
if (!el._tooltipInstance) {
|
|
el._tooltipInstance = new bootstrap.Tooltip(el, { container: 'body' });
|
|
}
|
|
});
|
|
|
|
// ---------------- DASHBOARD LOGIC ----------------
|
|
const toggleBtn = document.getElementById("toggleViewBtn");
|
|
const gridView = document.getElementById("gridView");
|
|
const tableView = document.getElementById("tableView");
|
|
const searchInput = document.getElementById("inventorySearch");
|
|
const tbody = document.getElementById("inventoryRows");
|
|
|
|
if(toggleBtn && gridView && tableView && tbody) {
|
|
// TOGGLE GRID/TABLE
|
|
toggleBtn.addEventListener("click", () => {
|
|
if(gridView.style.display !== "none") {
|
|
gridView.style.display = "none";
|
|
tableView.style.display = "block";
|
|
toggleBtn.textContent = "Switch to Grid View";
|
|
} else {
|
|
gridView.style.display = "block";
|
|
tableView.style.display = "none";
|
|
toggleBtn.textContent = "Switch to Table View";
|
|
}
|
|
});
|
|
|
|
// SEARCH FILTER
|
|
if(searchInput) {
|
|
searchInput.addEventListener("input", e => {
|
|
const term = e.target.value.toLowerCase();
|
|
[...tbody.querySelectorAll("tr")].forEach(row => {
|
|
row.style.display = row.textContent.toLowerCase().includes(term) ? "" : "none";
|
|
});
|
|
});
|
|
}
|
|
|
|
// SORTING
|
|
document.querySelectorAll("th[data-key]").forEach(th => {
|
|
let sortAsc = true;
|
|
th.addEventListener("click", () => {
|
|
const key = th.dataset.key;
|
|
const indexMap = {name:0,set:1,condition:2,qty:3,price:4,market:5,gain:6};
|
|
const idx = indexMap[key];
|
|
const rows = [...tbody.querySelectorAll("tr")];
|
|
|
|
rows.sort((a,b) => {
|
|
let aText = a.children[idx].textContent.replace(/\$|,/g,'').toLowerCase();
|
|
let bText = b.children[idx].textContent.replace(/\$|,/g,'').toLowerCase();
|
|
if(!isNaN(aText) && !isNaN(bText)) return sortAsc ? aText-bText : bText-aText;
|
|
return sortAsc ? aText.localeCompare(bText) : bText.localeCompare(aText);
|
|
});
|
|
|
|
sortAsc = !sortAsc;
|
|
tbody.innerHTML="";
|
|
rows.forEach(r => tbody.appendChild(r));
|
|
});
|
|
});
|
|
|
|
// INLINE EDITING + GAIN/LOSS UPDATE
|
|
tbody.addEventListener("input", e => {
|
|
const row = e.target.closest("tr");
|
|
if(!row) return;
|
|
|
|
const priceCell = row.querySelector(".editable-price");
|
|
const qtyCell = row.querySelector(".editable-qty");
|
|
const marketCell = row.children[5];
|
|
const gainCell = row.querySelector(".gain");
|
|
|
|
if(e.target.classList.contains("editable-price")) {
|
|
e.target.textContent = e.target.textContent.replace(/[^\d.]/g,"");
|
|
}
|
|
if(e.target.classList.contains("editable-qty")) {
|
|
e.target.textContent = e.target.textContent.replace(/\D/g,"");
|
|
}
|
|
|
|
const price = parseFloat(priceCell.textContent) || 0;
|
|
const qty = parseInt(qtyCell.textContent) || 0;
|
|
const market = parseFloat(marketCell.textContent) || 0;
|
|
const gain = market - price;
|
|
|
|
gainCell.textContent = (gain>=0 ? "+" : "-") + Math.abs(gain);
|
|
gainCell.className = gain>=0 ? "gain text-success" : "gain text-danger";
|
|
});
|
|
}
|
|
}); |