Vaibhav Surve 2dfe150a5c feat: AMS V1 — multi-page HTML prototype
- 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
2026-05-28 18:09:32 +05:30

310 lines
18 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Users & Roles | 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">
</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"><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 active"><span class="nav-icon">👥</span> Users &amp; Roles</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">Users &amp; Access Control</div></div>
<div class="topbar-actions">
<button class="btn btn-primary btn-sm" onclick="openModal('inviteModal')">+ Invite User</button>
<a href="index.html" class="icon-btn">🚪</a>
</div>
</header>
<main class="content">
<!-- Stats -->
<div class="grid-4 mb-4">
<div class="stat-card" style="--sc-color:var(--primary)"><div class="stat-icon" style="background:var(--primary-glow);color:var(--primary)">👥</div><div class="stat-label">Total Users</div><div class="stat-value" style="color:var(--primary)">10</div></div>
<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">Active</div><div class="stat-value" style="color:var(--success)">9</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">Inactive / Suspended</div><div class="stat-value" style="color:var(--warning)">1</div></div>
<div class="stat-card" style="--sc-color:var(--info)"><div class="stat-icon" style="background:var(--info-bg);color:var(--info)">🔐</div><div class="stat-label">Roles Defined</div><div class="stat-value" style="color:var(--info)">6</div></div>
</div>
<!-- Tabs -->
<div class="tab-container">
<div class="tabs" data-group="usr">
<button class="tab-btn active" data-tab="tab-users" data-group="usr">👥 User List</button>
<button class="tab-btn" data-tab="tab-roles" data-group="usr">🔐 Roles & Permissions</button>
<button class="tab-btn" data-tab="tab-sessions" data-group="usr">🖥️ Active Sessions</button>
</div>
<!-- Users List -->
<div class="tab-content active" id="tab-users" data-group="usr">
<div class="filters-row mb-3">
<div class="search-wrap" style="max-width:280px"><span style="color:var(--text-muted)">🔍</span><input type="text" id="userSearch" placeholder="Search users…"></div>
<select class="filter-sel"><option>All Roles</option><option>Super Admin</option><option>Asset Manager</option><option>IT Head</option><option>Finance Head</option><option>Employee</option></select>
<select class="filter-sel"><option>All Departments</option><option>IT</option><option>Finance</option><option>HR</option><option>Operations</option><option>Marketing</option></select>
<select class="filter-sel"><option>All Statuses</option><option>Active</option><option>Inactive</option></select>
</div>
<div class="table-wrapper">
<table class="data-table" id="userTable">
<thead><tr><th>User</th><th>Email</th><th>Role</th><th>Department</th><th>Status</th><th>Last Login</th><th>2FA</th><th>Actions</th></tr></thead>
<tbody id="userTbody"></tbody>
</table>
</div>
</div>
<!-- Roles & Permissions -->
<div class="tab-content" id="tab-roles" data-group="usr">
<div class="grid-2 mb-4" id="roleCards"></div>
<div class="card">
<div class="card-header"><span class="card-title">🔐 Permission Matrix</span><span style="font-size:12px;color:var(--text-muted)">✓ = Full Access · E = Edit Only · V = View Only · — = No Access</span></div>
<div class="card-body" style="overflow-x:auto">
<table class="perm-matrix">
<thead>
<tr>
<th>Module / Permission</th>
<th>Super Admin</th>
<th>Asset Manager</th>
<th>Dept Head</th>
<th>Finance Head</th>
<th>IT Head</th>
<th>Employee</th>
</tr>
</thead>
<tbody id="permMatrix"></tbody>
</table>
</div>
</div>
</div>
<!-- Active Sessions -->
<div class="tab-content" id="tab-sessions" data-group="usr">
<div class="alert alert-info mb-4">
<div class="alert-icon"></div>
<div><div class="alert-title">7 active sessions currently</div><div class="alert-text">You can revoke suspicious sessions from below. All sessions auto-expire after 7 days of inactivity.</div></div>
</div>
<div class="table-wrapper">
<table class="data-table">
<thead><tr><th>User</th><th>Device / Browser</th><th>IP Address</th><th>Location</th><th>Login Time</th><th>Last Active</th><th>Action</th></tr></thead>
<tbody id="sessionTbody"></tbody>
</table>
</div>
</div>
</div>
</main>
</div>
</div>
<!-- Invite Modal -->
<div class="modal-overlay" id="inviteModal">
<div class="modal">
<div class="modal-header"><span class="modal-title">Invite New User</span><button class="modal-close"></button></div>
<div class="modal-body">
<div class="form-group"><label class="form-label">Full Name <span class="req">*</span></label><input class="form-input" placeholder="Employee full name"></div>
<div class="form-group"><label class="form-label">Email Address <span class="req">*</span></label><input type="email" class="form-input" placeholder="employee@acmecorp.com"></div>
<div class="form-row">
<div class="form-group"><label class="form-label">Department <span class="req">*</span></label><select class="form-select"><option>IT</option><option>Finance</option><option>HR</option><option>Operations</option><option>Marketing</option><option>Admin</option></select></div>
<div class="form-group"><label class="form-label">Role <span class="req">*</span></label><select class="form-select"><option>Employee</option><option>Asset Coordinator</option><option>Department Head</option><option>Asset Manager</option><option>Finance Head</option></select></div>
</div>
<div class="form-group"><label class="form-label">Welcome Message (optional)</label><textarea class="form-textarea" rows="2" placeholder="Custom message to include in invite email…"></textarea></div>
<div class="alert alert-info" style="margin-top:8px">
<div class="alert-icon">📧</div>
<div><div class="alert-title">Invite process</div><div class="alert-text">An invite email with a one-time setup link (expires in 48 hours) will be sent to the user.</div></div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-ghost" onclick="closeModal('inviteModal')">Cancel</button>
<button class="btn btn-primary" onclick="sendInvite()">Send Invite</button>
</div>
</div>
</div>
<!-- Edit User Modal -->
<div class="modal-overlay" id="editUserModal">
<div class="modal">
<div class="modal-header"><span class="modal-title">Edit User</span><button class="modal-close"></button></div>
<div class="modal-body" id="editUserBody"></div>
<div class="modal-footer">
<button class="btn btn-ghost" onclick="closeModal('editUserModal')">Cancel</button>
<button class="btn btn-primary" onclick="saveUser()">Save Changes</button>
</div>
</div>
</div>
<div class="toast-container" id="toastContainer"></div>
<script src="js/data.js"></script>
<script src="js/app.js"></script>
<script>
const roles = [
{ name:'Super Admin', desc:'Full system access. Can manage all settings, users, and data.', color:'var(--danger)', perms:'All Modules', users:1 },
{ name:'Asset Manager', desc:'Manages all assets, can approve PRs, view all reports.', color:'var(--primary)', perms:'Assets, Reports, Procurement', users:2 },
{ name:'Department Head', desc:'Can view department assets, approve team PRs, raise tickets.', color:'var(--cyan)', perms:'Dept Assets, PR Approval', users:5 },
{ name:'Finance Head', desc:'Approves PRs (budget stage), views depreciation & financial reports.',color:'var(--warning)', perms:'Financial Reports, PR Approval', users:1 },
{ name:'IT Head', desc:'Manages IT assets, tickets, AMC, and user provisioning.', color:'var(--success)', perms:'IT Assets, Users (IT Dept)', users:1 },
{ name:'Employee', desc:'View own assigned assets, raise requests, acknowledge assignments.', color:'var(--text-muted)',perms:'View Own Assets, Raise Tickets', users:20 }
];
const permRows = [
{ module:'View All Assets', sa:'✓',am:'✓',dh:'V',fi:'V',it:'V',em:'—' },
{ module:'Create / Edit Assets', sa:'✓',am:'✓',dh:'—',fi:'—',it:'E',em:'—' },
{ module:'Delete / Dispose', sa:'✓',am:'✓',dh:'—',fi:'—',it:'—',em:'—' },
{ module:'Assign Assets', sa:'✓',am:'✓',dh:'E',fi:'—',it:'E',em:'—' },
{ module:'Transfer Assets', sa:'✓',am:'✓',dh:'E',fi:'—',it:'E',em:'—' },
{ module:'View Financial Reports',sa:'✓',am:'✓',dh:'—',fi:'✓',it:'—',em:'—' },
{ module:'Approve Purchase Req.', sa:'✓',am:'✓',dh:'E',fi:'E',it:'—',em:'—' },
{ module:'Raise Tickets', sa:'✓',am:'✓',dh:'✓',fi:'V',it:'✓',em:'✓' },
{ module:'Manage Users', sa:'✓',am:'—',dh:'—',fi:'—',it:'V',em:'—' },
{ module:'System Settings', sa:'✓',am:'—',dh:'—',fi:'—',it:'—',em:'—' },
{ module:'View Own Assets', sa:'✓',am:'✓',dh:'✓',fi:'✓',it:'✓',em:'✓' }
];
document.addEventListener('DOMContentLoaded', () => {
renderUsers();
renderRoles();
renderPermMatrix();
renderSessions();
initTabs();
document.getElementById('userSearch').addEventListener('input', filterUsers);
});
function renderUsers(data) {
const users = data || AMS.users;
document.getElementById('userTbody').innerHTML = users.map(u=>`
<tr>
<td>
<div class="flex items-center gap-3">
<div style="width:34px;height:34px;border-radius:50%;background:${u.color}22;color:${u.color};display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex-shrink:0">${u.av}</div>
<div><div style="font-weight:600;color:var(--text-primary)">${u.name}</div><div style="font-size:11px;color:var(--text-muted)">${u.dept}</div></div>
</div>
</td>
<td style="font-size:12.5px">${u.email}</td>
<td><span class="badge badge-primary" style="font-size:10px">${u.role}</span></td>
<td>${u.dept}</td>
<td><span class="badge ${statusBadge(u.status)}">${u.status}</span></td>
<td style="font-size:12px;color:var(--text-muted)">${u.lastLogin}</td>
<td><span style="color:${u.id!=='u009'?'var(--success)':'var(--danger)'}">${u.id!=='u009'?'✅ Enabled':'❌ Disabled'}</span></td>
<td>
<div class="flex gap-1">
<button class="btn btn-ghost btn-sm" onclick="editUser('${u.id}')">✏️</button>
<button class="btn btn-ghost btn-sm" onclick="revokeUser('${u.id}')" title="Revoke sessions">🔒</button>
<button class="btn btn-ghost btn-sm danger" onclick="toggleStatus('${u.id}')" style="color:var(--danger)">${u.status==='Active'?'🚫':'✅'}</button>
</div>
</td>
</tr>`).join('');
}
function filterUsers() {
const q = document.getElementById('userSearch').value.toLowerCase();
const filtered = AMS.users.filter(u => !q || u.name.toLowerCase().includes(q) || u.email.toLowerCase().includes(q) || u.role.toLowerCase().includes(q));
renderUsers(filtered);
}
function renderRoles() {
document.getElementById('roleCards').innerHTML = roles.map(r=>`
<div class="card">
<div class="card-body">
<div class="flex items-center gap-3 mb-3">
<div style="width:36px;height:36px;border-radius:var(--radius-md);background:${r.color}18;color:${r.color};display:flex;align-items:center;justify-content:center;font-size:16px">🔐</div>
<div><div style="font-weight:700;font-size:13.5px">${r.name}</div><div style="font-size:11px;color:var(--text-muted)">${r.users} user${r.users!==1?'s':''}</div></div>
</div>
<div style="font-size:12.5px;color:var(--text-secondary);margin-bottom:10px">${r.desc}</div>
<div style="font-size:11px;color:var(--text-muted)">Access: <span style="color:${r.color};font-weight:600">${r.perms}</span></div>
</div>
</div>`).join('');
}
function renderPermMatrix() {
const cols = ['sa','am','dh','fi','it','em'];
const colored = (v) => {
if(v==='✓') return `<span style="color:var(--success);font-size:15px">✓</span>`;
if(v==='E') return `<span class="badge badge-info" style="font-size:9px">Edit</span>`;
if(v==='V') return `<span class="badge badge-neutral" style="font-size:9px">View</span>`;
return `<span style="color:var(--text-muted)">—</span>`;
};
document.getElementById('permMatrix').innerHTML = permRows.map(r=>`
<tr>
<td>${r.module}</td>
${cols.map(c=>`<td>${colored(r[c])}</td>`).join('')}
</tr>`).join('');
}
function renderSessions() {
const sessions = [
{ user:'Arjun Sharma', device:'Chrome 124 / macOS', ip:'192.168.1.42', loc:'Bengaluru, IN', login:'Today 09:12', last:'2 min ago', current:true },
{ user:'Priya Kumar', device:'Chrome 124 / Windows',ip:'192.168.1.55', loc:'Bengaluru, IN', login:'Today 08:45', last:'15 min ago', current:false },
{ user:'Anita Singh', device:'Safari / iPhone 15', ip:'10.0.0.23', loc:'Bengaluru, IN', login:'Today 10:02', last:'5 min ago', current:false },
{ user:'Kavya Nair', device:'Firefox 125 / Ubuntu',ip:'192.168.1.78', loc:'Bengaluru, IN', login:'Today 09:55', last:'1 min ago', current:false },
{ user:'Deepak Joshi', device:'Edge 124 / Windows', ip:'192.168.1.90', loc:'Bengaluru, IN', login:'Yesterday', last:'18 hrs ago', current:false }
];
document.getElementById('sessionTbody').innerHTML = sessions.map(s=>`
<tr>
<td style="font-weight:600">${s.user} ${s.current?'<span class="badge badge-success" style="font-size:9px">You</span>':''}</td>
<td>${s.device}</td>
<td><code style="font-size:11px">${s.ip}</code></td>
<td>${s.loc}</td>
<td style="font-size:12px;color:var(--text-muted)">${s.login}</td>
<td style="font-size:12px;color:var(--text-muted)">${s.last}</td>
<td><button class="btn btn-${s.current?'ghost':'danger'} btn-sm" ${s.current?'disabled':''} onclick="revokeSession('${s.user}')">${s.current?'Current':'🔒 Revoke'}</button></td>
</tr>`).join('');
}
function editUser(id) {
const u = AMS.users.find(x=>x.id===id);
if(!u) return;
document.getElementById('editUserBody').innerHTML = `
<div class="form-row"><div class="form-group"><label class="form-label">Full Name</label><input class="form-input" value="${u.name}"></div>
<div class="form-group"><label class="form-label">Email</label><input class="form-input" type="email" value="${u.email}" readonly></div></div>
<div class="form-row"><div class="form-group"><label class="form-label">Role</label><select class="form-select"><option ${u.role==='Asset Manager'?'selected':''}>Asset Manager</option><option ${u.role==='IT Head'?'selected':''}>IT Head</option><option ${u.role==='Finance Head'?'selected':''}>Finance Head</option><option>Employee</option><option>Super Admin</option></select></div>
<div class="form-group"><label class="form-label">Department</label><select class="form-select"><option>IT</option><option>Finance</option><option>HR</option><option>Operations</option><option>Marketing</option><option>Admin</option></select></div></div>
<div class="form-group"><label class="form-label">Status</label><select class="form-select"><option ${u.status==='Active'?'selected':''}>Active</option><option ${u.status==='Inactive'?'selected':''}>Inactive</option></select></div>`;
openModal('editUserModal');
}
function saveUser() { closeModal('editUserModal'); showToast('User Updated','Changes saved','success'); }
function revokeUser(id) {
confirmAction('Revoke Sessions','This will log out all active sessions for this user. They will need to login again.',()=>{
showToast('Sessions Revoked','All sessions for user revoked','warning');
});
}
function toggleStatus(id) {
const u = AMS.users.find(x=>x.id===id);
if(!u) return;
u.status = u.status==='Active' ? 'Inactive' : 'Active';
renderUsers();
showToast('Status Updated',`${u.name} is now ${u.status}`, u.status==='Active'?'success':'warning');
}
function revokeSession(user) { showToast('Session Revoked',`${user}'s session has been terminated`,'warning'); }
function sendInvite() {
closeModal('inviteModal');
showToast('Invite Sent','Invitation email sent with 48-hour setup link','success');
}
function confirmAction(title, msg, cb) {
if(confirm(msg) && cb) cb();
}
</script>
</body>
</html>