NonInventPurchasingSystem/CPRNIMS.WebApps/Views/Account/Index.cshtml
rowell_m_soriano 7cf4852256
All checks were successful
Build and Deploy CPRNIMS / build-and-deploy (push) Successful in 3m35s
UploadPath change to new path C:\\inetpub\\cprnims-web\\wwwroot\\Content\\Images
2026-07-01 07:07:26 +08:00

840 lines
40 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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.

<title>User Management</title>
<link href="~/lib/bootstrap-icons/font/bootstrap-icons.min.css" rel="stylesheet" />
<link href="~/css/account/useraccount.css" rel="stylesheet" />
<body>
<!-- ── Page Header ── -->
<div class="page-header">
<div class="page-title-group">
<h1><i class="bi bi-people" style="font-size:20px; margin-right:8px; color:var(--teal-600)"></i>User Management</h1>
<p>Manage system users, roles, and access permissions</p>
</div>
<button class="btn-create" onclick="openModal('modalCreate')">
<i class="bi bi-person-plus-fill"></i> Create New User
</button>
</div>
<!-- ── Stat Cards ── -->
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Total Users</div>
<div class="stat-value">124</div>
<div class="stat-icon"><i class="bi bi-people-fill"></i></div>
</div>
<div class="stat-card">
<div class="stat-label">Active</div>
<div class="stat-value">110</div>
<div class="stat-icon"><i class="bi bi-check-circle-fill"></i></div>
</div>
<div class="stat-card danger">
<div class="stat-label">Inactive</div>
<div class="stat-value">14</div>
<div class="stat-icon"><i class="bi bi-slash-circle-fill"></i></div>
</div>
<div class="stat-card blue">
<div class="stat-label">Companies</div>
<div class="stat-value">4</div>
<div class="stat-icon"><i class="bi bi-building-fill"></i></div>
</div>
</div>
<!-- ── Table Card ── -->
<div class="table-card">
<div class="table-card-header">
<h2><i class="bi bi-list-ul" style="margin-right:8px;opacity:.8"></i>List of Users</h2>
<div class="search-box">
<!-- Decoy that Chrome will autofill instead -->
<input type="text" style="display:none" autocomplete="username">
<input type="password" style="display:none" autocomplete="current-password">
<i class="bi bi-search" style="opacity:.7; font-size:13px;"></i>
<input type="search" name="user-search" placeholder="Search users..."
autocomplete="off" data-form-type="other"
oninput="filterTable(this.value)">
</div>
</div>
<div style="overflow-x:auto;">
<table id="UserListTable" class="um-table" cellspacing="0" width="100%">
<thead>
<tr>
<th style="width:100px;">Actions</th>
<th>Full Name</th>
<th>Username</th>
<th>Email</th>
<th>Company</th>
<th>Role</th>
<th>Status</th>
<th>Created By</th>
<th>Created Date</th>
<th>Updated By</th>
<th>Updated Date</th>
</tr>
</thead>
<tbody id="userTbody">
</tbody>
</table>
</div>
<div class="table-footer">
<span id="pageInfo">Showing 16 of 6 users</span>
<div class="pager">
<button class="pager-btn"><i class="bi bi-chevron-left" style="font-size:11px;"></i></button>
<button class="pager-btn active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn"><i class="bi bi-chevron-right" style="font-size:11px;"></i></button>
</div>
</div>
</div>
<!-- ══════════════════════════════════
MODAL: Create New User
══════════════════════════════════ -->
<div class="modal-overlay" id="modalCreate">
<div class="modal-box">
<div class="modal-head">
<h3><span class="icon-badge"><i class="bi bi-person-plus"></i></span>Create New User</h3>
<button class="modal-close" onclick="closeModal('modalCreate')"><i class="bi bi-x"></i></button>
</div>
<div class="modal-body">
<div class="form-row" id="userRegistrationForm">
<div><label class="form-label">Full Name</label><input id="fullName" class="form-input" type="text" placeholder="e.g. Juan dela Cruz"></div>
<div><label class="form-label">Username</label><input id="userName" class="form-input" type="text" placeholder="e.g. JDCRUZ25"></div>
</div>
<div class="form-row">
<div>
<label class="form-label">Company</label>
<select class="form-input" id="company">
<option value="LLI">LLI</option>
<option value="MDLD">MDLD</option>
<option value="EUROPRINT">EUROPRINT</option>
<option value="Traders">Traders</option>
<option value="India">India</option>
</select>
</div>
<div>
<label class="form-label">Department</label>
<select class="form-input" id="department">
<option>-- Select --</option>
</select>
<input type="hidden" id="departmentId" />
</div>
</div>
<div class="form-row">
<div>
<label class="form-label">Role</label>
<select class="form-input" id="role">
<option>-- Select --</option>
</select>
</div>
<div><label class="form-label">Email</label><input id="email" class="form-input" type="email" placeholder="user@lloydlab.com"></div>
</div>
<div class="form-group">
<label class="form-label">Password</label>
<input id="password" class="form-input" type="password" placeholder="Min. 8 characters">
</div>
</div>
<div class="modal-foot">
<button class="btn-secondary" onclick="closeModal('modalCreate')">Cancel</button>
<button class="btn-primary" onclick="addNewUser();"><i class="bi bi-person-check-fill" style="margin-right:6px;"></i>Register</button>
</div>
</div>
</div>
<!-- ══════════════════════════════════
MODAL: Update User Profile
══════════════════════════════════ -->
<div class="modal-overlay" id="modalProfile">
<div class="modal-box xl">
<div class="modal-head">
<h3><span class="icon-badge"><i class="bi bi-person-badge"></i></span>User Profile</h3>
<button class="modal-close" onclick="closeModal('modalProfile')"><i class="bi bi-x"></i></button>
</div>
<div class="profile-layout">
<!-- sidebar -->
<div class="profile-sidebar">
<div class="profile-avatar-lg" id="profileAvatarLg">CT</div>
<h4 id="profileSidebarName">Catherine S. Toronon</h4>
<span id="profileSidebarRole">Approver</span>
<div style="display:flex; gap:8px; margin-top:4px;">
<button style="padding:6px 12px; border-radius:var(--radius-sm); border:1px solid rgba(255,255,255,.2); background:rgba(255,255,255,.1); color:#fff; font-size:12px; cursor:pointer;">Follow</button>
<button style="padding:6px 12px; border-radius:var(--radius-sm); border:1px solid rgba(255,255,255,.2); background:rgba(255,255,255,.1); color:#fff; font-size:12px; cursor:pointer;">Message</button>
</div>
<nav class="profile-nav">
<a href="#" class="active"><i class="bi bi-ticket-perforated"></i> Ticket List</a>
<a href="#"><i class="bi bi-headset"></i> Support Staff</a>
<a href="#"><i class="bi bi-sliders"></i> Configurations</a>
</nav>
</div>
<!-- content tabs -->
<div class="profile-content">
<div class="um-tabs">
<div class="um-tab active" onclick="switchTab(this,'tabDetail')">Detail</div>
<div class="um-tab" onclick="switchTab(this,'tabProfile')">Profile</div>
<div class="um-tab" onclick="switchTab(this,'tabSettings')">Settings</div>
</div>
<div class="um-tab-pane active" id="tabDetail">
<div class="form-row">
<div><label class="form-label">Username</label><input class="form-input" type="text" value="LSCATTOR25" readonly></div>
<div><label class="form-label">Full Name</label><input class="form-input" type="text" value="Catherine S. Toronon"></div>
</div>
<div class="form-row">
<div>
<label class="form-label">Role</label>
<select class="form-input"><option selected>LLIApprover</option><option>LLIAdmin</option><option>Admin</option></select>
</div>
<div><label class="form-label">Email</label><input class="form-input" type="email" value="cstoronon@lloydlab.com"></div>
</div>
<div class="form-group">
<label class="form-label">New Password</label>
<input class="form-input" type="password" placeholder="Leave blank to keep current">
</div>
</div>
<div class="um-tab-pane" id="tabProfile">
<div class="form-group">
<label class="form-label">Address</label>
<input class="form-input" type="text" placeholder="Street address">
</div>
<div class="form-row">
<div><label class="form-label">Phone Number</label><input class="form-input" type="text" placeholder="+63"></div>
<div>
<label class="form-label">Company</label>
<select class="form-input"><option>LLI</option><option>MDLD</option><option>EUROPRINT</option><option>Traders</option></select>
</div>
</div>
<div>
<label class="form-label">Gender</label>
<div style="display:flex; gap:20px; margin-top:4px;">
<label style="display:flex;align-items:center;gap:6px;font-size:13.5px;cursor:pointer;"><input type="radio" name="gender" style="accent-color:var(--teal-600);"> Male</label>
<label style="display:flex;align-items:center;gap:6px;font-size:13.5px;cursor:pointer;"><input type="radio" name="gender" style="accent-color:var(--teal-600);"> Female</label>
</div>
</div>
</div>
<div class="um-tab-pane" id="tabSettings">
<div style="display:flex; align-items:center; justify-content:space-between; padding:14px 0; border-bottom:1px solid var(--border);">
<div>
<div style="font-size:13.5px; font-weight:500;">Account Lockout</div>
<div style="font-size:12px; color:var(--text-muted);">Prevent user from logging in</div>
</div>
<label style="position:relative; width:42px; height:24px; cursor:pointer;">
<input type="checkbox" id="lockoutToggle" style="opacity:0;width:0;height:0;" onchange="toggleSwitch(this)">
<span id="lockoutSwitchTrack" style="position:absolute;inset:0;border-radius:12px;background:var(--border);transition:background .2s;"></span>
<span id="lockoutSwitchThumb" style="position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:transform .2s;box-shadow:0 1px 3px rgba(0,0,0,.2);"></span>
</label>
</div>
</div>
<div style="margin-top:20px;">
<button class="btn-primary" onclick="showToast('Profile updated!'); closeModal('modalProfile')"><i class="bi bi-check2-circle" style="margin-right:6px;"></i>Save Changes</button>
</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════
MODAL: User Access Rights
══════════════════════════════════ -->
<div class="modal-overlay" id="modalAccess">
<div class="modal-box xl">
<div class="modal-head">
<h3 id="labelAddNewAccess"><span class="icon-badge"><i class="bi bi-shield-lock"></i></span></h3>
<button class="modal-close" onclick="closeModal('modalAccess')"><i class="bi bi-x"></i></button>
</div>
<div class="modal-body">
<div class="form-row" style="margin-bottom:20px;">
<div>
<label class="form-label">Full Name</label>
<input class="form-input" type="text" id="ua-FullName" readonly>
</div>
<div>
<label class="form-label">Email Address</label>
<input class="form-input" type="text" id="ua-EmailAddress" readonly>
</div>
</div>
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:12px;">
<div class="counter-pill"><i class="bi bi-check2-square"></i> Total Selected: <strong id="totalSelAccess">0</strong></div>
<button class="btn-create" id="btnAddAccess" style="font-size:13px; padding:8px 14px;" onclick="viewUserAccessNotExist()"><i class="bi bi-plus"></i> Add Access</button>
</div>
<table id="access-table" class="table-hover" style="width:100%;">
<thead>
<tr>
<th>
<input id="selectAllCheckboxAccess"
type="checkbox"
class="selectAllCheckboxAccess"
style="margin-right:6px;" />
All
</th>
<th>Page Type</th>
<th>Page Name</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class="modal-foot">
<button class="btn-secondary" onclick="closeModal('modalAccess')">Cancel</button>
<button class="btn-primary" onclick="postPutAccessRights(true); closeModal('modalAccess')"><i class="bi bi-shield-check" style="margin-right:6px;"></i>Save Rights</button>
</div>
</div>
</div>
<script>
$(document).ready(function () {
loader = $('#overlay, #loader');
populateRoles();
userListTable = $('#UserListTable').DataTable({
dom: 'lrtip',
ajax: $.extend({
url: '/Account/GetAllUsers',
type: 'GET',
}, beforeComplete(loader)),
columns: [
// [0] Action buttons
{
data: null,
render: function (data, type, row) {
return renderUserBtns(data, row);
}
},
// [1] Full Name — avatar + name
{
data: 'fullName',
render: function (data) {
if (!data) return '';
const initials = data.split(' ').filter(Boolean).slice(0, 2).map(w => w[0].toUpperCase()).join('');
const colors = ['', 'blue', 'amber', 'purple', 'coral'];
const colorClass = colors[data.charCodeAt(0) % colors.length];
return `<div class="user-cell">
<div class="avatar ${colorClass}">${initials}</div>
<div class="user-name">${data}</div>
</div>`;
}
},
// [2] Username
{ data: 'userName' },
// [3] Email
{ data: 'email' },
// [4] Company
{
data: 'company',
render: d => `<span class="badge-company">${d ?? ''}</span>`
},
// [5] Role
{
data: 'role',
render: d => `<span class="badge-role">${d ?? ''}</span>`
},
// [6] Status — from lockoutEnabled
{
data: 'lockoutEnabled',
render: function (data) {
const isActive = !data;
return `<span class="badge-status ${isActive ? 'active' : 'inactive'}">
<i class="bi bi-circle-fill" style="font-size:7px;"></i>
${isActive ? 'Active' : 'Inactive'}
</span>`;
}
},
// [7] Created By
{ data: 'createdBy' },
// [8] Created Date
{ data: 'createdDate', render: d => formatDate(d) },
// [9] Updated By
{ data: 'updatedBy' },
// [10] Updated Date
{ data: 'updatedDate', render: d => formatDate(d) },
],
language: { emptyTable: "No record available" },
rowCallback: rowAccountCallback,
responsive: true,
error: errorHandler,
initComplete: function () {
const table = this.api();
updateStatCards(table);
initCompleteCallback.call(this);
}
});
});
function filterTable(value) {
if (userListTable) {
userListTable.search(value).draw();
}
}
// ═══════════════════════════════════════════════════════
// Action buttons — rendered inside each DataTable row
// ═══════════════════════════════════════════════════════
function renderUserBtns(data, row) {
// Derive avatar values from live row data
const name = row.fullName ?? '';
const initials = name.split(' ').filter(Boolean).slice(0, 2).map(w => w[0].toUpperCase()).join('');
const colors = ['', 'blue', 'amber', 'purple', 'coral'];
const colorClass = name ? colors[name.charCodeAt(0) % colors.length] : '';
// Safely encode strings for onclick attributes
const safeName = name.replace(/'/g, "\\'");
const safeInitials = initials.replace(/'/g, "\\'");
const safeColor = colorClass.replace(/'/g, "\\'");
const safeRole = (row.role ?? '').replace(/'/g, "\\'");
const safeId = row.id ?? '';
// Encode full row as JSON — passed to viewUserAccess without many args
const jsonRow = encodeURIComponent(JSON.stringify(row));
let html = '<div class="action-wrap">';
// Edit / Profile button
html += `<button
class="action-btn edit"
title="Edit Profile"
onclick="openProfile('${safeName}','${safeInitials}','${safeColor}','${safeRole}','${safeId}')">
<i class="bi bi-pencil-square"></i>
</button>`;
// Access Rights button — calls your existing viewUserAccess with the full row
html += `<button
class="action-btn access"
title="Access Rights"
onclick="viewUserAccess(JSON.parse(decodeURIComponent('${jsonRow}')))">
<i class="bi bi-shield-lock"></i>
</button>`;
html += '</div>';
return html;
}
// ═══════════════════════════════════════════════════════
// Existing Access Rights functions
// Bootstrap modals — kept exactly as your original logic
// ═══════════════════════════════════════════════════════
function viewUserAccess(data) {
loader = $('#overlay, #loader');
isNotExist=1;
UserId = data.id;
document.getElementById('btnAddAccess').style.display='block';
document.getElementById('labelAddNewAccess').innerHTML='User Access Rights';
$('#ua-EmailAddress').val(data.email);
console.log('data.email',data.email);
$('#ua-FullName').val(data.fullName);
$('#uan-EmailAddress').val(data.email);
$('#uan-FullName').val(data.fullName);
openModal('modalAccess');
tableName = '#access-table';
totalSelectedLabel = $('#totalSelAccess');
clearTableSelection(tableName, selectedProductsMap, () => {
totalSelectedLabel.text(0);
}, 'selected-row', '.select-all-Access-checkbox');
tableElement = $(tableName);
tableDestroy(tableElement);
accessDataTable = tableElement.DataTable({
ajax: $.extend({
url: '/Account/GetUserRights',
type: 'GET',
data: { userId: UserId },
}, beforeComplete(loader)),
language: { emptyTable: "No record available" },
initComplete: function () {
initializeTableSelection({
tableName: tableName,
dataTable: accessDataTable,
selectedItemsMap: selectedProductsMap,
idKey: 'userAccessId',
idKey2: 'contAccId',
checkboxClass: '.select-Access-checkbox',
selectAllClass: '.select-all-Access-checkbox',
selectedRowClass: 'selected-row',
updateCountCallback: function () {
totalSelectedLabel.text(getSelectedCount(selectedProductsMap));
}
});
},
columns: [
{
data: 'userAccessId',
render: function () {
return '<input type="checkbox" class="select-Access-checkbox" />';
}
},
{ data: 'accessType' },
{ data: 'pageName' },
{ data: 'isActive' },
{
data: null,
render: function (data, type, row) {
return renderAccessDetailbtn(data, row);
}
}],
responsive: true,
error: errorHandler
});
}
function viewUserAccessNotExist() {
closeModal('modalAccess');
loader = $('#overlay, #loader');
document.getElementById('btnAddAccess').style.display='none';
document.getElementById('labelAddNewAccess').innerHTML='Add New Access Rights';
var submitButton = $('#btnNotAccess');
var totalSelectedLabel = $('#totalSelNotAccess');
var IsNotExist = true;
isNotExist=13;
openModal('modalAccess');
tableName = '#access-table';
totalSelectedLabel = $('#totalSelAccess');
clearTableSelection(tableName, selectedProductsMap, () => {
totalSelectedLabel.text(0);
}, 'selected-row', '.select-all-Access-checkbox');
tableElement = $(tableName);
tableDestroy(tableElement);
accessDataTable = tableElement.DataTable({
ajax: $.extend({
url: '/Account/GetUserRights',
type: 'GET',
data: { UserId, IsNotExist },
}, beforeComplete(loader)),
language: { emptyTable: "No record available" },
initComplete: function () {
initializeTableSelection({
tableName: tableName,
dataTable: accessDataTable,
selectedItemsMap: selectedProductsMap,
idKey: 'userAccessId',
idKey2: 'contAccId',
checkboxClass: '.select-Access-checkbox',
selectAllClass: '.select-all-Access-checkbox',
selectedRowClass: 'selected-row',
updateCountCallback: function () {
totalSelectedLabel.text(getSelectedCount(selectedProductsMap));
}
});
},
columns: [
{
data: 'userAccessId',
title: '<input type="checkbox" class="select-all-Access-checkbox" />',
render: function () {
return '<input type="checkbox" class="select-Access-checkbox" />';
},
orderable: false,
searchable: false
},
{ data: 'accessType' },
{ data: 'pageName' },
{ data: 'isActive' },
{
data: null,
render: function (data, type, row) {
return renderAccessDetailbtn(data, row);
}
}],
responsive: true,
error: errorHandler
});
}
// ═══════════════════════════════════════════════════════
// Profile modal
// ═══════════════════════════════════════════════════════
function openProfile(name, initials, color, role, userId) {
console.log('pasok naman? openProfile');
// Sidebar fields
const avatar = document.getElementById('profileAvatarLg');
if (avatar) {
avatar.textContent = initials;
avatar.style.background = color ? 'var(--teal-400)' : 'var(--teal-500)';
}
setContent('profileSidebarName', name);
setContent('profileSidebarRole', role);
// Pull matching row from DataTable and pre-fill every form field
if (userListTable && userId) {
userListTable.rows().every(function () {
const row = this.data();
if (String(row.id) === String(userId)) {
// Detail tab
setValue('UserName', row.userName);
setValue('FullName', row.fullName);
setValue('Email', row.email);
setValue('Password', ''); // never pre-fill password
setSelect('UserRole', row.role);
// Profile tab
setValue('Address', row.address);
setValue('PhoneNumber', row.phoneNumber);
setSelect('Company', row.company);
// Settings tab — lockout toggle
const lockCb = document.getElementById('lockoutToggle');
if (lockCb) {
lockCb.checked = row.lockoutEnabled;
toggleSwitch(lockCb);
}
// Profile picture
const img = document.getElementById('profilePictureImage');
if (img && row.url) img.src = '/' + row.url;
// Hidden fields your postPut reads
setValue('PFullName', row.fullName);
setValue('PUserRole', row.role);
}
});
}
openModal('modalProfile');
}
// ═══════════════════════════════════════════════════════
// Custom modal helpers (new UI overlay modals)
// ═══════════════════════════════════════════════════════
let departmentLoaded = false;
let roleLoaded = false;
function openModal(id) {
const el = document.getElementById(id);
if (!el) return;
el.classList.add('show');
if (id === 'modalCreate') {
if (!departmentLoaded) {
populateDepartment();
departmentLoaded = true;
}
if (!roleLoaded) {
populateRoles();
roleLoaded = true;
}
}
}
function closeModal(id) {
const el = document.getElementById(id);
if (el) el.classList.remove('show');
}
function shakeModal(overlayEl) {
const box = overlayEl.querySelector('.modal-box');
if (!box) return;
box.classList.remove('shake');
void box.offsetWidth; // force reflow to replay animation
box.classList.add('shake');
}
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.modal-overlay').forEach(overlay => {
let pressStartedOnOverlay = false;
// Track where the press STARTED
overlay.addEventListener('mousedown', (e) => {
pressStartedOnOverlay = (e.target === overlay);
});
// Only shake if BOTH press and release happened on the overlay
overlay.addEventListener('mouseup', (e) => {
if (pressStartedOnOverlay && e.target === overlay) {
shakeModal(overlay);
}
pressStartedOnOverlay = false;
});
});
// Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
const openOverlay = document.querySelector('.modal-overlay.show');
if (openOverlay) {
e.preventDefault();
shakeModal(openOverlay);
}
}
});
});
// Wire up backdrop-click + Escape blocking for every modal-overlay
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.modal-overlay').forEach(overlay => {
overlay.addEventListener('mousedown', (e) => {
// Only react if the click started on the overlay itself,
// not on the modal-box or its children
if (e.target === overlay) {
shakeModal(overlay);
}
});
});
// Block Escape from closing (Bootstrap keyboard:false equivalent)
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
const openOverlay = document.querySelector('.modal-overlay.show');
if (openOverlay) {
e.preventDefault();
shakeModal(openOverlay);
}
}
});
});
// Close on backdrop click
document.querySelectorAll('.modal-overlay').forEach(function (overlay) {
overlay.addEventListener('click', function (e) {
if (e.target === overlay) overlay.classList.remove('show');
});
});
// ═══════════════════════════════════════════════════════
// Profile modal — tab switching
// ═══════════════════════════════════════════════════════
function switchTab(el, target) {
document.querySelectorAll('.um-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.um-tab-pane').forEach(p => p.classList.remove('active'));
el.classList.add('active');
const pane = document.getElementById(target);
if (pane) pane.classList.add('active');
}
// ═══════════════════════════════════════════════════════
// Settings tab — lockout toggle switch
// ═══════════════════════════════════════════════════════
function toggleSwitch(cb) {
const track = document.getElementById('lockoutSwitchTrack');
const thumb = document.getElementById('lockoutSwitchThumb');
if (!track || !thumb) return;
if (cb.checked) {
track.style.background = 'var(--teal-600)';
thumb.style.transform = 'translateX(18px)';
} else {
track.style.background = 'var(--border)';
thumb.style.transform = 'translateX(0)';
}
}
// ═══════════════════════════════════════════════════════
// Toast notifications
// ═══════════════════════════════════════════════════════
function showToast(msg) {
closeModal('modalAccess');
viewUserAccessNotExist();
// const wrap = document.getElementById('toastWrap');
// if (!wrap) return;
// const t = document.createElement('div');
// t.className = 'toast';
// t.innerHTML = `<i class="bi bi-check-circle-fill" style="color:var(--teal-400);font-size:16px;"></i> ${msg}`;
// wrap.appendChild(t);
// setTimeout(() => t.remove(), 3200);
}
// ═══════════════════════════════════════════════════════
// Stat cards — updated from live DataTable data
// ═══════════════════════════════════════════════════════
function updateStatCards(api) {
try {
const rows = api.rows().data().toArray();
const total = rows.length;
const active = rows.filter(r => !r.lockoutEnabled).length;
const inactive = rows.filter(r => r.lockoutEnabled).length;
const companies = [...new Set(rows.map(r => r.company).filter(Boolean))].length;
const set = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; };
set('statTotal', total);
set('statActive', active);
set('statInactive', inactive);
set('statCompanies', companies);
} catch (e) {
console.warn('updateStatCards:', e);
}
}
// ═══════════════════════════════════════════════════════
// Shared helpers
// ═══════════════════════════════════════════════════════
function formatDate(data) {
if (!data) return '';
const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
const d = new Date(data);
return `${months[d.getMonth()]}/${d.getDate()}/${d.getFullYear()}`;
}
// Set input/select value safely
function setValue(id, val) {
const el = document.getElementById(id);
if (el) el.value = val ?? '';
}
// Set textContent (labels, spans) safely
function setContent(id, val) {
const el = document.getElementById(id);
if (el) el.textContent = val ?? '';
}
// Set a <select> to the matching option
function setSelect(id, val) {
const el = document.getElementById(id);
if (!el) return;
const opt = [...el.options].find(o => o.value === val);
if (opt) opt.selected = true;
}
</script>
</body>
<script src="~/jsfunctions/account/index.js"></script>
<script src="~/jsfunctions/account/AccountPostPut.js"></script>
<script src="~/jsfunctions/account/accountvar.js"></script>
<script src="~/jsfunctions/utilities/StylesV3.js"></script>
<script src="~/JsFunctions/Utilities/utilsV3.js"></script>
<script src="~/jsfunctions/utilities/NewStyle.js"></script>
<script src="~/jsfunctions/account/rowcallback.js"></script>
<script src="~/jsfunctions/account/accountcolumn.js"></script>