HR-ATS-Portal/js/settings.js

194 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* ============================================================
settings.js — Settings page with many tabs
============================================================ */
window.Views = window.Views || {};
window.Settings = {};
Views.settings = function () {
const tabs = ['General', 'Users', 'Roles', 'Permissions', 'Notifications', 'Email Templates', 'Career Portal', 'Branding', 'Security', 'Appearance'];
const html = `
<div class="page">
<div class="page-head">
<div><h1 class="page-title">Settings</h1><p class="page-sub">Configure your workspace and team preferences</p></div>
<div class="page-head-actions"><button class="btn btn-primary" onclick="UI.toast('Settings saved','success')">${UI.icon('check')} Save Changes</button></div>
</div>
<div class="tabs" id="setTabs">${tabs.map((t, i) => `<div class="tab ${i === 0 ? 'active' : ''}" data-tab="${i}">${t}</div>`).join('')}</div>
<div id="setPanes">
${tabs.map((t, i) => `<div class="tab-pane ${i === 0 ? 'active' : ''}" data-pane="${i}">${Settings.pane(t)}</div>`).join('')}
</div>
</div>`;
return {
html,
onMount() {
const panes = document.querySelectorAll('#setPanes .tab-pane');
document.querySelectorAll('#setTabs .tab').forEach(tab => tab.onclick = () => {
document.querySelectorAll('#setTabs .tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
panes.forEach(p => p.classList.remove('active'));
panes[+tab.dataset.tab].classList.add('active');
if (tab.textContent === 'Appearance') Settings._bindTheme();
});
Settings._bindTheme();
}
};
};
function toggleRow(title, desc, checked) {
return `<div class="setting-row"><div class="setting-info"><h4>${title}</h4><p>${desc}</p></div>
<label class="switch"><input type="checkbox" ${checked ? 'checked' : ''} onchange="UI.toast('Preference updated','success')"/><span class="switch-track"></span></label></div>`;
}
Settings.pane = function (name) {
if (name === 'General') {
return `<div class="card"><div class="card-body">
<div class="form-grid">
<div class="form-field"><label>Organization Name</label><input value="Utopia Brands Inc."/></div>
<div class="form-field"><label>Company Website</label><input value="https://utopiabrands.com"/></div>
<div class="form-field"><label>Industry</label><select><option>Consumer Goods</option><option>Technology</option><option>Retail</option></select></div>
<div class="form-field"><label>Company Size</label><select><option>201500</option><option>51200</option><option>500+</option></select></div>
<div class="form-field"><label>Default Time Zone</label><select><option>(GMT-08:00) Pacific Time</option><option>(GMT-05:00) Eastern Time</option><option>(GMT+00:00) UTC</option></select></div>
<div class="form-field"><label>Default Currency</label><select><option>USD ($)</option><option>EUR (€)</option><option>GBP (£)</option></select></div>
</div>
<div class="divider"></div>
${toggleRow('Auto-archive stale jobs', 'Automatically close requisitions inactive for 90 days', true)}
${toggleRow('Duplicate detection', 'Flag candidates that already exist in the system', true)}
</div></div>`;
}
if (name === 'Users') {
const rows = DB.users.map(u => `<tr>
<td><div class="user-cell">${UI.avatar(u.name, u.initials, u.color)}<div><div class="cell-primary">${u.name}</div><div class="cell-sub">${u.email}</div></div></div></td>
<td>${UI.badge(u.role, 'b-indigo')}</td>
<td>${UI.badge(u.status)}</td>
<td class="text-muted">${u.lastActive}</td>
<td style="text-align:right"><div class="row-actions"><button class="act-btn" onclick="UI.toast('Editing ${u.name}','info')">${UI.icon('edit')}</button><button class="act-btn danger" onclick="UI.toast('User removed','success')">${UI.icon('trash')}</button></div></td>
</tr>`).join('');
return `<div class="card">
<div class="card-head"><div><h3>Team Members</h3><span class="ch-sub">${DB.users.length} users</span></div>
<button class="btn btn-primary btn-sm" onclick="UI.toast('Invite sent','success')">${UI.icon('plus')} Invite User</button></div>
<div class="table-wrap"><table class="data"><thead><tr><th>User</th><th>Role</th><th>Status</th><th>Last Active</th><th style="text-align:right">Actions</th></tr></thead><tbody>${rows}</tbody></table></div>
</div>`;
}
if (name === 'Roles') {
return `<div class="card"><div class="card-head"><div><h3>Roles</h3><span class="ch-sub">Define access levels</span></div>
<button class="btn btn-primary btn-sm" onclick="UI.toast('New role dialog','info')">${UI.icon('plus')} Add Role</button></div>
<div class="card-body"><div class="list-tight">
${DB.roles.map(r => `<div class="list-row">
<span class="kpi-icn i-purple" style="width:40px;height:40px;border-radius:11px">${UI.icon('users')}</span>
<div class="lr-main"><div class="lr-title">${r.name}</div><div class="lr-sub">${r.desc}</div></div>
<div class="lr-right"><div class="fw-600">${r.users} users</div><div class="lr-sub">${r.perms}</div></div>
<button class="act-btn" onclick="UI.toast('Editing ${r.name} role','info')">${UI.icon('edit')}</button>
</div>`).join('')}
</div></div></div>`;
}
if (name === 'Permissions') {
const modules = ['Jobs', 'Candidates', 'Interviews', 'Offers', 'Reports', 'Settings'];
const perms = ['View', 'Create', 'Edit', 'Delete'];
return `<div class="card"><div class="card-head"><div><h3>Permission Matrix</h3><span class="ch-sub">Recruiter role</span></div>
<select class="select"><option>Recruiter</option><option>Hiring Manager</option><option>Administrator</option></select></div>
<div class="table-wrap"><table class="data"><thead><tr><th>Module</th>${perms.map(p => `<th style="text-align:center">${p}</th>`).join('')}</tr></thead>
<tbody>${modules.map(m => `<tr><td class="cell-primary">${m}</td>${perms.map((p, i) => `<td style="text-align:center">
<label class="switch"><input type="checkbox" ${(i < 3 || m !== 'Settings') && !(m === 'Settings') ? 'checked' : ''} onchange="UI.toast('Permission updated','success')"/><span class="switch-track"></span></label></td>`).join('')}</tr>`).join('')}</tbody></table></div>
</div>`;
}
if (name === 'Notifications') {
return `<div class="card"><div class="card-body">
<div class="form-section-title" style="margin-top:0">Email Notifications</div>
${toggleRow('New applications', 'Get notified when a candidate applies', true)}
${toggleRow('Interview reminders', 'Reminders 30 minutes before interviews', true)}
${toggleRow('Offer responses', 'When candidates accept or decline offers', true)}
${toggleRow('Weekly digest', 'A summary of hiring activity every Monday', false)}
<div class="form-section-title">In-App Notifications</div>
${toggleRow('Mentions', 'When a teammate @mentions you', true)}
${toggleRow('Stage changes', 'When a candidate moves stages', false)}
${toggleRow('Task assignments', 'When you are assigned a task', true)}
</div></div>`;
}
if (name === 'Email Templates') {
const templates = ['Application Received', 'Interview Invitation', 'Assessment Assignment', 'Offer Letter', 'Rejection — Post Interview', 'Reference Request'];
return `<div class="card"><div class="card-head"><div><h3>Email Templates</h3></div>
<button class="btn btn-primary btn-sm" onclick="UI.toast('New template','info')">${UI.icon('plus')} New Template</button></div>
<div class="card-body"><div class="list-tight">
${templates.map(t => `<div class="list-row"><span class="kpi-icn i-blue" style="width:38px;height:38px;border-radius:10px">${UI.icon('mail')}</span>
<div class="lr-main"><div class="lr-title">${t}</div><div class="lr-sub">Last edited 3 days ago</div></div>
${UI.badge('Active', 'b-green')}<button class="act-btn" onclick="UI.toast('Editing template','info')">${UI.icon('edit')}</button></div>`).join('')}
</div></div></div>`;
}
if (name === 'Career Portal') {
return `<div class="card"><div class="card-body">
<div class="form-grid">
<div class="form-field col-span-2"><label>Careers Page URL</label><input value="https://careers.utopiabrands.com"/></div>
<div class="form-field"><label>Page Headline</label><input value="Build the future with us"/></div>
<div class="form-field"><label>Primary CTA Text</label><input value="View Open Roles"/></div>
</div>
<div class="divider"></div>
${toggleRow('Public job board', 'Make open roles visible to the public', true)}
${toggleRow('Allow one-click apply', 'Let candidates apply with LinkedIn', true)}
${toggleRow('Show salary ranges', 'Display compensation on job listings', false)}
${toggleRow('Enable referrals', 'Employees can refer candidates', true)}
</div></div>`;
}
if (name === 'Branding') {
return `<div class="card"><div class="card-body">
<div class="setting-row"><div class="setting-info"><h4>Company Logo</h4><p>Displayed on career pages and emails</p></div>
<div class="flex items-center gap-12"><span class="brand-logo" style="width:48px;height:48px">UB</span><button class="btn btn-secondary btn-sm" onclick="UI.toast('Upload dialog','info')">Upload</button></div></div>
<div class="setting-row"><div class="setting-info"><h4>Brand Color</h4><p>Primary accent across the portal</p></div>
<div class="flex items-center gap-8">
${['#004d43', '#ceff71', '#25e9a5', '#8e92ff', '#1a3134', '#eafff4'].map(c => `<span style="width:28px;height:28px;border-radius:8px;background:${c};cursor:pointer;border:2px solid var(--border)" onclick="UI.toast('Brand color updated','success')"></span>`).join('')}
</div></div>
<div class="form-grid" style="margin-top:16px">
<div class="form-field"><label>Email Footer</label><input value="Utopia Brands · San Francisco, CA"/></div>
<div class="form-field"><label>Support Email</label><input value="talent@utopiabrands.com"/></div>
</div>
</div></div>`;
}
if (name === 'Security') {
return `<div class="card"><div class="card-body">
${toggleRow('Two-factor authentication', 'Require 2FA for all team members', true)}
${toggleRow('Single Sign-On (SSO)', 'Enable SAML-based SSO login', false)}
${toggleRow('IP allowlist', 'Restrict access to approved IP ranges', false)}
${toggleRow('Audit logging', 'Track all data access and changes', true)}
<div class="form-grid" style="margin-top:16px">
<div class="form-field"><label>Session Timeout</label><select><option>30 minutes</option><option>1 hour</option><option>8 hours</option></select></div>
<div class="form-field"><label>Password Policy</label><select><option>Strong (12+ chars)</option><option>Medium (8+ chars)</option></select></div>
</div>
<div class="divider"></div>
<div class="setting-row"><div class="setting-info"><h4>Data Retention</h4><p>Auto-delete candidate data after set period</p></div>
<select class="select"><option>24 months</option><option>12 months</option><option>36 months</option></select></div>
</div></div>`;
}
if (name === 'Appearance') {
return `<div class="card"><div class="card-body">
<div class="form-section-title" style="margin-top:0">Theme</div>
<div class="grid g-3" style="margin-bottom:8px">
<div class="card theme-opt" data-theme-set="light" style="cursor:pointer;overflow:hidden">
<div style="height:80px;background:#f1f7f4;border-bottom:1px solid var(--border);display:flex"><div style="width:30%;background:#1a3134"></div><div style="flex:1;padding:10px"><div style="height:8px;background:#fff;border-radius:4px;margin-bottom:6px"></div><div style="height:8px;width:45%;background:#004d43;border-radius:4px"></div></div></div>
<div class="card-body" style="padding:12px"><div class="fw-600">Light</div><div class="lr-sub">Clean and bright</div></div>
</div>
<div class="card theme-opt" data-theme-set="dark" style="cursor:pointer;overflow:hidden">
<div style="height:80px;background:#0e1d1f;border-bottom:1px solid var(--border);display:flex"><div style="width:30%;background:#0a1618"></div><div style="flex:1;padding:10px"><div style="height:8px;background:#24403f;border-radius:4px;margin-bottom:6px"></div><div style="height:8px;width:45%;background:#ceff71;border-radius:4px"></div></div></div>
<div class="card-body" style="padding:12px"><div class="fw-600">Dark</div><div class="lr-sub">Easy on the eyes</div></div>
</div>
<div class="card theme-opt" data-theme-set="system" style="cursor:pointer;overflow:hidden">
<div style="height:80px;background:linear-gradient(90deg,#f1f7f4 50%,#0e1d1f 50%);border-bottom:1px solid var(--border)"></div>
<div class="card-body" style="padding:12px"><div class="fw-600">System</div><div class="lr-sub">Match OS setting</div></div>
</div>
</div>
<div class="divider"></div>
${toggleRow('Compact mode', 'Reduce spacing for denser layouts', false)}
${toggleRow('Show animations', 'Enable transitions and motion', true)}
</div></div>`;
}
return '';
};
Settings._bindTheme = function () {
document.querySelectorAll('.theme-opt').forEach(opt => opt.onclick = () => {
const mode = opt.dataset.themeSet;
if (mode === 'system') { App.setTheme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); }
else App.setTheme(mode);
UI.toast('Theme updated to ' + mode, 'success');
});
};