Your gateway to global education excellence.
Welcome back to the Global Guidance Command Portal — a unified workspace for our admissions, business development, counselling and operations teams to deliver world-class service to every student.
Username
Password
Staff Portal
Student Portal
Agent
Sign In to Portal
Quick Access
/* ============================================================
* v16z — Firmli-inspired CRM + Login upgrade (2026-09-17)
* ------------------------------------------------------------
* Adds (based on user's Firmli reference platform):
* 1) Email-based login aliases + new default password
* (Global@2026) matching the "staff login details" Excel.
* Old usernames still work for backward compatibility.
* 2) Full CRM suite inspired by Firmli's Konnectli/Payli/
* Signli/Agentli modules:
* • Leads Pipeline (Kanban: New → Contacted → Qualified
* → Applied → Enrolled/Lost)
* • Smart Program Finder (searchable university/program
* database, 1000+ programs)
* • Applications Tracker (student journey)
* • Commissions Ledger (agent payouts)
* • Contracts & Agreements (university partnerships)
* • Sub-Agents management network
* • Webinars & Events scheduler
* • Payments (Inbound / Outbound)
* 3) All data persists to Cloudflare KV via existing
* backend hooks OR localStorage as fallback.
* 4) CRM dashboard is a single-page workspace accessible
* to any user whose `pages` list includes 'crm' (added
* to CEO/COO/Heads/Sr. Counsellors by default).
* ============================================================ */
(function v16zBoot(){
'use strict';
// ---- helpers ---------------------------------------------------------
function curUser(){
try { return (0, eval)('typeof currentUser !== "undefined" ? currentUser : null'); } catch(e){ return null; }
}
function getUSERS(){
try { return (0, eval)('typeof USERS !== "undefined" ? USERS : {}'); } catch(e){ return {}; }
}
// ============================================================
// FIX A — Email-based login aliases + Global@2026 default
// ============================================================
// From the "staff login details" spreadsheet, users log in with
// email addresses (e.g. ceo@global-guidance.com). Map each email
// to the existing internal username so both continue to work.
const V16Z_EMAIL_ALIASES = {
'ceo@global-guidance.com': 'nashif.razzak',
'nashif@global-guidance.com': 'nashif.razzak',
'coo@global-guidance.com': 'nafees.razzak',
'nafees@global-guidance.com': 'nafees.razzak',
'razan@global-guidance.com': 'razan.thawus',
'thasbiha@global-guidance.com': 'thasbiha.s',
'frontoffice@global-guidance.com': 'jinushiya', // Jilukshiya → mapped to existing intern slot
'jilukshiya@global-guidance.com': 'jinushiya',
'jinushiya@global-guidance.com': 'jinushiya',
'shiran@global-guidance.com': 'shiran',
'saleh@global-guidance.com': 'saleh',
'umair@global-guidance.com': 'umair',
'mohamed@global-guidance.com': 'mohamed.s',
'sukaina@global-guidance.com': 'sukaina',
'binupa@global-guidance.com': 'binupa',
'shakya@global-guidance.com': 'shakya'
};
// New unified default password from spreadsheet
const V16Z_NEW_DEFAULT_PW = 'Global@2026';
// Wrap doLogin — the actual login function in this portal.
// Two normalizations run BEFORE the original doLogin body executes:
// 1) Email → username (ceo@global-guidance.com → nashif.razzak)
// 2) 'Global@2026' → the user's legacy password (Staff@Global2026,
// CEO@Global2026, COO@Global2026, etc.) so === compare passes.
function v16zInstallLoginWrap(){
try {
if (typeof window.doLogin !== 'function') {
setTimeout(v16zInstallLoginWrap, 400);
return;
}
if (window.__v16zLoginWrapped) return;
const origDoLogin = window.doLogin;
window.doLogin = function v16zDoLogin(){
try {
const uEl = document.getElementById('loginUser');
const pEl = document.getElementById('loginPass');
if (uEl && uEl.value) {
const raw = String(uEl.value || '').trim().toLowerCase();
if (V16Z_EMAIL_ALIASES[raw]) {
uEl.value = V16Z_EMAIL_ALIASES[raw];
console.log('[v16z] Email login: ' + raw + ' → ' + V16Z_EMAIL_ALIASES[raw]);
}
}
if (uEl && pEl && pEl.value === V16Z_NEW_DEFAULT_PW) {
const uName = uEl.value.trim();
try {
const legacy = (typeof window._passwordFor === 'function')
? window._passwordFor(uName) : 'Staff@Global2026';
if (legacy && legacy !== V16Z_NEW_DEFAULT_PW) {
pEl.value = legacy;
console.log('[v16z] pw normalized: Global@2026 accepted for ' + uName);
}
} catch(e){}
}
} catch(e){ console.warn('[v16z] login wrap failed', e); }
return origDoLogin.apply(this, arguments);
};
window.__v16zLoginWrapped = true;
console.log('[v16z] doLogin wrapped — email + Global@2026 support installed');
} catch(e){ console.warn('[v16z] doLogin wrap install failed', e); }
}
v16zInstallLoginWrap();
// ============================================================
// FIX B — Full CRM Suite (Firmli-inspired)
// ============================================================
// ── Seed data ────────────────────────────────────────────────
// Universities & programs (compact — extendable via CRM UI)
const V16Z_UNIVERSITIES = [
{ id:'univ_cov', name:'Coventry University', country:'UK', city:'Coventry', ranking:601, intake:['Jan','Sep'], commission:15, programs:12 },
{ id:'univ_dmu', name:'De Montfort University', country:'UK', city:'Leicester', ranking:660, intake:['Jan','Sep'], commission:14, programs:18 },
{ id:'univ_herts',name:'University of Hertfordshire', country:'UK', city:'Hatfield', ranking:801, intake:['Jan','May','Sep'], commission:15, programs:22 },
{ id:'univ_sund', name:'University of Sunderland', country:'UK', city:'Sunderland', ranking:851, intake:['Jan','Sep'], commission:16, programs:9 },
{ id:'univ_north',name:'Northumbria University', country:'UK', city:'Newcastle', ranking:501, intake:['Jan','Sep'], commission:12, programs:24 },
{ id:'univ_bir', name:'Birmingham City University', country:'UK', city:'Birmingham', ranking:701, intake:['Jan','Sep'], commission:15, programs:31 },
{ id:'univ_bpp', name:'BPP University', country:'UK', city:'London', ranking:0, intake:['Jan','Apr','Sep'], commission:18, programs:14 },
{ id:'univ_uwl', name:'University of West London', country:'UK', city:'London', ranking:801, intake:['Jan','Sep'], commission:15, programs:19 },
{ id:'univ_gcu', name:'Glasgow Caledonian University', country:'UK', city:'Glasgow', ranking:701, intake:['Jan','Sep'], commission:14, programs:16 },
{ id:'univ_ulaw', name:'University of Law', country:'UK', city:'London', ranking:0, intake:['Jan','Sep'], commission:17, programs:8 },
{ id:'univ_deakin',name:'Deakin University', country:'AU', city:'Melbourne', ranking:290, intake:['Mar','Jul','Nov'], commission:15, programs:28 },
{ id:'univ_lat', name:'La Trobe University', country:'AU', city:'Melbourne', ranking:242, intake:['Mar','Jul'], commission:14, programs:22 },
{ id:'univ_curtin',name:'Curtin University', country:'AU', city:'Perth', ranking:183, intake:['Feb','Jul'], commission:15, programs:32 },
{ id:'univ_yorku',name:'York University', country:'CA', city:'Toronto', ranking:353, intake:['Jan','Sep'], commission:12, programs:26 },
{ id:'univ_seneca',name:'Seneca College', country:'CA', city:'Toronto', ranking:0, intake:['Jan','May','Sep'], commission:15, programs:41 }
];
const V16Z_PROGRAMS = [
{ id:'p1', univ:'univ_cov', name:'MSc Business & Management', level:'Masters', duration:'12 mo', tuition:16800, intake:'Jan/Sep', ielts:6.5 },
{ id:'p2', univ:'univ_cov', name:'MSc Data Science & AI', level:'Masters', duration:'12 mo', tuition:17900, intake:'Jan/Sep', ielts:6.5 },
{ id:'p3', univ:'univ_cov', name:'BEng Mechanical Engineering', level:'Bachelor', duration:'36 mo', tuition:16600, intake:'Sep', ielts:6.0 },
{ id:'p4', univ:'univ_dmu', name:'MSc Cyber Security', level:'Masters', duration:'12 mo', tuition:16250, intake:'Jan/Sep', ielts:6.0 },
{ id:'p5', univ:'univ_dmu', name:'BA Business Management', level:'Bachelor', duration:'36 mo', tuition:15750, intake:'Sep', ielts:6.0 },
{ id:'p6', univ:'univ_herts',name:'MSc Financial Management', level:'Masters', duration:'12 mo', tuition:15500, intake:'Jan/May/Sep', ielts:6.5 },
{ id:'p7', univ:'univ_herts',name:'MSc Software Engineering', level:'Masters', duration:'12 mo', tuition:16200, intake:'Jan/May/Sep', ielts:6.5 },
{ id:'p8', univ:'univ_sund', name:'MSc International Business', level:'Masters', duration:'12 mo', tuition:14000, intake:'Jan/Sep', ielts:6.0 },
{ id:'p9', univ:'univ_north',name:'MSc Digital Marketing', level:'Masters', duration:'12 mo', tuition:18500, intake:'Jan/Sep', ielts:6.5 },
{ id:'p10', univ:'univ_north',name:'MSc Public Health', level:'Masters', duration:'12 mo', tuition:19000, intake:'Sep', ielts:6.5 },
{ id:'p11', univ:'univ_bir', name:'MBA International Business', level:'Masters', duration:'12 mo', tuition:17500, intake:'Jan/Sep', ielts:6.5 },
{ id:'p12', univ:'univ_bpp', name:'LLM Legal Practice', level:'Masters', duration:'12 mo', tuition:20500, intake:'Jan/Apr/Sep', ielts:7.0 },
{ id:'p13', univ:'univ_uwl', name:'BA Hospitality Management', level:'Bachelor', duration:'36 mo', tuition:14750, intake:'Jan/Sep', ielts:6.0 },
{ id:'p14', univ:'univ_gcu', name:'MSc Project Management', level:'Masters', duration:'12 mo', tuition:16000, intake:'Jan/Sep', ielts:6.5 },
{ id:'p15', univ:'univ_ulaw', name:'MSc International Corporate Governance', level:'Masters', duration:'12 mo', tuition:19500, intake:'Jan/Sep', ielts:7.0 },
{ id:'p16', univ:'univ_deakin',name:'Master of IT', level:'Masters', duration:'24 mo', tuition:37000, intake:'Mar/Jul/Nov', ielts:6.5 },
{ id:'p17', univ:'univ_curtin',name:'Master of Nursing', level:'Masters', duration:'24 mo', tuition:39000, intake:'Feb/Jul', ielts:7.0 },
{ id:'p18', univ:'univ_yorku',name:'MBA', level:'Masters', duration:'20 mo', tuition:42000, intake:'Jan/Sep', ielts:6.5 },
{ id:'p19', univ:'univ_seneca',name:'PG Diploma Cloud Computing', level:'PG Dip', duration:'12 mo', tuition:17500, intake:'Jan/May/Sep', ielts:6.0 }
];
// ── Storage helpers (localStorage-based, keyed per install) ─
const V16Z_KEYS = {
leads: 'v16z:leads',
apps: 'v16z:applications',
commissions:'v16z:commissions',
contracts: 'v16z:contracts',
subagents: 'v16z:subagents',
events: 'v16z:events',
payments: 'v16z:payments'
};
function v16zLoad(key, fallback){
try {
const raw = localStorage.getItem(key);
if (!raw) return fallback;
return JSON.parse(raw);
} catch(e){ return fallback; }
}
function v16zSave(key, data){
try { localStorage.setItem(key, JSON.stringify(data)); } catch(e){ console.warn('[v16z] save fail', e); }
}
function v16zSeedIfEmpty(){
// Only seed once, to give the CRM demonstrable content on first load
if (!localStorage.getItem(V16Z_KEYS.leads)) {
v16zSave(V16Z_KEYS.leads, [
{ id:'L001', name:'Anushka Perera', email:'anushka.p@gmail.com', phone:'+94 77 234 5678', country:'UK', program:'MSc Data Science', stage:'Qualified', assignee:'razan.thawus', source:'Instagram', budget:18000, note:'IELTS 6.5, has 2.8 CGPA, needs Jan intake', created:Date.now()-8*86400000 },
{ id:'L002', name:'Kavindu Fernando', email:'kavindu.f@gmail.com', phone:'+94 71 987 6543', country:'AU', program:'Master of IT', stage:'Applied', assignee:'thasbiha.s', source:'Referral', budget:38000, note:'Deakin — LOA received, awaiting deposit', created:Date.now()-14*86400000 },
{ id:'L003', name:'Sithara Rajapakse', email:'sithara.r@gmail.com', phone:'+94 76 111 2222', country:'UK', program:'MBA', stage:'Contacted', assignee:'razan.thawus', source:'Facebook', budget:22000, note:'Needs GMAT waiver info', created:Date.now()-3*86400000 },
{ id:'L004', name:'Dinesh Bandara', email:'dinesh.b@gmail.com', phone:'+94 78 333 4444', country:'CA', program:'PG Dip Cloud Computing', stage:'New', assignee:'sukaina', source:'TikTok', budget:19000, note:'Fresh enquiry from Instagram DM', created:Date.now()-1*86400000 },
{ id:'L005', name:'Malithi Perera', email:'malithi.p@gmail.com', phone:'+94 77 555 6666', country:'UK', program:'MSc Cyber Security', stage:'Enrolled', assignee:'razan.thawus', source:'Google Ads', budget:16000, note:'DMU confirmed. Visa lodged 12 Aug', created:Date.now()-40*86400000 },
{ id:'L006', name:'Nimesha Silva', email:'nimesha.s@gmail.com', phone:'+94 76 777 8888', country:'UK', program:'MSc Business', stage:'Contacted', assignee:'sukaina', source:'Walk-in', budget:17000, note:'Wants Coventry, prefers Sep 2026', created:Date.now()-5*86400000 },
{ id:'L007', name:'Chamara Wickrama', email:'chamara.w@gmail.com', phone:'+94 71 999 0000', country:'AU', program:'Master of Nursing', stage:'Qualified', assignee:'thasbiha.s', source:'Referral', budget:39000, note:'RN qualification verified. Curtin shortlist', created:Date.now()-9*86400000 },
{ id:'L008', name:'Sanuka Wijesinghe', email:'sanuka.w@gmail.com', phone:'+94 78 222 3333', country:'UK', program:'LLM Legal Practice', stage:'Lost', assignee:'razan.thawus', source:'Instagram', budget:20500, note:'Chose competitor — Kaplan Law School', created:Date.now()-25*86400000 }
]);
}
if (!localStorage.getItem(V16Z_KEYS.apps)) {
v16zSave(V16Z_KEYS.apps, [
{ id:'A001', leadId:'L002', student:'Kavindu Fernando', univ:'univ_deakin', program:'p16', status:'LOA Received', stage:'Deposit Pending', submitted:Date.now()-30*86400000, updated:Date.now()-3*86400000, deposit:5000, tuition:37000 },
{ id:'A002', leadId:'L005', student:'Malithi Perera', univ:'univ_dmu', program:'p4', status:'CAS Issued', stage:'Visa Lodged', submitted:Date.now()-55*86400000, updated:Date.now()-8*86400000, deposit:8500, tuition:16250 },
{ id:'A003', leadId:'L001', student:'Anushka Perera', univ:'univ_cov', program:'p2', status:'Docs Verified',stage:'Application Submitted', submitted:Date.now()-6*86400000, updated:Date.now()-1*86400000, deposit:0, tuition:17900 },
{ id:'A004', leadId:'L007', student:'Chamara Wickrama', univ:'univ_curtin', program:'p17', status:'Under Assessment', stage:'Under Review', submitted:Date.now()-4*86400000, updated:Date.now()-1*86400000, deposit:0, tuition:39000 }
]);
}
if (!localStorage.getItem(V16Z_KEYS.commissions)) {
v16zSave(V16Z_KEYS.commissions, [
{ id:'C001', appId:'A002', student:'Malithi Perera', univ:'De Montfort University', tuition:16250, rate:14, amount:2275, status:'Invoiced', invoiceDate:Date.now()-15*86400000, paidDate:null },
{ id:'C002', appId:'A001', student:'Kavindu Fernando', univ:'Deakin University', tuition:37000, rate:15, amount:5550, status:'Pending Approval', invoiceDate:null, paidDate:null },
{ id:'C003', appId:null, student:'Rohan Silva', univ:'University of Sunderland',tuition:14000, rate:16, amount:2240, status:'Paid', invoiceDate:Date.now()-60*86400000, paidDate:Date.now()-40*86400000 },
{ id:'C004', appId:null, student:'Fathima Rizna', univ:'Coventry University', tuition:16800, rate:15, amount:2520, status:'Paid', invoiceDate:Date.now()-90*86400000, paidDate:Date.now()-70*86400000 },
{ id:'C005', appId:null, student:'Sahan Alwis', univ:'Northumbria University', tuition:18500, rate:12, amount:2220, status:'Overdue', invoiceDate:Date.now()-45*86400000, paidDate:null }
]);
}
if (!localStorage.getItem(V16Z_KEYS.contracts)) {
v16zSave(V16Z_KEYS.contracts, [
{ id:'CT001', univ:'univ_cov', type:'Recruitment Agreement', signed:Date.now()-365*86400000, expires:Date.now()+120*86400000, commission:15, status:'Active', contact:'partnerships@coventry.ac.uk' },
{ id:'CT002', univ:'univ_dmu', type:'Preferred Partner', signed:Date.now()-280*86400000, expires:Date.now()+80*86400000, commission:14, status:'Active', contact:'international@dmu.ac.uk' },
{ id:'CT003', univ:'univ_herts', type:'Recruitment Agreement', signed:Date.now()-500*86400000, expires:Date.now()+30*86400000, commission:15, status:'Renewing', contact:'agents@herts.ac.uk' },
{ id:'CT004', univ:'univ_deakin',type:'Preferred Partner', signed:Date.now()-180*86400000, expires:Date.now()+185*86400000, commission:15, status:'Active', contact:'agents@deakin.edu.au' },
{ id:'CT005', univ:'univ_sund', type:'Recruitment Agreement', signed:Date.now()-450*86400000, expires:Date.now()-15*86400000, commission:16, status:'Expired', contact:'agentteam@sunderland.ac.uk' }
]);
}
if (!localStorage.getItem(V16Z_KEYS.subagents)) {
v16zSave(V16Z_KEYS.subagents, [
{ id:'SA001', name:'EduLink Colombo', contact:'ashan@edulink.lk', phone:'+94 11 234 5678', region:'Colombo', commission:5, activeLeads:12, totalApps:34, tier:'Gold' },
{ id:'SA002', name:'StudyBridge Kandy', contact:'nishani@studybridge.lk',phone:'+94 81 234 5678', region:'Kandy', commission:6, activeLeads:8, totalApps:19, tier:'Silver' },
{ id:'SA003', name:'GlobalPath Jaffna', contact:'raj@globalpath.lk', phone:'+94 21 234 5678', region:'Jaffna', commission:6, activeLeads:5, totalApps:11, tier:'Silver' },
{ id:'SA004', name:'FutureEdu Galle', contact:'priya@futureedu.lk', phone:'+94 91 234 5678', region:'Galle', commission:5, activeLeads:3, totalApps:7, tier:'Bronze' }
]);
}
if (!localStorage.getItem(V16Z_KEYS.events)) {
v16zSave(V16Z_KEYS.events, [
{ id:'E001', title:'UK Universities Virtual Fair — Sep 2026', date:Date.now()+10*86400000, type:'Webinar', capacity:200, registered:87, host:'Razan Thawus', link:'https://zoom.us/j/12345' },
{ id:'E002', title:'Study in Australia: Info Session', date:Date.now()+18*86400000, type:'Webinar', capacity:150, registered:42, host:'Thasbiha S.', link:'https://zoom.us/j/67890' },
{ id:'E003', title:'Coventry University Delegation Visit', date:Date.now()+35*86400000, type:'On-site', capacity:60, registered:24, host:'Nashif Razzak',link:'Office — Colombo HQ' },
{ id:'E004', title:'IELTS Prep Workshop', date:Date.now()-5*86400000, type:'On-site', capacity:40, registered:38, host:'Sukaina', link:'Office — Colombo HQ' }
]);
}
if (!localStorage.getItem(V16Z_KEYS.payments)) {
v16zSave(V16Z_KEYS.payments, [
{ id:'PI001', kind:'inbound', from:'Kavindu Fernando', to:'Global Guidance', amount:5000, currency:'AUD', ref:'Deposit — Deakin App', date:Date.now()-2*86400000, method:'Bank Transfer', status:'Received' },
{ id:'PI002', kind:'inbound', from:'Anushka Perera', to:'Global Guidance', amount:250, currency:'USD', ref:'Consultancy Fee', date:Date.now()-4*86400000, method:'Card', status:'Received' },
{ id:'PO001', kind:'outbound', from:'Global Guidance', to:'EduLink Colombo', amount:600, currency:'USD', ref:'Sub-agent commission (Malithi)', date:Date.now()-35*86400000, method:'Bank Transfer', status:'Sent' },
{ id:'PO002', kind:'outbound', from:'Global Guidance', to:'Rohan Silva', amount:200, currency:'USD', ref:'Refund — dropped enrolment', date:Date.now()-20*86400000, method:'Bank Transfer', status:'Sent' }
]);
}
}
v16zSeedIfEmpty();
// ── CRM Renderer ────────────────────────────────────────────
function v16zRenderCRM(){
const page = document.getElementById('page-crm');
if (!page) return;
const tab = page.dataset.v16zTab || 'dashboard';
page.innerHTML = v16zBuildCRM(tab);
v16zWireCRM(page);
}
function v16zBuildCRM(tab){
const nav = `
${['dashboard','leads','universities','applications','commissions','contracts','subagents','events','payments'].map(t=>`
${t}
`).join('')}
`;
let body = '';
switch(tab){
case 'dashboard': body = v16zRenderDashboard(); break;
case 'leads': body = v16zRenderLeads(); break;
case 'universities': body = v16zRenderUniversities(); break;
case 'applications': body = v16zRenderApplications(); break;
case 'commissions': body = v16zRenderCommissions(); break;
case 'contracts': body = v16zRenderContracts(); break;
case 'subagents': body = v16zRenderSubagents(); break;
case 'events': body = v16zRenderEvents(); break;
case 'payments': body = v16zRenderPayments(); break;
default: body = v16zRenderDashboard();
}
return `
CRM Suite
Firmli-inspired: Leads · Programs · Applications · Commissions · Contracts · Sub-agents · Events · Payments
Export
Reset demo data
${nav}
${body}
`;
}
// ── Section: Dashboard ──────────────────────────────
function v16zRenderDashboard(){
const leads = v16zLoad(V16Z_KEYS.leads, []);
const apps = v16zLoad(V16Z_KEYS.apps, []);
const comm = v16zLoad(V16Z_KEYS.commissions, []);
const ct = v16zLoad(V16Z_KEYS.contracts, []);
const sa = v16zLoad(V16Z_KEYS.subagents, []);
const ev = v16zLoad(V16Z_KEYS.events, []);
const paidComm = comm.filter(c=>c.status==='Paid').reduce((s,c)=>s+c.amount,0);
const pendingComm = comm.filter(c=>c.status!=='Paid').reduce((s,c)=>s+c.amount,0);
const enrolled = leads.filter(l=>l.stage==='Enrolled').length;
const applied = leads.filter(l=>l.stage==='Applied').length;
const activeCts = ct.filter(c=>c.status==='Active').length;
const upcoming = ev.filter(e=>e.date>Date.now()).length;
const stat = (label, value, color, icon) => `
`;
return `
${stat('Total Leads', leads.length, '#4f46e5 0%, #7c3aed 100%', 'fa-users')}
${stat('Applications', apps.length, '#059669 0%, #10b981 100%', 'fa-file-alt')}
${stat('Enrolled', enrolled, '#0891b2 0%, #06b6d4 100%', 'fa-graduation-cap')}
${stat('Sub-agents', sa.length, '#7c3aed 0%, #a855f7 100%', 'fa-network-wired')}
${stat('Active Contracts', activeCts, '#dc2626 0%, #ef4444 100%', 'fa-file-signature')}
${stat('Upcoming Events', upcoming, '#ea580c 0%, #f97316 100%', 'fa-calendar')}
${stat('Commissions Paid', '$'+paidComm.toLocaleString(), '#16a34a 0%, #22c55e 100%', 'fa-dollar-sign')}
${stat('Commissions Pending', '$'+pendingComm.toLocaleString(), '#ca8a04 0%, #eab308 100%', 'fa-hourglass-half')}
Pipeline Overview
${['New','Contacted','Qualified','Applied','Enrolled','Lost'].map(stage=>{
const n = leads.filter(l=>l.stage===stage).length;
const col = {New:'#94a3b8',Contacted:'#3b82f6',Qualified:'#8b5cf6',Applied:'#f59e0b',Enrolled:'#10b981',Lost:'#ef4444'}[stage];
return `
`;
}).join('')}
`;
}
// ── Section: Leads (Kanban) ─────────────────────────
function v16zRenderLeads(){
const leads = v16zLoad(V16Z_KEYS.leads, []);
const stages = ['New','Contacted','Qualified','Applied','Enrolled','Lost'];
const stageColors = {New:'#94a3b8',Contacted:'#3b82f6',Qualified:'#8b5cf6',Applied:'#f59e0b',Enrolled:'#10b981',Lost:'#ef4444'};
return `
${leads.length} leads · ${leads.filter(l=>l.stage==='Enrolled').length} enrolled · $${leads.reduce((s,l)=>s+(l.budget||0),0).toLocaleString()} pipeline value
New Lead
${stages.map(s=>{
const inStage = leads.filter(l=>l.stage===s);
return `
${inStage.map(l=>`
${l.name}
${l.program || '—'}
${l.country || ''}
$${(l.budget||0).toLocaleString()}
${l.source || ''} · ${l.assignee || ''}
`).join('') || '
No leads
'}
`;
}).join('')}
`;
}
// ── Section: Universities & Programs ────────────────
function v16zRenderUniversities(){
return `
All countries United Kingdom Australia Canada
All levels Bachelor Masters PG Diploma
${V16Z_UNIVERSITIES.map(u=>{
const flag = {UK:'🇬🇧',AU:'🇦🇺',CA:'🇨🇦'}[u.country] || '🌍';
const uPrograms = V16Z_PROGRAMS.filter(p=>p.univ===u.id);
return `
${flag} ${u.name}
${u.city}, ${u.country} ${u.ranking?'· World rank #'+u.ranking:''}
${u.commission}% comm
Intake: ${u.intake.join(', ')} · ${u.programs} programs
${uPrograms.map(p=>`
${p.name} · ${p.duration} · £${p.tuition.toLocaleString()}
`).join('')}
`;
}).join('')}
`;
}
// ── Section: Applications ──────────────────────────
function v16zRenderApplications(){
const apps = v16zLoad(V16Z_KEYS.apps, []);
const stageColors = {'Application Submitted':'#3b82f6','Under Review':'#8b5cf6','LOA Received':'#10b981','Deposit Pending':'#f59e0b','CAS Issued':'#059669','Visa Lodged':'#dc2626'};
return `
${['ID','Student','University','Program','Status','Stage','Tuition','Deposit','Updated'].map(h=>`${h} `).join('')}
${apps.map(a=>{
const u = V16Z_UNIVERSITIES.find(x=>x.id===a.univ) || {};
const p = V16Z_PROGRAMS.find(x=>x.id===a.program) || {};
const stColor = stageColors[a.stage] || '#94a3b8';
return `
${a.id}
${a.student}
${u.name || '—'}
${p.name || '—'}
${a.status}
${a.stage}
£${a.tuition.toLocaleString()}
${a.deposit?'£'+a.deposit.toLocaleString():'—'}
${new Date(a.updated).toLocaleDateString()}
`;
}).join('')}
`;
}
// ── Section: Commissions ─────────────────────────
function v16zRenderCommissions(){
const comm = v16zLoad(V16Z_KEYS.commissions, []);
const paid = comm.filter(c=>c.status==='Paid').reduce((s,c)=>s+c.amount,0);
const pending = comm.filter(c=>c.status==='Pending Approval').reduce((s,c)=>s+c.amount,0);
const invoiced= comm.filter(c=>c.status==='Invoiced').reduce((s,c)=>s+c.amount,0);
const overdue = comm.filter(c=>c.status==='Overdue').reduce((s,c)=>s+c.amount,0);
const stateColor = {'Paid':'#10b981','Pending Approval':'#f59e0b','Invoiced':'#3b82f6','Overdue':'#ef4444'};
return `
Paid
$${paid.toLocaleString()}
Invoiced
$${invoiced.toLocaleString()}
Pending
$${pending.toLocaleString()}
Overdue
$${overdue.toLocaleString()}
${['ID','Student','University','Tuition','Rate','Amount','Status','Invoiced','Paid'].map(h=>`${h} `).join('')}
${comm.map(c=>`
${c.id}
${c.student}
${c.univ}
$${c.tuition.toLocaleString()}
${c.rate}%
$${c.amount.toLocaleString()}
${c.status}
${c.invoiceDate?new Date(c.invoiceDate).toLocaleDateString():'—'}
${c.paidDate?new Date(c.paidDate).toLocaleDateString():'—'}
`).join('')}
`;
}
// ── Section: Contracts ────────────────────────────
function v16zRenderContracts(){
const ct = v16zLoad(V16Z_KEYS.contracts, []);
const stColor = {'Active':'#10b981','Renewing':'#f59e0b','Expired':'#ef4444'};
return `
${ct.map(c=>{
const u = V16Z_UNIVERSITIES.find(x=>x.id===c.univ) || {};
const daysLeft = Math.round((c.expires - Date.now())/86400000);
return `
${u.name || 'Unknown'}
${c.type}
${c.status}
Signed: ${new Date(c.signed).toLocaleDateString()}
Expires: ${new Date(c.expires).toLocaleDateString()} (${daysLeft} days)
Commission: ${c.commission}%
Contact: ${c.contact}
`;
}).join('')}
`;
}
// ── Section: Sub-agents ───────────────────────────
function v16zRenderSubagents(){
const sa = v16zLoad(V16Z_KEYS.subagents, []);
const tierColor = {'Gold':'#eab308','Silver':'#94a3b8','Bronze':'#a16207'};
return `
${sa.map(a=>`
📧 ${a.contact}
📞 ${a.phone}
💰 Commission: ${a.commission}%
${a.activeLeads}
Active Leads
${a.totalApps}
Total Apps
`).join('')}
`;
}
// ── Section: Events/Webinars ──────────────────────
function v16zRenderEvents(){
const ev = v16zLoad(V16Z_KEYS.events, []);
return `
${ev.map(e=>{
const upcoming = e.date > Date.now();
const fillPct = Math.round((e.registered/e.capacity)*100);
return `
${e.title}
📅 ${new Date(e.date).toLocaleString()}
${upcoming?'Upcoming':'Past'}
🎤 Host: ${e.host}
🏷 Type: ${e.type}
Registrations
${e.registered} / ${e.capacity}
`;
}).join('')}
`;
}
// ── Section: Payments ─────────────────────────────
function v16zRenderPayments(){
const p = v16zLoad(V16Z_KEYS.payments, []);
const inb = p.filter(x=>x.kind==='inbound');
const outb = p.filter(x=>x.kind==='outbound');
const inbTotal = inb.reduce((s,x)=>s+x.amount,0);
const outbTotal = outb.reduce((s,x)=>s+x.amount,0);
return `
💰 Inbound (received)
$${inbTotal.toLocaleString()}
${inb.length} transactions
💸 Outbound (sent)
$${outbTotal.toLocaleString()}
${outb.length} transactions
${['ID','Direction','From','To','Amount','Reference','Method','Status','Date'].map(h=>`${h} `).join('')}
${p.map(x=>`
${x.id}
${x.kind==='inbound'?'⬇️ In':'⬆️ Out'}
${x.from}
${x.to}
$${x.amount.toLocaleString()} ${x.currency}
${x.ref}
${x.method}
${x.status}
${new Date(x.date).toLocaleDateString()}
`).join('')}
`;
}
// ── Wiring & interactions ─────────────────────────
function v16zWireCRM(page){
// Tab switching
page.querySelectorAll('.v16z-tab').forEach(btn=>{
btn.onclick = () => {
page.dataset.v16zTab = btn.dataset.tab;
v16zRenderCRM();
};
});
// Export
const exportBtn = page.querySelector('#v16zExportBtn');
if (exportBtn) exportBtn.onclick = ()=>{
const dump = {};
Object.entries(V16Z_KEYS).forEach(([k,storeKey])=>{ dump[k] = v16zLoad(storeKey, []); });
const blob = new Blob([JSON.stringify(dump, null, 2)], {type:'application/json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'crm-export-' + new Date().toISOString().slice(0,10) + '.json';
a.click(); URL.revokeObjectURL(url);
};
// Reset
const resetBtn = page.querySelector('#v16zResetBtn');
if (resetBtn) resetBtn.onclick = ()=>{
if (!confirm('This will delete all CRM data and reseed demo content. Continue?')) return;
Object.values(V16Z_KEYS).forEach(k => localStorage.removeItem(k));
v16zSeedIfEmpty();
v16zRenderCRM();
};
// Add lead
const addBtn = page.querySelector('#v16zAddLead');
if (addBtn) addBtn.onclick = ()=>{
const name = prompt('Student name?'); if (!name) return;
const email = prompt('Email?', '') || '';
const phone = prompt('Phone?', '') || '';
const country = prompt('Country (UK/AU/CA/US)?', 'UK') || 'UK';
const program = prompt('Program of interest?', 'MSc') || '';
const stage = prompt('Stage (New/Contacted/Qualified/Applied/Enrolled/Lost)?', 'New') || 'New';
const budget = parseInt(prompt('Budget (USD)?', '15000')) || 0;
const source = prompt('Source?', 'Manual') || 'Manual';
const cur = curUser();
const leads = v16zLoad(V16Z_KEYS.leads, []);
leads.unshift({
id: 'L' + String(leads.length+100).padStart(3,'0'),
name, email, phone, country, program, stage, budget, source,
assignee: cur?.username || 'unassigned',
note: '',
created: Date.now()
});
v16zSave(V16Z_KEYS.leads, leads);
v16zRenderCRM();
};
// Lead card click → move stage
page.querySelectorAll('.v16z-lead-card').forEach(card=>{
card.onclick = ()=>{
const id = card.dataset.lead;
const leads = v16zLoad(V16Z_KEYS.leads, []);
const lead = leads.find(l=>l.id===id);
if (!lead) return;
const stage = prompt('Move ' + lead.name + ' to which stage?\n(New / Contacted / Qualified / Applied / Enrolled / Lost)', lead.stage);
if (!stage) return;
lead.stage = stage;
v16zSave(V16Z_KEYS.leads, leads);
v16zRenderCRM();
};
});
// University search filter
const searchIn = page.querySelector('#v16zUniSearch');
const countryIn= page.querySelector('#v16zUniCountry');
const applyFilter = ()=>{
const q = (searchIn?.value || '').toLowerCase();
const country = countryIn?.value || '';
page.querySelectorAll('.v16z-uni-card').forEach(card=>{
const text = card.textContent.toLowerCase();
const c = card.dataset.country;
const show = (!q || text.includes(q)) && (!country || c===country);
card.style.display = show ? '' : 'none';
});
};
if (searchIn) searchIn.oninput = applyFilter;
if (countryIn) countryIn.onchange = applyFilter;
}
// ── Nav injection: add CRM item to sidebar ────────
function v16zInjectNav(){
try {
const nav = document.querySelector('#sidebar, .sidebar, nav.side, [id*="Nav"]');
if (!nav) return;
if (document.getElementById('v16zNavCRM')) return;
// Insert after "Dashboard" if present, else at top
const item = document.createElement('a');
item.id = 'v16zNavCRM';
item.href = '#';
item.style.cssText = 'display:flex;align-items:center;gap:8px;padding:10px 14px;color:#374151;text-decoration:none;font-size:13px;font-weight:600;border-radius:6px;margin:4px 8px;transition:background .15s';
item.innerHTML = ' CRM Suite NEW ';
item.onmouseover = ()=> item.style.background='#f3f4f6';
item.onmouseout = ()=> item.style.background='';
item.onclick = (e)=>{ e.preventDefault(); if (typeof window.nav==='function') window.nav('crm'); };
nav.appendChild(item);
} catch(e){ console.warn('[v16z] nav inject failed', e); }
}
// Hook into page navigation so #page-crm renders
function v16zEnsurePage(){
try {
let page = document.getElementById('page-crm');
if (!page) {
page = document.createElement('div');
page.id = 'page-crm';
page.className = 'page';
page.style.display = 'none';
document.body.appendChild(page);
}
// Hook: when 'crm' is navigated to, render into it
if (typeof window.nav === 'function' && !window.__v16zNavWrapped) {
const origNav = window.nav;
window.nav = function v16zNav(pageId){
const r = origNav.apply(this, arguments);
if (pageId === 'crm') {
// hide other pages
document.querySelectorAll('.page').forEach(p=>p.style.display='none');
const cp = document.getElementById('page-crm');
if (cp) { cp.style.display=''; v16zRenderCRM(); }
}
return r;
};
window.__v16zNavWrapped = true;
}
} catch(e){ console.warn('[v16z] page setup failed', e); }
}
// Grant CRM access to appropriate users
function v16zGrantCRMAccess(){
try {
const U = getUSERS();
['superadmin','nashif.razzak','nafees.razzak','razan.thawus','thasbiha.s','umair','sukaina','saleh'].forEach(uname=>{
if (U[uname] && Array.isArray(U[uname].pages) && !U[uname].pages.includes('crm')) {
U[uname].pages.push('crm');
}
});
} catch(e){ console.warn('[v16z] page grant failed', e); }
}
// Init & schedule
setTimeout(function(){
v16zGrantCRMAccess();
v16zEnsurePage();
v16zInjectNav();
}, 1500);
setInterval(function(){
v16zEnsurePage();
v16zInjectNav();
}, 3000);
console.log('[v16z] Loaded — Firmli-inspired CRM + email login aliases + Global@2026 password support.');
})();