337 lines
21 KiB
HTML
337 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>Settings | 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" id="appSidebar"></aside>
|
||
|
||
<div class="main-wrapper">
|
||
<header class="topbar">
|
||
<div class="topbar-left"><div class="topbar-title">System Settings</div></div>
|
||
<div class="topbar-actions">
|
||
<button class="btn btn-primary btn-sm" id="saveSettingsBtn" onclick="saveSettings()">💾 Save All Settings</button>
|
||
<a href="index.html" class="icon-btn" title="Logout"><i data-lucide="log-out"></i></a>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="content">
|
||
<div style="display:grid;grid-template-columns:220px 1fr;gap:20px;align-items:start">
|
||
<!-- Settings Sidebar -->
|
||
<div class="card p-4">
|
||
<div style="font-size:11.5px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.6px;margin-bottom:12px">Settings</div>
|
||
<nav id="settingsNav"></nav>
|
||
</div>
|
||
|
||
<!-- Settings Content -->
|
||
<div id="settingsContent"></div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast-container" id="toastContainer"></div>
|
||
<script src="https://unpkg.com/lucide@latest"></script>
|
||
<script src="js/data.js"></script>
|
||
<script src="js/sidebar.js"></script>
|
||
<script src="js/app.js"></script>
|
||
<script>
|
||
const sections = [
|
||
{ id:'general', icon:'🏢', label:'Organization' },
|
||
{ id:'appearance', icon:'🎨', label:'Appearance' },
|
||
{ id:'depreciation',icon:'💰', label:'Depreciation' },
|
||
{ id:'notifications',icon:'🔔',label:'Notifications' },
|
||
{ id:'email', icon:'📧', label:'Email / SMTP' },
|
||
{ id:'backup', icon:'💾', label:'Backup & Export' },
|
||
{ id:'security', icon:'🔐', label:'Security & 2FA' },
|
||
{ id:'integrations',icon:'🔗', label:'Integrations' }
|
||
];
|
||
|
||
const settingsHTML = {
|
||
general: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">🏢 Organization Settings</span></div>
|
||
<div class="card-body">
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Company Name <span class="req">*</span></label><input class="form-input" id="setCompanyName" value="${AMS ? AMS.company.name : 'Acme Corporation Pvt. Ltd.'}"></div>
|
||
<div class="form-group"><label class="form-label">Company Logo</label><div class="flex items-center gap-3"><div style="width:48px;height:48px;border-radius:var(--radius-md);background:var(--primary-glow);display:flex;align-items:center;justify-content:center;font-size:22px">📦</div><button class="btn btn-secondary btn-sm" onclick="showToast('Upload','Logo upload dialog','info')">Change Logo</button></div></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Currency</label><select class="form-select" id="setCurrency"><option selected>INR (₹)</option><option>USD ($)</option><option>EUR (€)</option><option>GBP (£)</option></select></div>
|
||
<div class="form-group"><label class="form-label">Financial Year</label><select class="form-select"><option selected>April – March</option><option>January – December</option><option>July – June</option></select></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Date Format</label><select class="form-select"><option selected>DD-MMM-YYYY</option><option>DD/MM/YYYY</option><option>MM/DD/YYYY</option><option>YYYY-MM-DD</option></select></div>
|
||
<div class="form-group"><label class="form-label">Timezone</label><select class="form-select"><option selected>Asia/Kolkata (IST +5:30)</option><option>UTC</option><option>America/New_York</option></select></div>
|
||
</div>
|
||
<div class="form-group"><label class="form-label">Registered Address</label><textarea class="form-textarea" id="setAddress" rows="2">${AMS ? AMS.company.address : ''}</textarea></div>
|
||
<div class="form-group"><label class="form-label">GST Number</label><input class="form-input" id="setGst" value="${AMS ? AMS.company.gst : ''}"></div>
|
||
<div class="form-group"><label class="form-label">Asset ID Prefix</label><input class="form-input" value="AST" placeholder="e.g. AST, ACME, ITL"><div class="form-hint">IDs will be generated as: <code style="color:var(--primary-light)">AST-2025-001</code></div></div>
|
||
</div>
|
||
</div>`,
|
||
|
||
appearance: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">🎨 Appearance</span></div>
|
||
<div class="card-body">
|
||
<div class="form-group">
|
||
<label class="form-label">Theme</label>
|
||
<div class="flex gap-3 mt-2">
|
||
<label class="theme-opt" data-theme-opt="light" onclick="setTheme('light')"><div class="theme-swatch light"></div><span>Light (Default)</span></label>
|
||
<label class="theme-opt" data-theme-opt="dark" onclick="setTheme('dark')"><div class="theme-swatch dark"></div><span>Dark</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group mt-4">
|
||
<label class="form-label">Accent Color</label>
|
||
<div class="flex gap-3 mt-2 flex-wrap">
|
||
${['#6366F1','#06B6D4','#10B981','#F59E0B','#EF4444','#A855F7'].map((c,i)=>`
|
||
<button onclick="setAccent('${c}')" style="width:36px;height:36px;border-radius:50%;background:${c};border:${i===0?'3px solid #fff':'2px solid transparent'};cursor:pointer;transition:var(--t)" title="${c}"></button>`).join('')}
|
||
</div>
|
||
</div>
|
||
<div class="form-group mt-4">
|
||
<label class="form-label">Sidebar Style</label>
|
||
<select class="form-select"><option>Compact (Default)</option><option>Wide</option><option>Collapsed</option></select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label">Table Density</label>
|
||
<select class="form-select"><option>Comfortable (Default)</option><option>Compact</option><option>Spacious</option></select>
|
||
</div>
|
||
</div>
|
||
</div>`,
|
||
|
||
depreciation: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">💰 Depreciation Defaults</span></div>
|
||
<div class="card-body">
|
||
<div class="alert alert-info mb-4">
|
||
<div class="alert-icon">ℹ️</div>
|
||
<div><div class="alert-title">These are default values applied when creating new assets</div><div class="alert-text">Each asset can override these per category settings.</div></div>
|
||
</div>
|
||
<div class="form-group"><label class="form-label">Default Depreciation Method</label>
|
||
<select class="form-select"><option selected>SLM – Straight Line Method (as per Companies Act)</option><option>WDV – Written Down Value</option></select>
|
||
</div>
|
||
<hr class="divider">
|
||
<div class="section-hdr">Category-wise Default Rates</div>
|
||
<table class="data-table" style="font-size:12.5px">
|
||
<thead><tr><th>Category</th><th>Default Method</th><th>Rate (% p.a.)</th><th>Useful Life (Years)</th></tr></thead>
|
||
<tbody>
|
||
${AMS.categories.map(c=>`<tr data-cat="${c.id}">
|
||
<td>${c.icon} ${c.name}</td>
|
||
<td><select class="form-select cat-depM" style="padding:4px 8px;font-size:11px"><option ${c.depM==='SLM'?'selected':''}>SLM</option><option ${c.depM==='WDV'?'selected':''}>WDV</option></select></td>
|
||
<td><input type="number" class="form-input cat-depR" value="${c.depR}" style="width:70px;padding:4px 8px">%</td>
|
||
<td><input type="number" class="form-input cat-life" value="${c.life}" style="width:70px;padding:4px 8px"> yr</td>
|
||
</tr>`).join('')}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>`,
|
||
|
||
notifications: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">🔔 Notification Preferences</span></div>
|
||
<div class="card-body">
|
||
<div class="section-hdr">Warranty Alerts</div>
|
||
${notifRow('Warranty expiry alert',true,'Send email 90 / 60 / 30 days before expiry')}
|
||
${notifRow('Warranty expired',true,'Immediate alert when warranty expires')}
|
||
<hr class="divider">
|
||
<div class="section-hdr">Maintenance Alerts</div>
|
||
${notifRow('PM due reminder',true,'7 days before scheduled PM')}
|
||
${notifRow('PM overdue',true,'Daily reminders for overdue PMs')}
|
||
${notifRow('Ticket assigned to me',true,'When a ticket is assigned to you')}
|
||
${notifRow('Ticket status change',false,'When status changes on your tickets')}
|
||
<hr class="divider">
|
||
<div class="section-hdr">Procurement Alerts</div>
|
||
${notifRow('PR requires my approval',true,'When a PR is sent to you for approval')}
|
||
${notifRow('PR approved / rejected',true,'When your PR is actioned')}
|
||
${notifRow('PO delivery due',false,'3 days before expected delivery date')}
|
||
<hr class="divider">
|
||
<div class="section-hdr">System Alerts</div>
|
||
${notifRow('Low stock threshold reached',true,'When any category falls below minimum')}
|
||
${notifRow('AMC expiry reminder',true,'30 days before AMC contract expires')}
|
||
${notifRow('Audit schedule reminder',false,'Quarterly audit schedule reminders')}
|
||
</div>
|
||
</div>`,
|
||
|
||
email: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">📧 Email / SMTP Configuration</span></div>
|
||
<div class="card-body">
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">SMTP Host</label><input class="form-input" value="smtp.acmecorp.com"></div>
|
||
<div class="form-group"><label class="form-label">SMTP Port</label><input class="form-input" value="587"></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Username</label><input class="form-input" value="ams@acmecorp.com"></div>
|
||
<div class="form-group"><label class="form-label">Password</label><input type="password" class="form-input" value="•••••••••••••••"></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Sender Name</label><input class="form-input" value="AMS – Acme Corporation"></div>
|
||
<div class="form-group"><label class="form-label">Encryption</label><select class="form-select"><option selected>STARTTLS</option><option>SSL/TLS</option><option>None</option></select></div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Test Recipient</label><input type="email" class="form-input" placeholder="Send test email to…"></div>
|
||
<div class="form-group" style="display:flex;align-items:flex-end"><button class="btn btn-secondary w-full" onclick="testEmail()">📧 Send Test Email</button></div>
|
||
</div>
|
||
</div>
|
||
</div>`,
|
||
|
||
backup: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">💾 Backup & Data Export</span></div>
|
||
<div class="card-body">
|
||
<div class="section-hdr">Automated Backup</div>
|
||
<div class="form-group"><label class="form-label">Backup Frequency</label><select class="form-select"><option selected>Daily (2:00 AM IST)</option><option>Weekly</option><option>Monthly</option><option>Disabled</option></select></div>
|
||
<div class="form-group"><label class="form-label">Backup Location</label><select class="form-select"><option selected>AWS S3 – ap-south-1</option><option>Google Cloud Storage</option><option>Local Server</option><option>SFTP</option></select></div>
|
||
<div class="form-group"><label class="form-label">Retention Period</label><select class="form-select"><option>30 days</option><option selected>90 days</option><option>1 year</option></select></div>
|
||
<hr class="divider">
|
||
<div class="section-hdr">Manual Export</div>
|
||
<div class="flex gap-3 flex-wrap">
|
||
<button class="btn btn-secondary" onclick="showToast('Export','Exporting full asset database to JSON…','info')">📤 Export Database (JSON)</button>
|
||
<button class="btn btn-secondary" onclick="showToast('Export','Exporting asset register to CSV…','info')">📊 Export Asset Register (CSV)</button>
|
||
<button class="btn btn-secondary" onclick="showToast('Export','Generating audit report PDF…','info')">📄 Export Audit Report (PDF)</button>
|
||
</div>
|
||
<hr class="divider">
|
||
<div class="section-hdr">Import</div>
|
||
<div class="alert alert-warning mb-3"><div class="alert-icon">⚠️</div><div><div class="alert-title">Bulk import may overwrite existing records</div><div class="alert-text">Always take a backup before bulk importing data.</div></div></div>
|
||
<div class="flex gap-3">
|
||
<label class="btn btn-secondary" for="importFile">📥 Import Assets (CSV)</label>
|
||
<input type="file" id="importFile" accept=".csv" style="display:none" onchange="handleImport()">
|
||
<button class="btn btn-ghost btn-sm" onclick="downloadTemplate()">📋 Download Template</button>
|
||
</div>
|
||
</div>
|
||
</div>`,
|
||
|
||
security: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">🔐 Security Settings</span></div>
|
||
<div class="card-body">
|
||
<div class="section-hdr">Two-Factor Authentication</div>
|
||
<div class="flex items-center justify-between mb-4 p-4 bg-elevated rounded-md border">
|
||
<div><div style="font-weight:600">Enforce 2FA for all users</div><div style="font-size:12.5px;color:var(--text-muted)">All users will be required to set up 2FA on next login</div></div>
|
||
<label class="toggle"><input type="checkbox" checked><span class="toggle-slider"></span></label>
|
||
</div>
|
||
<div class="flex items-center justify-between mb-4 p-4 bg-elevated rounded-md border">
|
||
<div><div style="font-weight:600">2FA for Admin roles only</div><div style="font-size:12.5px;color:var(--text-muted)">Only Asset Managers and Super Admins require 2FA</div></div>
|
||
<label class="toggle"><input type="checkbox"><span class="toggle-slider"></span></label>
|
||
</div>
|
||
<hr class="divider">
|
||
<div class="section-hdr">Session Policy</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Session Timeout</label><select class="form-select"><option>30 minutes</option><option selected>1 hour</option><option>4 hours</option><option>8 hours</option><option>No timeout</option></select></div>
|
||
<div class="form-group"><label class="form-label">Max Concurrent Sessions</label><select class="form-select"><option>1</option><option selected>3</option><option>5</option><option>Unlimited</option></select></div>
|
||
</div>
|
||
<div class="form-group"><label class="form-label">IP Whitelist (optional)</label><textarea class="form-textarea" rows="2" placeholder="Enter allowed IP ranges, one per line. e.g. 192.168.1.0/24"></textarea></div>
|
||
<hr class="divider">
|
||
<div class="section-hdr">Password Policy</div>
|
||
<div class="form-row">
|
||
<div class="form-group"><label class="form-label">Minimum Length</label><input type="number" class="form-input" value="10" min="8"></div>
|
||
<div class="form-group"><label class="form-label">Expire After</label><select class="form-select"><option>Never</option><option selected>90 days</option><option>180 days</option><option>1 year</option></select></div>
|
||
</div>
|
||
</div>
|
||
</div>`,
|
||
|
||
integrations: `
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-title">🔗 Integrations</span></div>
|
||
<div class="card-body">
|
||
${integrationCard('Microsoft Active Directory / Azure AD','🔷','SSO via Microsoft OAuth 2.0. Sync users from AD groups.','Connected','Connected · 10 users synced')}
|
||
${integrationCard('Tally ERP / Zoho Books','📊','Auto-sync asset depreciation and financial data to accounting.','Connect','Not Connected')}
|
||
${integrationCard('JIRA / ServiceNow','🎫','Create and sync support tickets with your ITSM tool.','Connect','Not Connected')}
|
||
${integrationCard('Slack / Microsoft Teams','💬','Send alerts, notifications, and approvals to Slack/Teams channels.','Connect','Not Connected')}
|
||
${integrationCard('ERP System (SAP / Oracle)','🏭','Bi-directional sync with enterprise ERP for procurement data.','Connect','Not Connected')}
|
||
${integrationCard('Webhooks (Custom)','⚡','Send real-time events to your own systems via HTTP webhooks.','Configure','1 webhook active')}
|
||
</div>
|
||
</div>`
|
||
};
|
||
|
||
function notifRow(label, def, desc) {
|
||
return `<div class="flex items-center gap-3 mb-4" style="padding:12px;background:var(--bg-surface);border-radius:var(--radius-md);border:1px solid var(--border)">
|
||
<label class="toggle"><input type="checkbox" ${def?'checked':''}><span class="toggle-slider"></span></label>
|
||
<div style="flex:1"><div style="font-weight:600;font-size:13px">${label}</div><div style="font-size:11.5px;color:var(--text-muted)">${desc}</div></div>
|
||
</div>`;
|
||
}
|
||
|
||
function integrationCard(name, icon, desc, btnLabel, status) {
|
||
const connected = status.toLowerCase().includes('connected') || status.includes('active');
|
||
return `<div class="flex items-center gap-4 mb-4 p-4" style="background:var(--bg-surface);border-radius:var(--radius-md);border:1px solid var(--border)">
|
||
<div style="width:42px;height:42px;border-radius:10px;background:var(--bg-elevated);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0">${icon}</div>
|
||
<div style="flex:1">
|
||
<div style="font-weight:700;font-size:13.5px">${name}</div>
|
||
<div style="font-size:12px;color:var(--text-muted);margin-bottom:4px">${desc}</div>
|
||
<div style="font-size:11px;color:${connected?'var(--success)':'var(--text-muted)'}">${status}</div>
|
||
</div>
|
||
<button class="btn ${connected?'btn-ghost':'btn-secondary'} btn-sm" onclick="showToast('Integration','${name} integration dialog opening…','info')">${btnLabel}</button>
|
||
</div>`;
|
||
}
|
||
|
||
let activeSect = 'general';
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
renderSettingsNav();
|
||
loadSection('general');
|
||
AMS.categories.forEach(c => {/* pre-load */});
|
||
});
|
||
|
||
function renderSettingsNav() {
|
||
document.getElementById('settingsNav').innerHTML = sections.map(s=>`
|
||
<div class="settings-nav-item ${s.id===activeSect?'active':''}" id="snav-${s.id}" onclick="loadSection('${s.id}')">
|
||
<span style="font-size:15px">${s.icon}</span>
|
||
<span>${s.label}</span>
|
||
</div>`).join('');
|
||
}
|
||
|
||
function loadSection(id) {
|
||
activeSect = id;
|
||
document.querySelectorAll('.settings-nav-item').forEach(el=>el.classList.remove('active'));
|
||
const el=document.getElementById('snav-'+id);
|
||
if(el)el.classList.add('active');
|
||
document.getElementById('settingsContent').innerHTML = settingsHTML[id] || `<div class="card"><div class="card-body">${id} settings</div></div>`;
|
||
if (typeof updateThemeUI === 'function') updateThemeUI();
|
||
}
|
||
|
||
function saveSettings() {
|
||
if (window.AMS) {
|
||
// Persist General (organization) settings if that section is rendered
|
||
const nameEl = document.getElementById('setCompanyName');
|
||
if (nameEl) {
|
||
AMS.company.name = nameEl.value.trim() || AMS.company.name;
|
||
const addr = document.getElementById('setAddress');
|
||
const gst = document.getElementById('setGst');
|
||
if (addr) AMS.company.address = addr.value.trim();
|
||
if (gst) AMS.company.gst = gst.value.trim();
|
||
const cur = document.getElementById('setCurrency');
|
||
if (cur) {
|
||
const map = { 'INR (₹)':['₹','INR'], 'USD ($)':['$','USD'], 'EUR (€)':['€','EUR'], 'GBP (£)':['£','GBP'] };
|
||
const [sym, code] = map[cur.value] || ['₹','INR'];
|
||
AMS.company.currency = sym; AMS.company.currencyCode = code;
|
||
}
|
||
}
|
||
// Persist Depreciation category defaults if that section is rendered
|
||
document.querySelectorAll('tr[data-cat]').forEach(tr => {
|
||
const cat = AMS.categories.find(c => c.id === tr.dataset.cat);
|
||
if (!cat) return;
|
||
const depM = tr.querySelector('.cat-depM');
|
||
const depR = tr.querySelector('.cat-depR');
|
||
const life = tr.querySelector('.cat-life');
|
||
if (depM) cat.depM = depM.value;
|
||
if (depR) cat.depR = parseInt(depR.value, 10) || cat.depR;
|
||
if (life) cat.life = parseInt(life.value, 10) || cat.life;
|
||
});
|
||
AMS.save();
|
||
}
|
||
document.getElementById('saveSettingsBtn').textContent = '✅ Saved!';
|
||
showToast('Settings Saved','All configuration changes have been applied','success');
|
||
setTimeout(()=>{ document.getElementById('saveSettingsBtn').textContent = '💾 Save All Settings'; },2500);
|
||
}
|
||
|
||
function testEmail() { showToast('Test Email Sent','Check your inbox for the test email','success'); }
|
||
function handleImport() { showToast('Import Started','Validating CSV file…','info'); }
|
||
function downloadTemplate() { showToast('Template Downloaded','CSV import template downloaded','success'); }
|
||
function setAccent(color) { showToast('Theme Updated',`Accent color changed to ${color}`,'success'); }
|
||
</script>
|
||
</body>
|
||
</html>
|