114 lines
4.2 KiB
Plaintext
114 lines
4.2 KiB
Plaintext
@await Html.PartialAsync("PagesView/Inventory/_InventoryStyles")
|
|
@await Html.PartialAsync("PagesView/Inventory/_InventoryHelpers")
|
|
|
|
<div class="inventory-wrapper">
|
|
@* {{-- HEADER --}} *@
|
|
<div class="inv-header">
|
|
<div class="inv-header-inner">
|
|
<i class="fas fa-file-invoice inv-header-icon"></i>
|
|
<div>
|
|
<h1>Inventory Management</h1>
|
|
<p>Manage inventory transaction, status, and comparison</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@* {{-- TAB NAV --}}
|
|
{{-- data-tab-id matches the ViewComponent switch:*@
|
|
<div class="inv-tabs" role="tablist">
|
|
<button class="inv-tab-btn active" data-tab-id="1" role="tab">
|
|
<i class="fas fa-user-tag"></i> Inventory
|
|
</button>
|
|
<button class="inv-tab-btn" data-tab-id="2" role="tab">
|
|
<i class="fas fa-clock"></i> For Approval
|
|
</button>
|
|
<button class="inv-tab-btn" data-tab-id="3" role="tab">
|
|
<i class="fas fa-id-badge"></i> Return Issuance Slip (Report)
|
|
</button>
|
|
<button class="inv-tab-btn" data-tab-id="4" role="tab">
|
|
<i class="fas fa-store"></i> Material Return Slip (Report)
|
|
</button>
|
|
<button class="inv-tab-btn" data-tab-id="5" role="tab">
|
|
<i class="fas fa-check-circle"></i> Transaction History
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div id="inv-tab-content">
|
|
<div class="inv-tab-loading">
|
|
<div class="inv-spinner"></div>
|
|
<span>Loading…</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
"use strict";
|
|
// ── Prevent re-initialization on cache restore ──
|
|
if (window.__invTab1Initialized) return;
|
|
window.__invTab1Initialized = true;
|
|
|
|
const tabContent = document.getElementById("inv-tab-content");
|
|
const tabBtns = document.querySelectorAll(".inv-tab-btn");
|
|
|
|
// Cache stores the raw HTML string per tab id
|
|
const cache = {};
|
|
let activeTabId = null;
|
|
|
|
async function loadTab(tabId) {
|
|
if (activeTabId === tabId) return;
|
|
activeTabId = tabId;
|
|
|
|
// Mark active button
|
|
tabBtns.forEach(b => b.classList.toggle("active", b.dataset.tabId === String(tabId)));
|
|
|
|
if (cache[tabId]) {
|
|
// ── FIX: inject cached HTML then re-run its <script> blocks ──────
|
|
injectHtml(tabContent, cache[tabId]);
|
|
return;
|
|
}
|
|
|
|
tabContent.innerHTML = `<div class="inv-tab-loading">
|
|
<div class="inv-spinner"></div><span>Loading…</span></div>`;
|
|
|
|
try {
|
|
const res = await fetch(`/InventoryMgmt/GetInventoryTabPage?id=${tabId}`);
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
const html = await res.text();
|
|
cache[tabId] = html;
|
|
injectHtml(tabContent, html);
|
|
} catch (err) {
|
|
console.error("Tab load error:", err);
|
|
tabContent.innerHTML = `
|
|
<div class="inv-placeholder">
|
|
<i class="fas fa-exclamation-triangle" style="color:#ff5c5c"></i>
|
|
<h3>Failed to load</h3>
|
|
<p>Please try again or refresh the page.</p>
|
|
</div>`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set innerHTML then re-execute every <script> block so IIFEs inside
|
|
* ViewComponent views fire correctly — both on first load AND cache restore.
|
|
*/
|
|
function injectHtml(container, html) {
|
|
container.innerHTML = html;
|
|
container.querySelectorAll("script").forEach(oldScript => {
|
|
const newScript = document.createElement("script");
|
|
Array.from(oldScript.attributes).forEach(attr =>
|
|
newScript.setAttribute(attr.name, attr.value));
|
|
newScript.textContent = oldScript.textContent;
|
|
oldScript.replaceWith(newScript);
|
|
});
|
|
}
|
|
|
|
// Wire tab clicks
|
|
tabBtns.forEach(btn =>
|
|
btn.addEventListener("click", () => loadTab(parseInt(btn.dataset.tabId, 10)))
|
|
);
|
|
|
|
// Auto-load the first tab on page ready
|
|
loadTab(1);
|
|
})();
|
|
</script>
|
|
@await Html.PartialAsync("PagesView/Inventory/_InventoryTransactModal") |