- Login page with animated floating stat cards - Executive dashboard with Chart.js KPIs and activity feed - Full asset registry (list, search, filter, bulk actions, QR) - Asset detail page with 6 tabs (financial, maintenance, history…) - 3-step asset creation wizard with category-specific fields - Inventory: stock overview, GRN, location tree, physical audit - Procurement: PR → approval → PO → GRN → asset lifecycle - Maintenance: Kanban board, PM schedule, AMC contracts - Reports: depreciation schedule, utilization, compliance gauge - User management: roles, permission matrix, session control - Settings: 8 config sections (org, depreciation, security, integrations) - Premium dark UI with CSS variables, Chart.js 4, toast system
384 lines
21 KiB
HTML
384 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||
<title>Inventory | AMS</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="css/styles.css">
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<div class="app-layout">
|
||
<aside class="sidebar">
|
||
<div class="sidebar-logo"><div class="logo-icon">📦</div><div><div class="logo-title">AMS</div><div class="logo-sub">Asset Management</div></div></div>
|
||
<nav class="sidebar-nav">
|
||
<div class="nav-section-label">Overview</div>
|
||
<a href="dashboard.html" class="nav-item"><span class="nav-icon">📊</span> Dashboard</a>
|
||
<div class="nav-section-label">Assets</div>
|
||
<a href="assets.html" class="nav-item"><span class="nav-icon">📦</span> All Assets</a>
|
||
<a href="asset-create.html" class="nav-item"><span class="nav-icon">➕</span> Add Asset</a>
|
||
<div class="nav-section-label">Supply Chain</div>
|
||
<a href="inventory.html" class="nav-item active"><span class="nav-icon">🏪</span> Inventory</a>
|
||
<a href="procurement.html" class="nav-item"><span class="nav-icon">🛒</span> Procurement</a>
|
||
<div class="nav-section-label">Operations</div>
|
||
<a href="maintenance.html" class="nav-item"><span class="nav-icon">🔧</span> Maintenance</a>
|
||
<a href="reports.html" class="nav-item"><span class="nav-icon">📈</span> Reports</a>
|
||
<div class="nav-section-label">Administration</div>
|
||
<a href="users.html" class="nav-item"><span class="nav-icon">👥</span> Users</a>
|
||
<a href="settings.html" class="nav-item"><span class="nav-icon">⚙️</span> Settings</a>
|
||
</nav>
|
||
<div class="sidebar-footer"><div class="user-card"><div class="user-av">AS</div><div style="flex:1;min-width:0"><div class="user-name">Arjun Sharma</div><div class="user-role">Asset Manager</div></div></div></div>
|
||
</aside>
|
||
|
||
<div class="main-wrapper">
|
||
<header class="topbar">
|
||
<div class="topbar-left"><div class="topbar-title">Inventory Management</div></div>
|
||
<div class="topbar-actions">
|
||
<button class="btn btn-primary btn-sm" onclick="openModal('grnModal')">📋 Record GRN</button>
|
||
<button class="btn btn-secondary btn-sm" onclick="openModal('auditModal')">🔍 Physical Audit</button>
|
||
<a href="index.html" class="icon-btn">🚪</a>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="content">
|
||
<!-- Alerts -->
|
||
<div id="invAlerts" class="mb-4"></div>
|
||
|
||
<!-- KPIs -->
|
||
<div class="grid-4 mb-4" id="invStats"></div>
|
||
|
||
<!-- Tabs -->
|
||
<div class="tab-container">
|
||
<div class="tabs" data-group="inv">
|
||
<button class="tab-btn active" data-tab="tab-stock" data-group="inv">📊 Stock Overview</button>
|
||
<button class="tab-btn" data-tab="tab-location" data-group="inv">📍 By Location</button>
|
||
<button class="tab-btn" data-tab="tab-movement" data-group="inv">↔ Movement Log</button>
|
||
<button class="tab-btn" data-tab="tab-audit" data-group="inv">🔍 Audit Results</button>
|
||
</div>
|
||
|
||
<!-- Stock Overview -->
|
||
<div class="tab-content active" id="tab-stock" data-group="inv">
|
||
<div class="grid-2 mb-4">
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">📊 Stock by Category</span></div>
|
||
<div class="card-body"><canvas id="stockChart" height="240"></canvas></div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">⚠️ Low Stock Alerts</span><span class="badge badge-danger">5 items</span></div>
|
||
<div class="card-body" id="lowStockList"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-wrapper">
|
||
<table class="data-table" id="stockTable">
|
||
<thead><tr><th>Category</th><th>Total Assets</th><th>Active</th><th>Idle</th><th>Maintenance</th><th>Min Threshold</th><th>Status</th><th>Actions</th></tr></thead>
|
||
<tbody id="stockTbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- By Location -->
|
||
<div class="tab-content" id="tab-location" data-group="inv">
|
||
<div style="display:grid;grid-template-columns:280px 1fr;gap:16px">
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">📍 Location Tree</span></div>
|
||
<div class="card-body">
|
||
<ul class="tree-list" id="locationTree"></ul>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title" id="locDetailTitle">Select a location</span></div>
|
||
<div class="card-body" id="locDetailContent">
|
||
<div class="empty-state"><div class="empty-icon">📍</div><div class="empty-title">No location selected</div><div class="empty-text">Click on a location from the tree to view its assets</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Movement Log -->
|
||
<div class="tab-content" id="tab-movement" data-group="inv">
|
||
<div class="filters-row mb-4">
|
||
<div class="search-wrap" style="max-width:280px"><span style="color:var(--text-muted)">🔍</span><input type="text" placeholder="Search movements…" id="movSearch"></div>
|
||
<select class="filter-sel"><option>All Types</option><option>Inward (GRN)</option><option>Outward (Issue)</option><option>Transfer</option><option>Disposal</option></select>
|
||
<select class="filter-sel"><option>All Departments</option><option>IT</option><option>Finance</option><option>HR</option><option>Operations</option></select>
|
||
</div>
|
||
<div class="table-wrapper">
|
||
<table class="data-table">
|
||
<thead><tr><th>Date</th><th>Movement Type</th><th>Asset / Item</th><th>From</th><th>To</th><th>Qty</th><th>Reference</th><th>By</th></tr></thead>
|
||
<tbody id="movTbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Audit Results -->
|
||
<div class="tab-content" id="tab-audit" data-group="inv">
|
||
<div class="grid-3 mb-4">
|
||
<div class="stat-card" style="--sc-color:var(--success)">
|
||
<div class="stat-icon" style="background:var(--success-bg);color:var(--success)">✅</div>
|
||
<div class="stat-label">Assets Found</div>
|
||
<div class="stat-value" style="color:var(--success)">1,198</div>
|
||
<div class="stat-change up">96.1% of total</div>
|
||
</div>
|
||
<div class="stat-card" style="--sc-color:var(--danger)">
|
||
<div class="stat-icon" style="background:var(--danger-bg);color:var(--danger)">❌</div>
|
||
<div class="stat-label">Not Found</div>
|
||
<div class="stat-value" style="color:var(--danger)">49</div>
|
||
<div class="stat-change down">3.9% – Under investigation</div>
|
||
</div>
|
||
<div class="stat-card" style="--sc-color:var(--warning)">
|
||
<div class="stat-icon" style="background:var(--warning-bg);color:var(--warning)">⚠️</div>
|
||
<div class="stat-label">Discrepancies</div>
|
||
<div class="stat-value" style="color:var(--warning)">7</div>
|
||
<div class="stat-change down">Location mismatches</div>
|
||
</div>
|
||
</div>
|
||
<div class="alert alert-info mb-4">
|
||
<div class="alert-icon">ℹ️</div>
|
||
<div><div class="alert-title">Last Physical Audit: Q4 FY 2024-25 (March 2025)</div>
|
||
<div class="alert-text">Next scheduled audit: Q2 FY 2025-26 (September 2025). Audited by: Kavya Nair, Deepak Joshi</div>
|
||
</div>
|
||
<button class="btn btn-primary btn-sm" style="margin-left:auto;flex-shrink:0" onclick="openModal('auditModal')">Start New Audit</button>
|
||
</div>
|
||
<div class="table-wrapper">
|
||
<table class="data-table">
|
||
<thead><tr><th>Asset ID</th><th>Asset Name</th><th>System Location</th><th>Physical Location</th><th>Status</th><th>Action</th></tr></thead>
|
||
<tbody id="auditTbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- GRN Modal -->
|
||
<div class="modal-overlay" id="grnModal">
|
||
<div class="modal modal-lg">
|
||
<div class="modal-header"><span class="modal-title">📋 Record Goods Receipt Note (GRN)</span><button class="modal-close">✕</button></div>
|
||
<div class="modal-body">
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">GRN Number</label><input class="form-input" value="GRN-2025-042" readonly></div>
|
||
<div class="form-group"><label class="form-label">PO Reference <span class="req">*</span></label><select class="form-select"><option>PO-2025-001 – 5× Dell Laptops</option><option>PO-2025-002 – 8× TP-Link WAP</option><option>PO-2025-003 – Office Chairs</option></select></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Vendor</label><input class="form-input" value="Dell India Pvt. Ltd." readonly></div>
|
||
<div class="form-group"><label class="form-label">Receipt Date <span class="req">*</span></label><input type="date" class="form-input" value="2025-05-28"></div>
|
||
</div>
|
||
<div class="section-hdr mt-4">Items Received</div>
|
||
<table class="data-table" style="margin-bottom:14px">
|
||
<thead><tr><th>Item</th><th>Ordered Qty</th><th>Received Qty</th><th>Condition</th><th>Remarks</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Dell Latitude 5540 Laptop</td><td>5</td><td><input type="number" class="form-input" value="5" style="width:60px;padding:4px 8px"></td><td><select class="form-select" style="padding:4px 8px"><option>Good</option><option>Damaged</option><option>Partial</option></select></td><td><input class="form-input" placeholder="Notes" style="padding:4px 8px"></td></tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="form-group"><label class="form-label">Received By <span class="req">*</span></label><input class="form-input" value="Arjun Sharma"></div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-ghost" onclick="closeModal('grnModal')">Cancel</button>
|
||
<button class="btn btn-primary" onclick="saveGRN()">Save GRN & Create Assets</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Audit Modal -->
|
||
<div class="modal-overlay" id="auditModal">
|
||
<div class="modal">
|
||
<div class="modal-header"><span class="modal-title">🔍 Start Physical Audit</span><button class="modal-close">✕</button></div>
|
||
<div class="modal-body">
|
||
<div class="form-group"><label class="form-label">Audit Name <span class="req">*</span></label><input class="form-input" value="Q2 FY2025-26 Physical Audit"></div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Scope</label><select class="form-select"><option>All Locations</option><option>Floor 2 Only</option><option>Server Room</option><option>Warehouse</option></select></div>
|
||
<div class="form-group"><label class="form-label">Assigned Auditors</label><input class="form-input" value="Kavya Nair, Deepak Joshi"></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Start Date</label><input type="date" class="form-input" value="2025-06-01"></div>
|
||
<div class="form-group"><label class="form-label">End Date</label><input type="date" class="form-input" value="2025-06-05"></div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-ghost" onclick="closeModal('auditModal')">Cancel</button>
|
||
<button class="btn btn-primary" onclick="startAudit()">Start Audit</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast-container" id="toastContainer"></div>
|
||
<script src="js/data.js"></script>
|
||
<script src="js/app.js"></script>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
renderAlerts();
|
||
renderStats();
|
||
renderStockTable();
|
||
renderLowStock();
|
||
renderMovements();
|
||
renderAudit();
|
||
renderLocationTree();
|
||
renderStockChart();
|
||
initTabs();
|
||
initTrees();
|
||
});
|
||
|
||
function renderAlerts() {
|
||
document.getElementById('invAlerts').innerHTML = `
|
||
<div class="alert alert-warning">
|
||
<div class="alert-icon">⚠️</div>
|
||
<div><div class="alert-title">5 categories below minimum stock threshold</div><div class="alert-text">Toner Cartridges, Projector Lamps, UPS Batteries, Network Cables, Keyboard/Mouse sets need reorder</div></div>
|
||
<a href="procurement.html" class="btn btn-warning btn-sm" style="margin-left:auto;flex-shrink:0;color:var(--warning);background:var(--warning-bg);border-color:rgba(245,158,11,.2)">Raise PR →</a>
|
||
</div>`;
|
||
}
|
||
|
||
function renderStats() {
|
||
const stats = [
|
||
{ label:'Total Items', icon:'📦', val:'1,247', color:'var(--primary)' },
|
||
{ label:'Active', icon:'✅', val:'1,089', color:'var(--success)' },
|
||
{ label:'Low Stock', icon:'📉', val:'5', color:'var(--danger)' },
|
||
{ label:'Pending GRNs', icon:'📋', val:'3', color:'var(--warning)' }
|
||
];
|
||
document.getElementById('invStats').innerHTML = stats.map(s=>`
|
||
<div class="stat-card" style="--sc-color:${s.color}">
|
||
<div class="stat-icon" style="background:${s.color}18;color:${s.color}">${s.icon}</div>
|
||
<div class="stat-label">${s.label}</div>
|
||
<div class="stat-value" style="color:${s.color}">${s.val}</div>
|
||
</div>`).join('');
|
||
}
|
||
|
||
function renderStockTable() {
|
||
document.getElementById('stockTbody').innerHTML = AMS.categories.map(c => {
|
||
const idle = Math.floor(c.count * 0.05);
|
||
const maint = Math.floor(c.count * 0.04);
|
||
const active = c.count - idle - maint;
|
||
const below = active < c.minStock;
|
||
return `<tr>
|
||
<td><div class="flex items-center gap-2">${c.icon} <strong>${c.name}</strong></div></td>
|
||
<td><strong>${c.count}</strong></td>
|
||
<td style="color:var(--success)">${active}</td>
|
||
<td style="color:var(--warning)">${idle}</td>
|
||
<td style="color:var(--info)">${maint}</td>
|
||
<td>${c.minStock}</td>
|
||
<td><span class="badge ${below?'badge-danger':'badge-success'}">${below?'⚠ Low Stock':'✓ OK'}</span></td>
|
||
<td><button class="btn btn-ghost btn-sm" onclick="showToast('Threshold','Opening threshold config','info')">⚙️ Config</button></td>
|
||
</tr>`;
|
||
}).join('');
|
||
}
|
||
|
||
function renderLowStock() {
|
||
const low = [
|
||
{ name:'Toner Cartridges', cat:'Consumables', current:2, min:10, icon:'🖨️' },
|
||
{ name:'Projector Lamps', cat:'AV Equipment',current:0, min:2, icon:'💡' },
|
||
{ name:'UPS Batteries', cat:'Power Equip', current:1, min:3, icon:'🔋' },
|
||
{ name:'Cat6 Network Cable', cat:'Networking',current:3, min:10, icon:'🔌' },
|
||
{ name:'Keyboard & Mouse Sets', cat:'Peripherals',current:4, min:15, icon:'⌨️' }
|
||
];
|
||
document.getElementById('lowStockList').innerHTML = low.map(l=>`
|
||
<div class="flex items-center gap-3 mb-3" style="padding:10px;background:var(--bg-surface);border-radius:var(--radius-md);border:1px solid rgba(239,68,68,.15)">
|
||
<span style="font-size:20px">${l.icon}</span>
|
||
<div style="flex:1">
|
||
<div style="font-size:13px;font-weight:600">${l.name}</div>
|
||
<div style="font-size:11px;color:var(--text-muted)">${l.cat} · Min: ${l.min}</div>
|
||
<div class="progress-wrap mt-2" style="height:4px">
|
||
<div class="progress-fill" style="width:${Math.round(l.current/l.min*100)}%;background:linear-gradient(90deg,var(--danger),var(--warning))"></div>
|
||
</div>
|
||
</div>
|
||
<div style="text-align:right">
|
||
<div style="font-size:16px;font-weight:800;color:var(--danger)">${l.current}</div>
|
||
<div style="font-size:10px;color:var(--text-muted)">in stock</div>
|
||
</div>
|
||
</div>`).join('') + `<a href="procurement.html" class="btn btn-primary btn-sm w-full" style="margin-top:8px">Raise Purchase Request →</a>`;
|
||
}
|
||
|
||
function renderMovements() {
|
||
const movs = [
|
||
{ date:'2025-05-28', type:'Inward (GRN)', item:'Dell Latitude 5540 Laptop', from:'Vendor', to:'Warehouse', qty:5, ref:'GRN-2025-041', by:'Arjun Sharma' },
|
||
{ date:'2025-05-27', type:'Outward (Issue)', item:'TP-Link WAP EAP670 (×8)', from:'Warehouse', to:'IT Dept – Floor 3', qty:8, ref:'ISS-2025-022', by:'Kavya Nair' },
|
||
{ date:'2025-05-26', type:'Transfer', item:'Epson Projector', from:'Marketing F3', to:'Conference Room A', qty:1, ref:'TRF-2025-015', by:'Deepak Joshi' },
|
||
{ date:'2025-05-25', type:'Disposal', item:'HP ProBook 440 G4 (×2)', from:'IT Dept', to:'Disposed', qty:2, ref:'DSP-2025-008', by:'Arjun Sharma' },
|
||
{ date:'2025-05-24', type:'Outward (Issue)', item:'Steelcase Chair (×10)', from:'Warehouse', to:'Floor 3 Expansion', qty:10, ref:'ISS-2025-021', by:'Deepak Joshi' },
|
||
{ date:'2025-05-22', type:'Inward (GRN)', item:'Cisco IP Phone 8841 (×5)', from:'Vendor', to:'Warehouse', qty:5, ref:'GRN-2025-040', by:'Kavya Nair' }
|
||
];
|
||
const typeColor = {'Inward (GRN)':'badge-success','Outward (Issue)':'badge-info','Transfer':'badge-primary','Disposal':'badge-danger'};
|
||
document.getElementById('movTbody').innerHTML = movs.map(m=>`
|
||
<tr>
|
||
<td>${fmtDate(m.date)}</td>
|
||
<td><span class="badge ${typeColor[m.type]||'badge-neutral'}">${m.type}</span></td>
|
||
<td style="font-weight:600;color:var(--text-primary)">${m.item}</td>
|
||
<td>${m.from}</td>
|
||
<td>${m.to}</td>
|
||
<td style="font-weight:700">${m.qty}</td>
|
||
<td><code style="font-size:11px;color:var(--primary-light)">${m.ref}</code></td>
|
||
<td>${m.by}</td>
|
||
</tr>`).join('');
|
||
}
|
||
|
||
function renderAudit() {
|
||
const discrepancies = [
|
||
{ id:'AST-2025-007', name:'Epson Projector', sysLoc:'Marketing – F3', phyLoc:'Conference Room A', status:'Location Mismatch' },
|
||
{ id:'AST-2025-015', name:'HP ProDesk 600', sysLoc:'Finance – F1', phyLoc:'Not Found', status:'Missing' },
|
||
{ id:'AST-2025-012', name:'APC UPS 3KVA', sysLoc:'Server Room B1', phyLoc:'Server Room B1', status:'Found' }
|
||
];
|
||
document.getElementById('auditTbody').innerHTML = discrepancies.map(d=>`
|
||
<tr>
|
||
<td><code style="font-size:11px;color:var(--primary-light)">${d.id}</code></td>
|
||
<td style="font-weight:600;color:var(--text-primary)">${d.name}</td>
|
||
<td>${d.sysLoc}</td>
|
||
<td>${d.phyLoc}</td>
|
||
<td><span class="badge ${d.status==='Found'?'badge-success':d.status==='Missing'?'badge-danger':'badge-warning'}">${d.status}</span></td>
|
||
<td><button class="btn btn-ghost btn-sm" onclick="showToast('Update','Location updated in system','success')">Update</button></td>
|
||
</tr>`).join('');
|
||
}
|
||
|
||
function renderLocationTree() {
|
||
function buildTree(nodes) {
|
||
return `<ul class="tree-list" style="padding-left:0">
|
||
${nodes.map(n => `
|
||
<li class="tree-node">
|
||
<div class="tree-label tree-toggle ${n.children?'':'leaf'}" onclick="${n.children?'':(`selectLocation('${n.id}','${n.name}')`)}" style="${n.children?'':''}" >
|
||
${n.children ? `<span class="tree-arrow" style="font-size:10px">▶</span>` : `<span style="font-size:10px;color:var(--text-muted)">•</span>`}
|
||
<span>${n.children ? '📁' : '📍'} ${n.name}</span>
|
||
</div>
|
||
${n.children ? `<div class="tree-children">${buildTree(n.children)}</div>` : ''}
|
||
</li>`).join('')}
|
||
</ul>`;
|
||
}
|
||
document.getElementById('locationTree').outerHTML = `<div id="locationTree">${buildTree(AMS.locations)}</div>`;
|
||
initTrees();
|
||
}
|
||
|
||
function selectLocation(id, name) {
|
||
document.querySelectorAll('.tree-label').forEach(el => el.classList.remove('selected'));
|
||
document.getElementById('locDetailTitle').textContent = `📍 ${name}`;
|
||
const locAssets = AMS.assets.filter(a => a.loc.includes(name.split('–').pop().trim()) || Math.random() > .4).slice(0,6);
|
||
document.getElementById('locDetailContent').innerHTML = `
|
||
<div style="font-size:12px;color:var(--text-muted);margin-bottom:14px">Showing ${locAssets.length} assets in <strong>${name}</strong></div>
|
||
${locAssets.map(a=>`
|
||
<div class="flex items-center gap-3 mb-3" style="padding:10px;background:var(--bg-surface);border-radius:var(--radius-md);cursor:pointer" onclick="window.location.href='asset-detail.html?id=${a.id}'">
|
||
<span style="font-size:18px">${a.icon}</span>
|
||
<div style="flex:1"><div style="font-size:13px;font-weight:600">${a.name}</div><div style="font-size:11px;color:var(--text-muted)">${a.id} · ${a.assignee}</div></div>
|
||
<span class="badge ${statusBadge(a.status)}">${a.status}</span>
|
||
</div>`).join('')}`;
|
||
}
|
||
|
||
function renderStockChart() {
|
||
new Chart(document.getElementById('stockChart'), {
|
||
type:'bar',
|
||
data:{
|
||
labels: AMS.categories.map(c=>c.name),
|
||
datasets:[
|
||
{ label:'Active', data:AMS.categories.map(c=>Math.floor(c.count*.91)), backgroundColor:'rgba(16,185,129,.7)', borderRadius:4 },
|
||
{ label:'Idle', data:AMS.categories.map(c=>Math.floor(c.count*.05)), backgroundColor:'rgba(245,158,11,.7)', borderRadius:4 },
|
||
{ label:'Maintenance', data:AMS.categories.map(c=>Math.floor(c.count*.04)), backgroundColor:'rgba(59,130,246,.7)', borderRadius:4 }
|
||
]
|
||
},
|
||
options:{
|
||
responsive:true, maintainAspectRatio:false, plugins:{legend:{labels:{color:'#94A3B8',font:{family:'Inter',size:11},usePointStyle:true}}},
|
||
scales:{x:{stacked:true,grid:{color:'rgba(255,255,255,.04)'},ticks:{color:'#4B5563',font:{family:'Inter',size:9},maxRotation:45}},
|
||
y:{stacked:true,grid:{color:'rgba(255,255,255,.04)'},ticks:{color:'#4B5563',font:{family:'Inter',size:11}}}}
|
||
}
|
||
});
|
||
}
|
||
|
||
function saveGRN() { closeModal('grnModal'); showToast('GRN Saved','5 assets created from GRN-2025-042','success'); }
|
||
function startAudit() { closeModal('auditModal'); showToast('Audit Started','Q2 Physical Audit initiated. Auditors notified.','info'); }
|
||
</script>
|
||
</body>
|
||
</html>
|