Skip to main content
MyTalent Jobs
FIND JOBS · 16 COUNTRIES
MyTalent Jobs Global — Find Jobs in Malaysia, Singapore, UAE, UK, USA & 16 Countries
Job Search Portal Malaysia — Jawatan Kosong 2026
Kerja Kosong Malaysia — Jobs in KL, Selangor, Penang, Johor, Sabah
Singapore Jobs — SGD Salary Careers for Malaysians & Expats
Dubai UAE Jobs — Tax-Free Salary, Cabin Crew, Finance, IT
UK Jobs — Skilled Worker Visa, Graduate Jobs, Engineering
Australia Jobs — PR Pathway, Nursing, IT, Engineering, Mining
Japan Jobs — English-Speaking, IT, Finance, Teaching
India Jobs — IT, BPO, Finance, Healthcare — Bangalore, Mumbai, Delhi
Germany Jobs — Engineering, IT, Healthcare — Work Visa Deutschland
Canada Jobs — Express Entry, IT, Healthcare, Engineering
Software Engineer Jobs Malaysia 2026
Data Scientist Jobs — Malaysia Singapore
Financial Analyst Jobs — Kuala Lumpur, Singapore
HR Manager Jobs Malaysia — Employment Act 1955
Nursing Jobs Malaysia — MNB Registered Nurse, ICU, Hospital
Digital Marketing Manager Jobs — Google Ads, Meta, SEO
Civil Structural Engineer Jobs — MRT, Highway, Construction
Petroleum Engineer Jobs — PETRONAS, Shell, Oil Gas Sabah Sarawak
Remote Work From Home Jobs Malaysia 2026
Fresh Graduate Jobs Malaysia — No Experience Required
Internship Jobs Malaysia — Industrial Training
MNC Jobs Malaysia — Multinational Companies Hiring
Salary Guide Malaysia 2026 — Average Salary by Industry
EPF SOCSO Employment Act Malaysia HR Compliance
Work Permit Employment Pass Malaysia Singapore UAE
MyTalent Jobs is Malaysia's leading AI-powered job portal with over 850,000 active job listings across 16 countries. Search for jobs in Kuala Lumpur, Selangor, Penang, Johor Bahru, Sabah, Sarawak, Singapore, Dubai, London, Sydney, Tokyo and more.
Popular job searches: software engineer, data analyst, accountant, HR executive, nurse, graphic designer, project manager, business development, customer service, sales executive, operations manager, supply chain, procurement.
Find jobs by salary: RM 2000-3000, RM 3000-5000, RM 5000-8000, RM 8000-12000, RM 12000+. SGD 3000-5000, SGD 5000-8000, SGD 8000-12000. USD 50000-100000. GBP 30000-50000. AED 5000-15000.
Employer services: Post jobs, search resumes, AI recruitment tools, hiring pipeline, candidate matching, salary benchmarking, fraud detection, interview question generator, offer letter writer, HR policy generator.
Industries: Technology IT Software, Finance Banking Insurance, Healthcare Medical Nursing, Engineering Construction, Education Teaching, Retail E-commerce, Hospitality Tourism, Oil Gas Energy, Logistics Transport, Marketing Advertising, Legal Compliance, Agriculture Plantation, Real Estate Property, Media Creative, Automotive Manufacturing.
MyTalent Jobs
Global Careers 🏢 Clients 🇲🇾 Malaysia 🇸🇬 Singapore 🇮🇩 Indonesia 🇹🇭 Thailand 🇻🇳 Vietnam 🇦🇺 Australia 🇬🇧 United Kingdom 🇺🇸 United States 🇦🇪 UAE / Dubai 🇯🇵 Japan 🇮🇳 India 🇩🇪 Germany 🇨🇦 Canada ▼
🌍
🇲🇾 Malaysia 🇸🇬 Singapore 🇮🇩 Indonesia 🇹🇭 Thailand 🇻🇳 Vietnam 🇦🇺 Australia 🇬🇧 UK 🇺🇸 USA 🇦🇪 UAE 🇯🇵 Japan 🇮🇳 India 🇩🇪 Germany 🇨🇦 Canada
Log In Register Free For Employers
⚙️
👤 My Profile
📋 My Applications
❤️ Saved Jobs
📄 My Resume
🔔 Job Alerts
💬 Messages
💰 Salary Tools
⚙️ Admin Dashboard
🏢 Employer Dashboard
🚪 Sign Out
🌍 Switch Country
🇲🇾 Malaysia
🇸🇬 Singapore
🇮🇩 Indonesia
🇹🇭 Thailand
🇻🇳 Vietnam
🇵🇭 Philippines
🇦🇺 Australia
🇬🇧 United Kingdom
🇺🇸 United States
🇦🇪 UAE / Dubai
🇯🇵 Japan
🇮🇳 India
🇩🇪 Germany
🇨🇦 Canada
🇭🇰 Hong Kong Navigation
🔍 Find Jobs
🌍 Browse Countries
🏭 Industries
💰 Salary Guide
Account
👤 Sign In
✨ Register Free
🏢 For Employers
Tools
📝 Post a Job
⚙️ Admin Panel
MyTalent Jobs Global · 16 Countries · 850K+ Jobs
Malaysia's #1 Job Portal
Find Your Next Career Anywhere in the World MyTalent Jobs connects top talent with leading employers across every industry and profession globally. Find your perfect role by field, specialisation, and location.
850K+
Active Jobs Globally
🔥 Trending: Software Engineer HR Manager Sales Executive Accounting Data Scientist Nursing Digital Marketing
📊 Market Intelligence — —
✕ 📈 Demand Trend (6mo)
Dec Jan Feb Mar Apr May
🤖 AI insight will appear here after search...
Jobs Posted Today
+1,842
Live globally
Countries
16
🌍 5 continents
Hired This Week
8,420
🎉 Congratulations!
MY/SG UK/EU USA UAE JP AU IN 🇲🇾 🇸🇬 🇦🇺 🇬🇧 🇺🇸 🇦🇪 🇯🇵 🇩🇪
16 Countries · 5 Continents
Where Global Careers Are Built From Southeast Asia to Europe, the Americas to the Middle East — MyTalent Jobs connects talent with opportunity worldwide.
How MyTalent Jobs Works — Three steps to your opportunity
1. Search & Filter · 2. Apply Instantly · 3. Get Hired
📊 Live BI Dashboard — All Jobs
Live
🌍 MyTalent Jobs Global Network Find opportunities in 16 countries across 5 continents
🇸🇬
Singapore
92,400 jobs
SGD 6,500 avg
🇦🇺
Australia
185,200 jobs
AUD 7,800 avg
🇬🇧
United Kingdom
248,600 jobs
GBP 4,200 avg
🇺🇸
United States
520,800 jobs
USD 7,500 avg
🇦🇪
UAE / Dubai
98,400 jobs
AED 12,000 avg
🇯🇵
Japan
142,000 jobs
JPY 280,000 avg
🇩🇪
Germany
178,500 jobs
EUR 4,800 avg
🇨🇦
Canada
210,400 jobs
CAD 6,200 avg
🌏 Southeast Asia
Browse Jobs by Country
Explore opportunities across 16 countries — updated daily
🇦🇪 UAE / Dubai
72,000+ jobs
🇬🇧 United Kingdom
210,000+ jobs
🇺🇸 United States
380,000+ jobs
🇵🇭 Philippines
31,000+ jobs
Browse by Industry — Malaysia Explore all major sectors — Malaysia
Success Stories Real Malaysians, real results 🇲🇾
★★★★★
"Found my dream software engineer role in 2 weeks. MyTalent Jobs's industry filters made it so easy to find the right match."
AH
Ahmad Hafiz
Software Engineer, KL
★★★★★
"As HR manager I hired 8 qualified candidates in one month. The profession-focused filters saved us so much time."
LC
Lim Chin Wei
HR Manager, Penang
★★★★★
"Fresh grad from UiTM and landed a nursing position in JB. MyTalent Jobs had so many healthcare listings!"
NR
Nurul Rahayu
Registered Nurse, JB
⚡ 1,248 jobs added today
Ready to Find Your Next Role?
Join 5 million professionals already using MyTalent Jobs. Free for job seekers, forever.
Get Started — Free
Hiring? Post a Job
☰ Dashboard Welcome back, Admin. Here's what's happening today.
➕ Post Job ➕ Add Candidate 🌐 View Site + Post Job Logout 🇲🇾 MyTalent Jobs Platform — Live Overview Sunday, 17 May 2026 · All systems operational · Last updated: just now
💼
48,210
Active Job Listings
▲ 12% from last month
👤
852,340
Registered Job Seekers
▲ 8.4% from last month
🏢
12,580
Registered Employers
▲ 5.1% from last month
📨
134,820
Applications This Month
▲ 18.2% from last month
⏳
342
Pending Approvals
▲ 24 new today
✅
1,240
Successful Hires This Week
▲ 6.8% from last week
💰
RM 84,200
Revenue This Month
▲ 22% from last month
🚩
17
Flagged Listings
Needs attention
Quick Actions 🏦
Set Up Your Payout Account
Enter your company bank account number to receive payments from customers. Required before your first payout.
Dismiss 🏦 Set Up Payout Account →
🏦
Payout & Banking
Enter your company account number to receive customer payments
→
📊 Jobs Posted — Last 6 Months
🗺️ Jobs by State — Malaysia KL 18,420 jobs Selangor 9,840 Penang 5,230 Johor 4,810 Sabah 3,120 Sarawak 2,890 🕐 Recent Activity 🏢
Shopee Malaysia posted Digital Marketing Manager
2 minutes ago
👤
Ahmad Hafiz applied for Senior Software Engineer
8 minutes ago
✅
KPJ Healthcare account verified and approved
25 minutes ago
🚩
Job "Easy Money Work From Home" flagged
1 hour ago
⏳ Pending Approvals 💼
Account Manager — Sales Corp MY
10 mins ago
Approve Reject
🏢
New Employer: Nexus Logistics Sdn Bhd
Registration pending
Approve Reject
🚩
Flagged: "Work From Home RM5000/day No Experience"
Likely scam
Remove
All Job Listings Export CSV + Add Job
All Status Active Pending Flagged
Job Title Company Industry State Salary Apps Status Actions Senior Software Engineer Tech Solutions MY Technology & IT KL RM7K–12K 48 Active View Edit Delete
HR Executive Global Recruit Sdn Bhd HR & Recruitment Selangor RM3.5K–5.5K 31 Pending Approve Reject
Financial Analyst Maybank Bhd Finance & Banking KL RM6K–9K 72 Active View Edit Delete
Registered Nurse KPJ Healthcare Healthcare Johor RM3K–4.5K 19 Active View Delete
Work From Home RM5K/day Unknown Sdn Bhd — — — 3 Flagged Remove
Employer Accounts + Add Employer
All Plans Free Basic Pro Enterprise
Company Industry Plan Jobs Status Actions PETRONAS Oil & Gas Enterprise 124 Verified View Edit
Maybank Bhd Finance & Banking Pro 89 Verified View Edit
Nexus Logistics Logistics Basic 3 Pending Approve Reject
Spam Jobs MY Unknown Free 18 Suspended Remove
Job Seeker Accounts
Name Email State Industry Interest Apps Status Actions Ahmad Hafiz ahmad@email.com KL Technology & IT 12 Active View Suspend
Nurul Rahayu nurul@email.com Johor Healthcare 7 Active View Suspend
Lim Wei Jian weijian@email.com Penang Finance & Banking 4 Active View Suspend
🔍
2.4M
Searches This Month
▲ 14%
📄
134K
Applications Submitted
▲ 18%
⏱️
4m 32s
Avg. Session
▲ 0.8%
🥧 Applications by Industry
Announcements + New Announcement 🔔 System Notice
Scheduled Maintenance — 20 May 2026
MyTalent Jobs will undergo scheduled maintenance on 20 May from 2AM–4AM.
🎉 Promotion
Hari Raya Special — 50% Off Pro Plan
Employers can enjoy 50% off first month on Pro plan. Use code RAYA2026.
💼 Feature Update
New: AI-Powered Job Matching is Live
MyTalent Jobs now uses AI to match job seekers with the most relevant listings.
⚠️ Policy Update
Updated Terms of Service — 1 June 2026
Updated Terms of Service for improved clarity on employer posting policies.
Featured Listings + Add Featured Job Title Company Plan Featured Until Impressions Clicks Actions ⭐ Senior Software Engineer Tech Solutions MY Pro 31 May 2026 12,400 840 Edit Remove
⭐ Petroleum Engineer PETRONAS Enterprise 30 Jun 2026 18,200 1,040 Edit Remove
💳 Buy Credits & Ad Packages
Top up your job ad slots and resume search credits anytime
📣
Job Ad Slots Remaining
3
of 5 purchased
🔍
Resume Search Credits
42
of 50 purchased
💰
Total Spent
RM 1,000
2 purchases this month
📣 Job Advertisement Packages
Each slot lets you post one job listing on MyTalent Jobs. Slots never expire.
×5
5 Job Advertisements
Post up to 5 job listings · RM 100 per ad
⭐ Best Value
×10
10 Job Advertisements
Post up to 10 job listings · RM 75 per ad Save 25%
×20
20 Job Advertisements
Post up to 20 job listings · RM 50 per ad Save 50%
×50
50 Job Advertisements
Post up to 50 job listings · RM 40 per ad Save 60%
🔍 Resume Search Credits
Each credit allows you to view 1 full candidate resume. Credits never expire.
50
50 Search Credits
View 50 full resumes · RM 10 per search
🔥 Most Popular
100
100 Search Credits
View 100 full resumes · RM 8 per search Save 20%
200
200 Search Credits
View 200 full resumes · RM 5 per search Save 50%
🛒 Order Summary
📦
Select a package from the left to continue
Select your bank for FPX payment
🔒 SSL 🛡️ PCI DSS 🏦 FPX ✅ Bank Negara
🔒 Pay Now — RM 0 🧾 Purchase History
5 Job Ads
12 May 2026 · Credit Card
50 Search Credits
3 May 2026 · Maybank2u
Processing Payment...
Please do not close this window.
🔒 SSL Encrypted 🏦 FPX Verified ✅ Bank Negara
✅
Payment Successful! 🎉
Your credits have been added to your account.
🧾 Official Tax Receipt
Transaction ID —
Invoice No. —
Package —
Date & Time —
Payment Method —
Subtotal —
SST (8%) —
Total Paid —
Status ✅ Confirmed
Credited —
📧 Tax invoice sent to your registered email. Credits/slots added immediately.
📄 Download Invoice 🔍 Search Resumes Done ✓
🤖 MyTalent Jobs AI Hub
16 AI-powered tools · Powered by Claude · Real-time · Global job market intelligence
🧠 Claude Sonnet 4
⚡ Real-time API
📊 0 calls today
RM 8,200
Avg AI Salary Rec.
Enter a job title and details — AI writes a professional job description instantly.
Job Title *
Country 🇲🇾 Malaysia 🇸🇬 Singapore 🇦🇺 Australia 🇬🇧 United Kingdom 🇺🇸 United States 🇦🇪 UAE 🇯🇵 Japan 🇮🇳 India 🇩🇪 Germany
Industry Technology & IT Finance & Banking Healthcare & Medical Engineering HR & Recruitment Marketing & Advertising Education Oil & Gas Logistics
Experience Level Fresh Graduate 1–3 Years 3–5 Years 5–10 Years Senior / Management Director / C-Suite
Key Skills (comma separated)
Tone / Style Professional & Corporate Friendly & Startup Concise & Direct Detailed & Technical
Company Culture / Benefits to Highlight
✨ Generate Job Description Paste CV / Resume Text *
Job Requirements & Must-Haves
🔍 Screen This CV Job Description
Candidate Profiles (one per line)
Priority Criteria Best Overall Fit Most Experienced Best Value (Salary vs Skills) Fastest Available Strongest Technical Skills
🎯 Match & Rank Candidates Job Title *
Country Malaysia Singapore Australia United Kingdom United States UAE Japan India Germany
Industry Technology & IT Finance & Banking Healthcare Engineering Marketing Oil & Gas Education
State / City Kuala Lumpur Selangor Penang Johor Sabah Sarawak Other
Years of Experience 0–1 Year (Fresh Grad) 1–3 Years 3–5 Years 5–10 Years 10+ Years
Company Size Startup (< 50) SME (50–200) Mid-size (200–1000) Large Corp (1000+) MNC / Listed
💰 Get Salary Benchmark Job Title *
Interview Stage Phone Screening (15 mins) 1st Interview (HR) 2nd Interview (Technical) Final Interview (Director) Assessment Centre
Interview Type Technical / Skills Behavioural (STAR) Cultural Fit Case Study / Problem Solving Mixed Comprehensive
Number of Questions 5 8 10 15 20
Key Competencies to Assess
Candidate Background (optional)
🗣️ Generate Questions Tone Professional & Warm Brief & Formal Encouraging & Kind Direct & Concise
Language English Bahasa Malaysia Both (bilingual)
Interview Details (for invitations)
📧 Write Email 👋 Hi! I'm MyTalent Jobs's AI Recruitment Assistant. I can help with: • Hiring strategies & best practices • Malaysian employment law & HR compliance • Salary negotiation tips • Candidate evaluation advice • Job market insights across 16 countries • HR policy guidance What would you like to know?
📈 Hiring trends 2026 💰 Min wage MY 📝 Offer letter tips 💻 Top tech skills
Send →
🗑 Clear Chat Job Role *
Candidate CV / Profile *
Company Culture Fast-paced Startup Corporate MNC Government-linked SME / Family Business Creative Agency
Scoring Model Balanced (Skills + Fit) Technical Skills First Culture Fit Priority Experience Weighted
📊 Score This Candidate Industry / Sector * Technology & IT Finance & Banking Healthcare Manufacturing & Engineering Retail & E-commerce Oil & Gas Education Hospitality
Country Malaysia Singapore Southeast Asia (Regional) Australia UAE / GCC United Kingdom India
Focus Area Hiring Trends & Demand Salary Movements In-Demand Skills Remote Work Patterns Talent Shortage Areas Q2 2026 Outlook
Specific Question (optional)
📈 Get Market Intelligence Employee Role
Tenure at Company < 6 months 6–12 months 1–3 years 3–5 years 5+ years
Current Risk Level Low Risk Medium Risk High Risk (flight risk) Already Resigned
Industry Technology Finance Healthcare Manufacturing Retail
Suspected Reasons for Leaving
🤝 Get Retention Strategy Policy Type * Annual Leave Policy Remote Work / WFH Policy Performance Management Policy Anti-Harassment Policy Code of Conduct Data Privacy Policy (PDPA) Recruitment & Hiring Policy Termination Procedure Grievance Handling Policy
Company Size Startup (< 50) SME (50–200) Mid-size (200–1000) Large Corp (1000+)
Country / Jurisdiction Malaysia (Employment Act 1955) Singapore (EA 1968) UK (Employment Rights Act) Australia (Fair Work Act) UAE (Labour Law)
Tone Formal & Legal Clear & Employee-Friendly Concise Policy Format
Special Requirements or Context
⚖️ Write HR Policy Focus Area * Improve Hiring Diversity Inclusive Job Descriptions Equal Pay Analysis Bias-Free Interview Process Women in Leadership Neurodiversity at Work D&I Strategy Roadmap
Company Size Startup SME Mid-size Large Enterprise
Current Challenges
🌈 Get D&I Recommendations Key Achievements (bullet points)
Areas for Improvement
🎖️ Write Performance Review Benefits Package
Country / Jurisdiction Malaysia Singapore UAE UK Australia
📝 Generate Offer Letter 📄 AI Output 📋 Copy 💾 Save 🗑 Clear
🤖
Select an AI tool and fill in the details. Your AI-generated content will appear here.
📄 AI Output 📋 Copy 🗑️ Clear
🤖
Select an AI tool and fill in the details to get started. Your AI-generated content will appear here.
📊 AI Insights — Malaysia Job Market 🔥
Tech
Highest demand industry
▲ 24% YoY growth
💰
RM 7,200
Avg salary — KL Tech roles
▲ 12% vs last year
⏱️
18 days
Avg time to hire in Malaysia
▼ 3 days faster
🎯
68%
Applications from mobile
▲ 8% this quarter
📄 Resume & Candidate Search
Search 850,000+ resumes · AI-powered matching · Instant shortlisting
📄 Resume Search
👤 Candidate Search
🔎 Search Resumes by Skills, Title or Keywords
Quick search:
${['React','Python','Java','HR Manager','Accountant','Nurse','Sales','Data Analyst','Project Manager','Civil Engineer','Marketing','Logistics'].map(s=>`${s} `).join('')}
State
All States Kuala Lumpur Selangor Penang Johor Sabah Sarawak Perak Pahang Experience
Any Fresh Graduate 1–3 Years 3–5 Years 5–10 Years 10+ Years Education
Any SPM Diploma Bachelor's Master's PhD Salary Expect (RM)
Any < RM 3,000 RM 3,000–5,000 RM 5,000–8,000 RM 8,000–12,000 > RM 12,000 Availability
Any Immediately 2 Weeks 1 Month 3 Months Options: Actively Job Seeking Open to Relocation Remote Ready Malaysian Citizens Only ✅ Verified Resume Only
Found 8 resumes
Sort by: Best Match Newest Resume Most Experienced Lowest Salary Highest Match Score 📥 Export
🤖 AI Resume Matching Analysis
✕
Showing 8 candidates
🤖 AI Match to My Job
🤖 AI Candidate Ranking
📄 View Full Resumes →
📝 Post a Job
Reach 850,000+ qualified Malaysian candidates instantly
📝 Job Details Job Description *
Requirements
Benefits & Perks
🤖 AI Write Description Save Draft 🚀 Publish Job
Want to proactively find matching candidates? 📄 Search Resumes →
👁️ Live Preview Job Title
Your Company · KL
Job description will appear here...
RM — / month
📣 Advertisements
Promote your brand and jobs to millions of Malaysian professionals
👁️
42,800
Total Impressions
▲ 18% this week
🖱️
1,240
Total Clicks
CTR 2.9%
💼
86
Applications via Ads
▲ 12 this week
💰
RM 2,150
Ad Spend This Month
Budget: RM 3,000
📊 Active Campaigns + New Ad
🎯 Create New Campaign Campaign Name
Ad Type Banner Ad — Homepage (RM 500/week) Featured Job Listing (RM 150/7 days) Email Blast — 10K candidates (RM 350) Search Result Highlight (RM 200/week) Social Media Boost (RM 400/campaign)
Target Industry All Industries Technology & IT Finance & Banking Healthcare Engineering
Target State All Malaysia Kuala Lumpur Selangor Penang Johor
Ad Headline
Ad Description
🚀 Launch Campaign 📈 Campaign Performance — Last 7 Days
Mon Tue Wed Thu Fri Sat Sun
🎯 Hiring Pipeline
Track every candidate through your recruitment funnel
📄 Search Resumes 📝 Post a Job 📣 Run Ad Campaign 🤖 AI Match Candidates
<✅ Done
⏰ Payout Schedule — When We Transfer to Your Account Payout Frequency Daily (next business day) Weekly Bi-weekly (every 2 weeks) Monthly (1st of month) Manual (request payout)
Payout Day (for weekly)
${['monday','tuesday','wednesday','thursday','friday'].map(d=>`${d.charAt(0).toUpperCase()+d.slice(1)} `).join('')}
Payout Currency
${['RM','SGD','USD','GBP','AED','AUD','JPY','INR','EUR','CAD'].map(c=>`${c} `).join('')}
Enable automatic payouts on schedule (recommended) Next Scheduled Payout
${getNextPayoutDate(cfg.payoutSchedule,cfg.payoutDay)}
Pending Amount
${cfg.payoutCurrency} 0.00
💸 Request Payout Now ➕ Additional Payout Accounts (e.g. SGD account for Singapore revenue)
${cfg.additionalAccounts.length===0
?'
No additional accounts added yet.
'
:cfg.additionalAccounts.map((a,i)=>`
${a.bankName} — ${a.currency}
${a.accountName} · ••••${a.accountNo.slice(-4)} · ${a.bankCountry}
Remove `).join('')}
+ Add Another Bank Account 🔒 Security Notice: Your bank account details are encrypted and stored locally. MyTalent Jobs uses bank-grade AES-256 encryption. Account numbers are masked in displays and logs. Only authorised finance personnel can view full account details. All payout transfers are verified via your registered finance email. Never share your API keys or gateway credentials with anyone.
`;
}
function getNextPayoutDate(schedule, day){
const now = new Date();
const days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'];
if(schedule==='daily'){ const d=new Date(now); d.setDate(d.getDate()+1); return d.toLocaleDateString('en-GB',{weekday:'long',day:'2-digit',month:'short',year:'numeric'}); }
if(schedule==='weekly'){
const target = days.indexOf(day||'friday');
var d = new Date(now); var diff=(target-d.getDay()+7)%7||7;
d.setDate(d.getDate()+diff);
return d.toLocaleDateString('en-GB',{weekday:'long',day:'2-digit',month:'short',year:'numeric'});
}
if(schedule==='monthly'){ const d=new Date(now.getFullYear(),now.getMonth()+1,1); return d.toLocaleDateString('en-GB',{day:'2-digit',month:'short',year:'numeric'}); }
return 'On request';
}
function savePayoutSettings(){
const fields = ['companyName','regNo','taxNo','contactName','contactEmail','contactPhone',
'bankCountry','bankName','accountName','accountNo','accountType','branchName',
'branchCode','swiftCode','ibanNo','fpxId','payNowProxy','upiId',
'payoutSchedule','payoutDay','payoutMinAmt','payoutCurrency','stripeKey','paypalEmail'];
fields.forEach(f=>{
const el = document.getElementById('payout_'+f);
if(el) PAYOUT_CFG[f] = el.value;
});
PAYOUT_CFG.autoPayoutEnabled = (document.getElementById('payout_auto')||{}).checked;
PAYOUT_CFG.gateway = PAYOUT_CFG.gateway||'stripe';
if(!PAYOUT_CFG.companyName){ showToast('Please enter your company name','⚠️'); return; }
if(!PAYOUT_CFG.bankName) { showToast('Please select your bank','🏦'); return; }
if(!PAYOUT_CFG.accountName) { showToast('Please enter account holder name','⚠️'); return; }
if(!PAYOUT_CFG.accountNo) { showToast('Please enter your account number','🏦'); return; }
PAYOUT_CFG.verified = true;
PAYOUT_CFG.verifiedDate = new Date().toLocaleDateString('en-GB',{day:'2-digit',month:'short',year:'numeric'});
if(savePayoutCfg()){
const st = document.getElementById('payoutSaveStatus');
if(st){ st.textContent='✅ Saved at '+new Date().toLocaleTimeString(); st.style.color='var(--green)'; }
showToast('Banking details saved! 🏦 Payouts activated.','✅');
if(typeof DB!=='undefined') DB.addAudit('U001','PAYOUT_SETUP',`Bank account configured: ${PAYOUT_CFG.bankName} — ${PAYOUT_CFG.bankCountry}`);
setTimeout(()=>{ document.getElementById('settingsTabContent').innerHTML=renderPayoutSettings(); },1500);
} else{
showToast('Save failed — please try again','❌');
}
}
function testPayoutAccount(){
if(!PAYOUT_CFG.accountNo){ showToast('Please enter and save your bank account first','⚠️'); return; }
showToast('Sending verification micro-deposit (RM 0.01)... Check your bank in 1-2 business days.','🔍');
if(typeof DB!=='undefined') DB.addAudit('U001','PAYOUT_TEST',`Test micro-deposit sent to ${PAYOUT_CFG.bankName}`);
}
function addAdditionalAccount(){
const bankCountry = prompt('Bank Country Code (e.g. SG, AU, GB, US):')?.toUpperCase()||'SG';
const bankName = prompt('Bank Name:')||'';
const accountName = prompt('Account Holder Name:')||'';
const accountNo = prompt('Account Number:')||'';
const currency = prompt('Currency (e.g. SGD, AUD, USD):')?.toUpperCase()||'SGD';
if(!bankName||!accountNo){ showToast('Account not added — please fill all fields','⚠️'); return; }
PAYOUT_CFG.additionalAccounts.push({ bankCountry, bankName, accountName, accountNo, currency });
savePayoutCfg();
showToast(`${bankName} account added!`,'🏦');
document.getElementById('settingsTabContent').innerHTML = renderPayoutSettings();
}
function removeAdditionalAccount(idx){
if(!confirm('Remove this bank account?')) return;
PAYOUT_CFG.additionalAccounts.splice(idx,1);
savePayoutCfg();
showToast('Account removed','🗑️');
document.getElementById('settingsTabContent').innerHTML = renderPayoutSettings();
}
function openPayoutSettings(){ switchSettingsTab('payout'); showAdminPage('settings',null); }
(function checkPayoutBanner(){
setTimeout(()=>{
const banner = document.getElementById('payoutSetupBanner');
if(!banner) return;
try{
const saved = localStorage.getItem('tn_payout_cfg');
if(saved){
const cfg = JSON.parse(saved);
const isConfigured = cfg.accountNumber&&cfg.accountNumber.length > 4;
if(isConfigured){
banner.style.background = 'rgba(30,58,138,.07)';
banner.style.borderColor = 'rgba(30,58,138,.25)';
banner.innerHTML = `
✅
Payout Account Configured
Bank: ${cfg.bankName||'—'} · Account: ••••${String(cfg.accountNumber||'').slice(-4)} · Next payout: ${cfg.nextPayout||'Pending'}
✏️ Edit Payout Settings
`;
}
}
} catch(e){}
}, 700);
})();
function renderGeneralSettings(){
const c = ADMIN_CFG;
return `
🏢 Platform Identity Platform Name
Tagline g-field">Support Email >
" value="${c.billingEmail}">
Admin Email
Phone Number
Default Country
${Object.entries(typeof COUNTRIES!=='undefined'?COUNTRIES:{}).map(([k,v])=>`${v.flag||''} ${v.name||k} `).join('')}
Default Currency
${['RM','SGD','USD','GBP','AED','AUD','JPY','INR','EUR','CAD'].map(cur=>`${cur} `).join('')}
Timezone
${['Asia/Kuala_Lumpur','Asia/Singapore','Asia/Tokyo','Asia/Dubai','Europe/London','America/New_York','Australia/Sydney','Asia/Kolkata','Europe/Berlin'].map(tz=>`${tz} `).join('')}
Address
💼 Job & Candidate Settings
${toggleRow('cfg_autoExpireJobs', c.autoExpireJobs, 'Auto-Expire Jobs', 'Automatically deactivate job listings after the expiry period')}
${toggleRow('cfg_requireApproval', c.requireApproval, 'Require Job Approval', 'All new job posts must be approved by an admin before going live')}
${toggleRow('cfg_allowRemote', c.allowRemote, 'Allow Remote Jobs', 'Enable remote/work-from-home job type filter')}
💾 Save General Settings
`;
}
function renderPricingSettings(){
const plans = ADMIN_CFG.plans;
const keys = ['trial','basic','pro','enterprise'];
return `
💰 Subscription Plans Configure pricing, features and limits for each plan
${keys.map(k=>{
const p = plans[k];
return `
`;
}).join('')}
💾 Save Pricing Plans
`;
}
function renderPackageSettings(){
const ads = ADMIN_CFG.adPackages;
const creds = ADMIN_CFG.creditPackages;
return `
📣 Job Advertisement Packages + Add Package Slots
Label
Price (RM)
Per Unit
Saving %
Badge
Active
🔍 Resume Search Credit Packages + Add Package Credits
Label
Price (RM)
Per Unit
Saving %
Badge
Active
💾 Save Packages
`;
}
function renderTaxSettings(){
const taxes = ADMIN_CFG.taxRates;
return `
🧾 Tax & SST Rates by Country Applied automatically at checkout per employer's country
${Object.entries(taxes).map(([code,t])=>{
const cc = typeof COUNTRIES!=='undefined' ? (COUNTRIES[code]||{}) : {};
return `
${cc.flag||'🌐'}
${cc.name||code} (${code})
`;
}).join('')}
💾 Save Tax Rates
`;
}
function renderRoleSettings(){
const allPerms = ['all','manage_jobs','manage_users','manage_candidates','manage_employers','view_analytics','view_revenue','manage_billing','export_data','manage_content','manage_tickets','contact_candidates','post_job','search_resume','view_own_analytics','apply','view_jobs','manage_profile','view_reports'];
return `
👥 User Roles & Permissions + New Role
${ADMIN_CFG.roles.map((role,i)=>`
`).join('')}
💾 Save Roles
`;
}
function renderNotifSettings(){
const n = ADMIN_CFG.notifications;
return `
📧 Email Notification Templates
${Object.entries(n).map(([key,t])=>`
${key.replace(/([A-Z])/g,' $1').replace(/^./,s=>s.toUpperCase())}
${toggleInline('notif_'+key, t.enabled, t.enabled?'Enabled':'Disabled')}
`).join('')}
💾 Save Notifications
`;
}
function renderAISettings(){
const ai = ADMIN_CFG.ai;
return `
🤖 AI Configuration
${toggleRow('ai_enabled', ai.enabled, 'Enable AI Features', 'Master switch for all AI-powered features on the platform')}
${toggleRow('ai_autoJobDescription', ai.autoJobDescription, 'Auto Job Description', 'AI writes job descriptions when employer clicks "Generate"')}
${toggleRow('ai_autoCvScreening', ai.autoCvScreening, 'Auto CV Screening', 'AI automatically screens and scores candidate CVs')}
${toggleRow('ai_fraudDetection', ai.fraudDetection, 'Fraud Job Detection', 'AI flags potentially fraudulent job postings for review')}
${toggleRow('ai_salaryBenchmarking', ai.salaryBenchmarking, 'Salary Benchmarking', 'AI-powered salary comparison and market rate insights')}
${toggleRow('ai_floatingAssistant', ai.floatingAssistant, 'Floating AI Assistant', 'Show floating chat assistant for job seekers on the frontend')}
${toggleRow('ai_biInsights', ai.biInsights, 'BI Market Insights', 'AI-generated market intelligence in the search panel')}
ℹ️ Changes to the AI model affect all AI tools including Job Description Generator, CV Screener, Candidate Matcher, Salary Benchmarker, Interview Questions, and the Recruitment Assistant chat.
💾 Save AI Settings
`;
}
function renderSecuritySettings(){
const s = ADMIN_CFG.security;
return `
🔒 Security & Authentication
${toggleRow('sec_require2FA', s.require2FA, 'Require 2FA for Admins', 'All admin accounts must enable two-factor authentication')}
${toggleRow('sec_requireUppercase', s.requireUppercase, 'Require Uppercase Letter', 'Password must contain at least one uppercase character')}
${toggleRow('sec_requireNumber', s.requireNumber, 'Require Number', 'Password must contain at least one numeric digit')}
${toggleRow('sec_requireSpecial', s.requireSpecial, 'Require Special Character', 'Password must contain at least one special character (!@#$...)')}
${toggleRow('sec_allowSocialLogin', s.allowSocialLogin, 'Allow Social Login', 'Enable Google and LinkedIn sign-in buttons on the auth modal')}
💾 Save Security Settings
`;
}
function renderFeatureFlags(){
const f = ADMIN_CFG.features;
const flagDefs = [
{key:'biDashboard', label:'BI Live Dashboard', desc:'Show real-time analytics strip above job listings on the frontend'},
{key:'resumeSearch', label:'Resume Search', desc:'Allow employers to search and view candidate resumes'},
{key:'hiringPipeline', label:'Hiring Pipeline / Kanban', desc:'Enable the drag-and-drop hiring stages pipeline for employers'},
{key:'aiHub', label:'AI Hub', desc:'Show the AI tools hub in the employer dashboard sidebar'},
{key:'globalRegulations', label:'Global Regulations', desc:'Show country-specific employment law info in job modals'},
{key:'multiCurrency', label:'Multi-Currency Support', desc:'Auto-convert prices based on employer country (16 currencies)'},
{key:'floatingAI', label:'Floating AI Assistant', desc:'Show the floating chat bubble on the public-facing frontend'},
{key:'darkMode', label:'Dark Mode UI', desc:'Force dark theme across the entire platform'},
{key:'emailNotifications', label:'Email Notifications', desc:'Send automated emails for applications, payments, expiry alerts'},
{key:'maintenanceMode', label:'🔴 Maintenance Mode', desc:'Take the platform offline and show maintenance page to users'},
];
return `
🚀 Feature Flags Enable or disable platform features without code changes
${flagDefs.map(fd=>toggleRow('feat_'+fd.key, f[fd.key], fd.label, fd.desc, fd.key==='maintenanceMode'?'rgba(239,68,68,.06)':'')).join('')}
⚠️ Feature flags take effect immediately for all users. Disabling a feature hides it from the UI but does not delete any data.
💾 Save Feature Flags
`;
}
function toggleRow(id, checked, label, desc, bg=''){
return `${label}
${desc?`
${desc}
`:''}
`;
}
function toggleInline(id, checked, label){
return ` ${label}
`;
}
function handleToggleChange(id, val){
if(id==='cfg_autoExpireJobs') ADMIN_CFG.autoExpireJobs = val;
if(id==='cfg_requireApproval') ADMIN_CFG.requireApproval = val;
if(id==='cfg_allowRemote') ADMIN_CFG.allowRemote = val;
if(id.startsWith('ai_')) { const k=id.slice(3); if(k in ADMIN_CFG.ai) ADMIN_CFG.ai[k]=val; }
if(id.startsWith('sec_')) { const k=id.slice(4); if(k in ADMIN_CFG.security) ADMIN_CFG.security[k]=val; }
if(id.startsWith('feat_')) { const k=id.slice(5); if(k in ADMIN_CFG.features) ADMIN_CFG.features[k]=val; }
if(id.startsWith('notif_')&&!id.includes('_sub_')&&!id.includes('_body_')){
const k=id.slice(6);
if(ADMIN_CFG.notifications[k]) ADMIN_CFG.notifications[k].enabled=val;
}
}
function saveGeneralSettings(){
const g = id=>(document.getElementById(id)||{value:''}).value;
Object.assign(ADMIN_CFG,{
platformName: g('cfg_platformName'),
platformTagline: g('cfg_platformTagline'),
supportEmail: g('cfg_supportEmail'),
billingEmail: g('cfg_billingEmail'),
adminEmail: g('cfg_adminEmail'),
phone: g('cfg_phone'),
defaultCountry: g('cfg_defaultCountry'),
defaultCurrency: g('cfg_defaultCurrency'),
timezone: g('cfg_timezone'),
address: g('cfg_address'),
maxFreeJobPosts: +g('cfg_maxFreeJobPosts')||3,
jobExpiryDays: +g('cfg_jobExpiryDays')||60,
featuredJobDays: +g('cfg_featuredJobDays')||30,
maxJobsPerEmployer: +g('cfg_maxJobsPerEmployer')||500,
maxTagsPerJob: +g('cfg_maxTagsPerJob')||8,
minSalaryRM: +g('cfg_minSalaryRM')||1200,
maxResumeViewsPerDay: +g('cfg_maxResumeViewsPerDay')||50,
resumeExpiryDays: +g('cfg_resumeExpiryDays')||365,
autoVerifyAfterDays: +g('cfg_autoVerifyAfterDays')||7,
autoExpireJobs: (document.getElementById('cfg_autoExpireJobs')||{}).checked,
requireApproval: (document.getElementById('cfg_requireApproval')||{}).checked,
allowRemote: (document.getElementById('cfg_allowRemote')||{}).checked,
});
saveAdminCfg(); showToast('General settings saved ✅','✅');
}
function savePricingSettings(){
['trial','basic','pro','enterprise'].forEach(k=>{
const g = id=>(document.getElementById(id)||{value:''}).value;
ADMIN_CFG.plans[k].name = g('plan_name_'+k);
ADMIN_CFG.plans[k].price = +g('plan_price_'+k)||0;
ADMIN_CFG.plans[k].duration = g('plan_duration_'+k);
ADMIN_CFG.plans[k].adSlots = +g('plan_adSlots_'+k)||0;
ADMIN_CFG.plans[k].credits = +g('plan_credits_'+k)||0;
ADMIN_CFG.plans[k].active = (document.getElementById('plan_active_'+k)||{}).checked;
const colEl = document.getElementById('plan_color_'+k);
if(colEl) ADMIN_CFG.plans[k].color = colEl.value;
const featEl = document.getElementById('plan_feats_'+k);
if(featEl) ADMIN_CFG.plans[k].features = featEl.value.split('\n').map(s=>s.trim()).filter(Boolean);
if(k==='pro'){ const pop = document.getElementById('plan_popular_pro'); if(pop) ADMIN_CFG.plans[k].popular = pop.checked; }
});
syncPricingToPRICING();
saveAdminCfg(); showToast('Pricing plans saved ✅','💰');
}
function syncPricingToPRICING(){
if(typeof PRICING==='undefined') return;
PRICING.ad = {};
ADMIN_CFG.adPackages.filter(p=>p.active).forEach(p=>{
PRICING.ad[p.qty] = { label:p.label, price:p.price, perUnit:p.perUnit, saving:p.saving||null, badge:p.badge||null };
});
PRICING.credit = {};
ADMIN_CFG.creditPackages.filter(p=>p.active).forEach(p=>{
PRICING.credit[p.qty] = { label:p.label, price:p.price, perUnit:p.perUnit, saving:p.saving||null, badge:p.badge||null };
});
}
function savePackageSettings(){
syncPricingToPRICING();
saveAdminCfg(); showToast('Package settings saved ✅','📦');
}
function saveTaxSettings(){
saveAdminCfg(); showToast('Tax rates saved ✅','🧾');
if(typeof COUNTRY_PAYMENT!=='undefined'){
Object.entries(ADMIN_CFG.taxRates).forEach(([code,t])=>{
if(COUNTRY_PAYMENT[code]){ COUNTRY_PAYMENT[code].taxRate = t.enabled?t.rate:0; COUNTRY_PAYMENT[code].taxLabel = t.name; }
});
}
}
function saveRoleSettings(){
saveAdminCfg(); showToast('Roles & permissions saved ✅','👥');
}
function saveNotifSettings(){
Object.keys(ADMIN_CFG.notifications).forEach(key=>{
const subEl = document.getElementById('notif_sub_'+key);
const bodyEl = document.getElementById('notif_body_'+key);
const enEl = document.getElementById('notif_'+key);
if(subEl) ADMIN_CFG.notifications[key].subject = subEl.value;
if(bodyEl) ADMIN_CFG.notifications[key].body = bodyEl.value;
if(enEl) ADMIN_CFG.notifications[key].enabled = enEl.checked;
});
saveAdminCfg(); showToast('Notification templates saved ✅','📧');
}
function saveAISettings(){
const g = id=>(document.getElementById(id)||{value:''}).value;
ADMIN_CFG.ai.model = g('ai_model');
ADMIN_CFG.ai.maxTokens = +g('ai_maxTokens')||1000;
['enabled','autoJobDescription','autoCvScreening','fraudDetection','salaryBenchmarking','floatingAssistant','biInsights'].forEach(k=>{
const el = document.getElementById('ai_'+k); if(el) ADMIN_CFG.ai[k]=el.checked;
});
saveAdminCfg(); showToast('AI settings saved ✅','🤖');
}
function saveSecuritySettings(){
const g = id=>(document.getElementById(id)||{value:''}).value;
ADMIN_CFG.security.sessionTimeoutMins = +g('sec_sessionTimeoutMins')||480;
ADMIN_CFG.security.maxLoginAttempts = +g('sec_maxLoginAttempts')||5;
ADMIN_CFG.security.passwordMinLength = +g('sec_passwordMinLength')||8;
ADMIN_CFG.security.ipWhitelist = g('sec_ipWhitelist');
['require2FA','requireUppercase','requireNumber','requireSpecial','allowSocialLogin'].forEach(k=>{
const el = document.getElementById('sec_'+k); if(el) ADMIN_CFG.security[k]=el.checked;
});
saveAdminCfg(); showToast('Security settings saved ✅','🔒');
}
function saveFeatureFlags(){
Object.keys(ADMIN_CFG.features).forEach(k=>{
const el = document.getElementById('feat_'+k); if(el) ADMIN_CFG.features[k]=el.checked;
});
saveAdminCfg();
if(ADMIN_CFG.features.maintenanceMode){ showToast('⚠️ MAINTENANCE MODE ENABLED — users will see maintenance page','⚠️'); }
showToast('Feature flags saved ✅','🚀');
}
function saveAllSettings(){
saveGeneralSettings(); savePricingSettings(); savePackageSettings();
saveTaxSettings(); saveRoleSettings(); saveNotifSettings();
saveAISettings(); saveSecuritySettings(); saveFeatureFlags();
showToast('All settings saved successfully ✅','💾');
}
function toggleRolePerm(roleIdx, perm, val){
const role = ADMIN_CFG.roles[roleIdx];
if(!role||role.editable===false) return;
const perms = role.perms||[];
if(val){ if(!perms.includes(perm)) perms.push(perm); }
else { role.perms = perms.filter(p=>p!==perm); }
}
function addNewRole(){
ADMIN_CFG.roles.push({id:'custom_'+Date.now(),name:'New Role',color:'#6b7fa3',perms:[],editable:true});
document.getElementById('settingsTabContent').innerHTML = renderSettingsTab();
}
function addAdPackage(){
ADMIN_CFG.adPackages.push({qty:25,price:1250,label:'25 Job Advertisements',perUnit:'RM 50/ad',saving:'50%',badge:'',active:true});
document.getElementById('settingsTabContent').innerHTML = renderSettingsTab();
}
function addCreditPackage(){
ADMIN_CFG.creditPackages.push({qty:300,price:1200,label:'300 Resume Search Credits',perUnit:'RM 4/search',saving:'60%',badge:'',active:true});
document.getElementById('settingsTabContent').innerHTML = renderSettingsTab();
}
function exportAdminConfig(){
const data = JSON.stringify(ADMIN_CFG, null, 2);
const blob = new Blob([data],{type:'application/json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href=url; a.download='MyTalent Jobs_AdminConfig.json'; a.click();
showToast('Config exported 📤','📤');
}
function resetAdminConfig(){
localStorage.removeItem(ADMIN_CFG_KEY);
location.reload();
}
const _origSAP3 = window.showAdminPage;
window.showAdminPage = function(id, el){
if(_origSAP3) _origSAP3(id, el);
if(id==='settings') setTimeout(renderSettingsPage, 80);
};
setTimeout(syncPricingToPRICING, 500);
var PRICING ={
ad:{
5: { label:'5 Job Advertisements', price:500, perUnit:'RM 100/ad', saving:null, color:'var(--accent)', badge:null },
10: { label:'10 Job Advertisements', price:750, perUnit:'RM 75/ad', saving:'25%', color:'var(--accent2)', badge:'⭐ Best Value' },
20: { label:'20 Job Advertisements', price:1000, perUnit:'RM 50/ad', saving:'50%', color:'#a78bfa', badge:null },
50: { label:'50 Job Advertisements', price:2000, perUnit:'RM 40/ad', saving:'60%', color:'var(--yellow)', badge:null },
},
credit:{
50: { label:'50 Resume Search Credits', price:500, perUnit:'RM 10/search', saving:null, color:'var(--accent)', badge:null },
100: { label:'100 Resume Search Credits', price:800, perUnit:'RM 8/search', saving:'20%', color:'#a78bfa', badge:'🔥 Most Popular' },
200: { label:'200 Resume Search Credits', price:1000, perUnit:'RM 5/search', saving:'50%', color:'var(--yellow)', badge:null },
}
};
var selectedPkg = null;
var selectedPkgType = null;
var selectedPkgQty = 0;
var selectedPkgPrice = 0;
var pricingPayMethod = 'card';
var pricingBank = null;
var pricingWallet = null;
function selectPackage(type, qty, price){
const key = `${type}_${qty}`;
selectedPkg = key;
selectedPkgType = type;
selectedPkgQty = qty;
selectedPkgPrice = price;
document.querySelectorAll('#adPackageList > div, #adPackageList ~ div + div, [id^="pkg_"]').forEach(el=>{
if(el.id&&el.id.startsWith('pkg_')){
const isSelected = el.id===`pkg_${key}`;
el.style.borderColor = isSelected ? 'var(--accent)' : 'var(--border)';
el.style.background = isSelected ? 'rgba(0,120,184,0.05)' : 'var(--card)';
}
});
document.querySelectorAll('[id^="radio_"]').forEach(r =>{
r.style.background = '';
r.style.borderColor = 'var(--border)';
r.textContent = '';
});
const radio = document.getElementById(`radio_${key}`);
if(radio){
radio.style.background = 'var(--accent)';
radio.style.borderColor = 'var(--accent)';
radio.textContent = '✓';
radio.style.color = '#ffffff';
radio.style.fontSize = '0.7rem';
}
const sst = Math.round(price * 0.08);
const total = price + sst;
const info = PRICING[type][qty];
document.getElementById('pkgSummaryEmpty').style.display = 'none';
document.getElementById('pkgSummaryDetail').style.display = 'block';
document.getElementById('ps_name').textContent = info.label;
document.getElementById('ps_price').textContent = `RM ${price.toLocaleString()}`;
document.getElementById('ps_desc').textContent = `${info.perUnit}${info.saving ? ' · Save '+info.saving : ''}`;
document.getElementById('ps_subtotal').textContent = `RM ${price.toLocaleString()}`;
document.getElementById('ps_sst').textContent = `RM ${sst.toLocaleString()}`;
document.getElementById('ps_total').textContent = `RM ${total.toLocaleString()}`;
document.getElementById('ps_payBtn').textContent = `RM ${total.toLocaleString()}`;
}
function setPricingPayMethod(method, el){
pricingPayMethod = method;
pricingBank = null;
pricingWallet = null;
['card','fpx','ew'].forEach(m =>{
const tab = document.getElementById('ppm_'+m);
const panel = document.getElementById('pp_'+(m==='ew'?'ew':m));
if(tab){
tab.style.background = m===method ? 'var(--surface)' : 'transparent';
tab.style.color = m===method ? 'var(--text)' : 'var(--muted)';
tab.style.boxShadow = m===method ? '0 2px 6px rgba(0,0,0,0.3)' : 'none';
}
if(panel) panel.style.display = m===method ? 'block' : 'none';
});
document.querySelectorAll('#pp_fpx > div > div, #pp_ew > div > div').forEach(el=>{
el.style.borderColor = 'var(--border)';
});
}
function selPricingBank(el, name){
pricingBank = name;
document.querySelectorAll('#pp_fpx > div > div').forEach(b=>b.style.borderColor='var(--border)');
el.style.borderColor = 'var(--accent)';
}
function selPricingWallet(el, name){
pricingWallet = name;
document.querySelectorAll('#pp_ew > div > div').forEach(b=>b.style.borderColor='var(--border)');
el.style.borderColor = 'var(--accent)';
}
function updatePricingCard(){
const name = (document.getElementById('pp_name')||{}).value||'';
const num = (document.getElementById('pp_num')||{}).value||'';
const exp = (document.getElementById('pp_exp')||{}).value||'';
const pName = document.getElementById('pp_cardName');
const pNum = document.getElementById('pp_cardNum');
const pExp = document.getElementById('pp_cardExp');
if(pName) pName.textContent = name.toUpperCase()||'YOUR NAME';
if(pNum){
const clean = num.replace(/\s/g,'');
var masked = '';
for(var i=0;i<16;i++){ if(i>0&&i%4===0) masked+=' '; masked += clean[i]||'•'; }
pNum.textContent = masked;
}
if(pExp) pExp.textContent = exp||'MM/YY';
}
function detectPricingCardType(val){
const v = val.replace(/\s/g,'');
const badge = document.getElementById('pp_cardType');
const preview = document.getElementById('pp_cardPreview');
if(!badge) return;
if(v.startsWith('4')) { badge.textContent='VISA'; badge.style.color='rgba(255,255,255,0.85)'; }
else if(v.startsWith('5')) { badge.textContent='Mastercard'; badge.style.color='rgba(255,255,255,0.85)'; }
else if(v.startsWith('3')) { badge.textContent='AMEX'; badge.style.color='rgba(255,255,255,0.85)'; }
else { badge.textContent='CARD'; badge.style.color='rgba(255,255,255,0.4)'; }
}
function processPricingPayment(){
if(!selectedPkg){ showToast('Please select a package first','📦'); return; }
if(pricingPayMethod==='card'){
const name = (document.getElementById('pp_name')||{}).value;
const num = (document.getElementById('pp_num')||{}).value.replace(/\s/g,'');
const exp = (document.getElementById('pp_exp')||{}).value;
const cvv = (document.getElementById('pp_cvv')||{}).value;
if(!name){ showToast('Please enter cardholder name','💳'); return; }
if(num.length < 15){ showToast('Please enter a valid card number','💳'); return; }
if(exp.length < 7) { showToast('Please enter expiry date','📅'); return; }
if(cvv.length < 3) { showToast('Please enter CVV','🔒'); return; }
}
if(pricingPayMethod==='fpx'&&!pricingBank){
showToast('Please select a bank','🏦'); return;
}
if(pricingPayMethod==='ewallet'&&!pricingWallet){
showToast('Please select an e-Wallet','📱'); return;
}
document.getElementById('pricingProcessing').style.display = 'flex';
setTimeout(()=>{
document.getElementById('pricingProcessing').style.display = 'none';
completePricingPurchase();
}, 2500);
}
function completePricingPurchase(){
const cfg = (typeof COUNTRY_PAYMENT!=='undefined'&&COUNTRY_PAYMENT[payCurrentCountry])||{currency:'RM',taxLabel:'SST',taxRate:0.08};
const taxRate = cfg.taxRate||0.08;
const sst = Math.round(selectedPkgPrice * taxRate);
const total = selectedPkgPrice + sst;
const txnId = 'TN' + Date.now().toString().slice(-9).toUpperCase();
const invNo = 'INV-' + new Date().getFullYear() + '-' + String((typeof DB!=='undefined'?DB.transactions.length:0)+1).padStart(4,'0');
const now = new Date();
const dateStr = now.toLocaleDateString('en-GB',{day:'2-digit',month:'short',year:'numeric'}) + ' ' + now.toLocaleTimeString('en-GB',{hour:'2-digit',minute:'2-digit'});
const info = (typeof PRICING!=='undefined'&&PRICING[selectedPkgType]&&PRICING[selectedPkgType][selectedPkgQty])||{label:`${selectedPkgQty} ${selectedPkgType==='ad'?'Job Ads':'Credits'}`};
var methodLabel = 'Credit Card';
if(pricingPayMethod==='fpx') methodLabel = `FPX — ${pricingBank||'Bank'}`;
if(pricingPayMethod==='ewallet') methodLabel = `e-Wallet — ${pricingWallet||'Wallet'}`;
if(pricingPayMethod==='card'){
const num = (document.getElementById('pp_num')||{value:''}).value||'';
const last4 = num.replace(/\s/g,'').slice(-4)||'••••';
const type = (typeof detectCardTypeStr==='function') ? detectCardTypeStr(num) : 'Card';
methodLabel = `${type} ····${last4}`;
}
if(selectedPkgType==='ad'){
ACCOUNT.adSlots.remaining += selectedPkgQty;
ACCOUNT.adSlots.total += selectedPkgQty;
const bal = document.getElementById('bal_ads');
if(bal) bal.textContent = ACCOUNT.adSlots.remaining;
updateAdSlotBadge();
if(typeof DB!=='undefined') DB.addAdSlots(CURRENT_EMP_ID||'E001', selectedPkgQty, total, cfg.currency, methodLabel);
} else{
ACCOUNT.searchCredits.remaining += selectedPkgQty;
ACCOUNT.searchCredits.total += selectedPkgQty;
const bal = document.getElementById('bal_credits');
if(bal) bal.textContent = ACCOUNT.searchCredits.remaining;
updateSearchCreditBadge();
if(typeof DB!=='undefined') DB.addCredits(CURRENT_EMP_ID||'E001', selectedPkgQty, total, cfg.currency, methodLabel);
}
ACCOUNT.totalSpent += total;
const spentEl = document.querySelector('#adm-page-pricing [style*="font-weight:800;color:var(--yellow)"]');
if(spentEl) spentEl.textContent = `${cfg.currency} ${ACCOUNT.totalSpent.toLocaleString()}`;
ACCOUNT.history.unshift({
pkg: info.label, qty: selectedPkgQty, type: selectedPkgType,
price: total, method: methodLabel, date: dateStr,
txnId, invNo, currency: cfg.currency, sst,
});
renderPurchaseHistory();
if(typeof DB!=='undefined'){
DB.addAudit(CURRENT_EMP_ID||'U001','PURCHASE',`Purchased ${info.label} for ${cfg.currency} ${total} via ${methodLabel}`);
DB.save();
}
const sEl = id=>document.getElementById(id);
if(sEl('ps_txn')) sEl('ps_txn').textContent = txnId;
if(sEl('ps_invNo')) sEl('ps_invNo').textContent = invNo;
if(sEl('ps_recPkg')) sEl('ps_recPkg').textContent = info.label;
if(sEl('ps_recMethod')) sEl('ps_recMethod').textContent = methodLabel;
if(sEl('ps_recDate')) sEl('ps_recDate').textContent = dateStr;
if(sEl('ps_recSub')) sEl('ps_recSub').textContent = `${cfg.currency} ${selectedPkgPrice.toLocaleString()}`;
if(sEl('ps_recTaxLbl')) sEl('ps_recTaxLbl').textContent = `${cfg.taxLabel||'SST'} (${(taxRate*100).toFixed(0)}%)`;
if(sEl('ps_recTax')) sEl('ps_recTax').textContent = `${cfg.currency} ${sst.toLocaleString()}`;
if(sEl('ps_recAmt')) sEl('ps_recAmt').textContent = `${cfg.currency} ${total.toLocaleString()}`;
if(sEl('ps_recCredits')) sEl('ps_recCredits').textContent = selectedPkgType==='ad'
? `+${selectedPkgQty} Job Ad Slots → Total: ${ACCOUNT.adSlots.remaining} slots`
: `+${selectedPkgQty} Resume Credits → Total: ${ACCOUNT.searchCredits.remaining} credits`;
if(sEl('ps_successMsg')) sEl('ps_successMsg').textContent = selectedPkgType==='ad'
? `${selectedPkgQty} job ad slots added! You can start posting jobs immediately.`
: `${selectedPkgQty} resume search credits added! Start finding great candidates now.`;
const successEl = document.getElementById('pricingSuccess');
if(successEl) successEl.style.display='flex';
const toastMsg = selectedPkgType==='ad' ? '+'+selectedPkgQty+' Ad Slots' : '+'+selectedPkgQty+' Credits';
showToast('Payment successful! '+toastMsg+' added 🎉','✅');
selectedPkg=null; selectedPkgType=null; selectedPkgQty=0; selectedPkgPrice=0;
pricingBank=null; pricingWallet=null; pricingPayMethod='card';
document.querySelectorAll('[id^="radio_"]').forEach(r=>{ r.textContent=''; r.style.background=''; r.style.borderColor='var(--border)'; r.style.color=''; });
document.querySelectorAll('[id^="pkg_"]').forEach(el=>{ el.style.borderColor='var(--border)'; el.style.background='var(--card)'; });
const emptyEl=document.getElementById('pkgSummaryEmpty'), detailEl=document.getElementById('pkgSummaryDetail');
if(emptyEl) emptyEl.style.display='block';
if(detailEl) detailEl.style.display='none';
['pp_name','pp_num','pp_exp','pp_cvv'].forEach(id=>{ const el=document.getElementById(id); if(el) el.value=''; });
}
function closePricingSuccess(){
const el=document.getElementById('pricingSuccess'); if(el) el.style.display='none';
}
function downloadPricingInvoice(){
const cfg=(typeof COUNTRY_PAYMENT!=='undefined'&&COUNTRY_PAYMENT[payCurrentCountry])||{currency:'RM',taxLabel:'SST',taxRate:0.08};
const h=ACCOUNT.history[0];
if(!h){ showToast('No purchase to download','⚠️'); return; }
const content=[
'TALENT NODE GLOBAL — OFFICIAL TAX INVOICE',
'='.repeat(50),
`Invoice No : ${h.invNo||'—'}`,
`Transaction ID: ${h.txnId||'—'}`,
`Date & Time : ${h.date}`,
'',
`Employer ID : ${CURRENT_EMP_ID||'E001'}`,
`Package : ${h.pkg}`,
'',
`Subtotal : ${h.currency||cfg.currency} ${(h.price-(h.sst||0)).toLocaleString()}`,
`${h.sst!==undefined?(cfg.taxLabel||'SST')+' (8%)':'Tax (0%)'} : ${h.currency||cfg.currency} ${(h.sst||0).toLocaleString()}`,
`Total Paid : ${h.currency||cfg.currency} ${h.price.toLocaleString()}`,
`Payment Method: ${h.method}`,
`Status : PAID ✅`,
'',
'Thank you for using MyTalent Jobs Global!',
'Billing enquiries: billing@mytalentjobs.com',
'Support: support@mytalentjobs.com',
'',
'MyTalent Jobs Global',
'16 Countries · 850,000+ Jobs',
].join('\n');
const blob=new Blob([content],{type:'text/plain'});
const url=URL.createObjectURL(blob);
const a=document.createElement('a');
a.href=url; a.download=`${h.invNo||'MyTalent Jobs'}_Invoice.txt`; a.click();
showToast('Invoice downloaded','📄');
}
function updateAdSlotBadge(){
const sidebarBadge = document.querySelector('.adm-item[onclick*="emp-post"] .abadge');
if(!sidebarBadge){
const item = document.querySelector('.adm-item[onclick*="emp-post"]');
if(item&&ACCOUNT.adSlots.remaining > 0){
const b = document.createElement('span');
b.className='abadge'; b.style.background='var(--accent)'; b.textContent=ACCOUNT.adSlots.remaining+' slots';
item.appendChild(b);
}
} else{
sidebarBadge.textContent = ACCOUNT.adSlots.remaining + ' slots';
}
const slotInfo = document.getElementById('jp_slotInfo');
if(slotInfo) slotInfo.textContent = `You have ${ACCOUNT.adSlots.remaining} job ad slots remaining.`;
}
function updateSearchCreditBadge(){
const item = document.querySelector('.adm-item[onclick*="emp-search"]');
if(item){
var badge = item.querySelector('.abadge');
if(!badge){ badge=document.createElement('span'); badge.className='abadge'; item.appendChild(badge); }
badge.style.background='var(--accent3)';
badge.textContent = ACCOUNT.searchCredits.remaining + ' credits';
}
const creditBadge = document.getElementById('rs_creditBalance');
if(creditBadge) creditBadge.textContent = `${ACCOUNT.searchCredits.remaining} credits remaining`;
}
function renderPurchaseHistory(){
const el = document.getElementById('purchaseHistory');
if(!el) return;
var history = [...ACCOUNT.history];
if(typeof DB!=='undefined'){
const dbTxns = DB.transactions
.filter(t=>t.empId===(CURRENT_EMP_ID||'E001'))
.map(t=>({
pkg: t.plan, qty: 0, type: t.type,
price: t.amount, method: t.method, date: t.date,
txnId: t.id, invNo: t.invoice, currency: t.currency,
sst: t.sst||t.gst||t.vat||t.tax||0
}));
const existingIds = new Set(history.map(h=>h.txnId));
dbTxns.forEach(t=>{ if(!existingIds.has(t.txnId)) history.push(t); });
history.sort((a,b)=>(b.date||'').localeCompare(a.date||''));
}
if(!history.length){
el.innerHTML='No purchases yet. Select a package above to get started.
';
return;
}
el.innerHTML = history.slice(0,20).map((h,i)=>`
${h.pkg}
${h.date} · ${h.method}
${h.txnId?`
${h.txnId}
`:''}
${h.currency||'RM'} ${(h.price||0).toLocaleString()}
✅ Paid
📄 `).join('');
}
function downloadSingleInvoice(idx){
const history = ACCOUNT.history;
const h = history[idx];
if(!h){ showToast('Invoice not found','⚠️'); return; }
const taxRate = 0.08;
const sub = h.price - (h.sst||0);
const content=[
'TALENT NODE GLOBAL — TAX INVOICE',
'='.repeat(50),
`Invoice No : ${h.invNo||'—'}`,
`Transaction ID: ${h.txnId||'—'}`,
`Date : ${h.date}`,
'',
`Package : ${h.pkg}`,
`Subtotal : ${h.currency||'RM'} ${sub.toLocaleString()}`,
`SST (8%) : ${h.currency||'RM'} ${(h.sst||0).toLocaleString()}`,
`Total Paid : ${h.currency||'RM'} ${h.price.toLocaleString()}`,
`Payment Method: ${h.method}`,
`Status : PAID ✅`,
'',
'MyTalent Jobs Global — billing@mytalentjobs.com',
].join('\n');
const blob=new Blob([content],{type:'text/plain'});
const url=URL.createObjectURL(blob);
const a=document.createElement('a');
a.href=url; a.download=`${h.invNo||'MyTalent Jobs'}_Invoice.txt`; a.click();
showToast('Invoice downloaded','📄');
}
const _origViewResume = window.viewResume;
window.viewResume = function(id){
if(ACCOUNT.searchCredits.remaining<=0){
showToast('No search credits remaining. Please purchase more.','🔒');
setTimeout(()=>showAdminPage('pricing',null), 500);
return;
}
ACCOUNT.searchCredits.remaining -= 1;
updateSearchCreditBadge();
const bal = document.getElementById('bal_credits');
if(bal) bal.textContent = ACCOUNT.searchCredits.remaining;
if(ACCOUNT.searchCredits.remaining===5){
showToast('⚠️ Only 5 search credits left! Top up now.','⚠️');
}
if(_origViewResume) _origViewResume(id);
};
const _origSubmitJobPost = window.submitJobPost;
window.submitJobPost = function(){
const title = (document.getElementById('jp_title')||{}).value;
if(!title){ showToast('Please enter a job title','⚠️'); return; }
if(ACCOUNT.adSlots.remaining<=0){
showToast('No job ad slots remaining. Please purchase more.','🔒');
setTimeout(()=>showAdminPage('pricing',null), 500);
return;
}
ACCOUNT.adSlots.remaining -= 1;
updateAdSlotBadge();
const bal = document.getElementById('bal_ads');
if(bal) bal.textContent = ACCOUNT.adSlots.remaining;
showToast(`"${title}" published! ${ACCOUNT.adSlots.remaining} ad slot(s) remaining.`,'🚀');
if(ACCOUNT.adSlots.remaining===1){
setTimeout(()=>showToast('⚠️ Only 1 ad slot left! Top up now.','⚠️'), 1500);
}
setTimeout(()=>{
showAdminPage('emp-search', null);
setTimeout(()=>{
switchSearchTab('resume');
document.getElementById('rs_keyword').value = title;
runResumeSearch();
}, 300);
}, 1200);
};
function checkLowBalance(){
if(ACCOUNT.adSlots.remaining<=1){
showToast(`⚠️ Only ${ACCOUNT.adSlots.remaining} job ad slot(s) left!`,'⚠️');
}
if(ACCOUNT.searchCredits.remaining<=5){
showToast(`⚠️ Only ${ACCOUNT.searchCredits.remaining} search credits left!`,'⚠️');
}
}
function addCreditIndicatorToSearch(){
const toolbar = document.getElementById('resumeResultsList');
if(!toolbar) return;
var indicator = document.getElementById('rs_creditBalance');
if(!indicator){
indicator = document.createElement('div');
indicator.id = 'rs_creditBalance';
indicator.style.cssText = 'font-size:0.72rem;color:var(--muted);background:rgba(124,58,237,0.08);border:1px solid rgba(124,58,237,0.2);border-radius:8px;padding:0.35rem 0.75rem;display:inline-flex;align-items:center;gap:0.4rem;margin-bottom:0.75rem;';
indicator.innerHTML = `🔍 ${ACCOUNT.searchCredits.remaining} search credits remaining · Buy More `;
toolbar.parentNode.insertBefore(indicator, toolbar);
} else{
indicator.querySelector('span').textContent = `${ACCOUNT.searchCredits.remaining} search credits remaining`;
}
}
function addSlotIndicatorToJobPost(){
const publishBtn = document.querySelector('#adm-page-emp-post button[onclick*="submitJobPost"]');
if(publishBtn&&!document.getElementById('jp_slotInfo')){
const info = document.createElement('div');
info.id = 'jp_slotInfo';
info.style.cssText = 'font-size:0.75rem;color:var(--muted);margin-bottom:0.75rem;background:rgba(30,58,138,0.06);border:1px solid rgba(30,58,138,0.15);border-radius:8px;padding:0.5rem 0.85rem;display:flex;justify-content:space-between;align-items:center;';
info.innerHTML = `📣 You have ${ACCOUNT.adSlots.remaining} job ad slots remaining Buy More → `;
publishBtn.parentNode.insertBefore(info, publishBtn);
}
}
const _origInitAdminCharts = initAdminCharts;
document.addEventListener('keydown', function(e){
if(e.key==='Escape'){ closeResumeViewer(); hideBISuggestions(); closePay(); closeEmpReg(); }
});
const DB ={
version:'2.0',
candidates:[
{alertFreq:'weekly',alertOptOut:false,id:'C001',name:'Ahmad Hafiz bin Roslan',email:'ahmad.hafiz@email.com',phone:'+60 12-334 5678',country:'MY',state:'Kuala Lumpur',title:'Senior Software Engineer',exp:'3-5 Years',edu:"Bachelor's",skills:['React','Node.js','AWS','Python','Docker'],salaryExpect:10000,currency:'RM',avail:'Immediately',active:true,verified:true,citizen:true,reloc:true,remote:true,score:94,avatar:'AH',dob:'1990-03-15',gender:'Male',nationality:'Malaysian',visa:'Citizen',languages:['English','Bahasa Malaysia'],certs:['AWS SAA','Google Cloud'],summary:'Full-stack engineer with 5 years fintech/e-commerce. AWS certified. Led teams of 6 engineers.',experience:[{co:'Grab Malaysia',role:'Sr Software Engineer',period:'2022–Present',desc:'Led backend API for 200K+ users.'},{co:'Shopee',role:'Software Engineer',period:'2020–2022',desc:'Built React seller dashboard, page load -40%.'}],status:'active',source:'organic',regDate:'2024-11-12',lastLogin:'2026-05-27',views:142,applications:8},
{id:'C002',name:'Nurul Rahayu binti Ahmad',email:'nurul.rahayu@email.com',phone:'+60 11-223 4567',country:'MY',state:'Johor Bahru',title:'Registered Nurse',exp:'1-3 Years',edu:'Diploma',skills:['Patient Care','BLS','ACLS','ICU','EMR'],salaryExpect:4500,currency:'RM',avail:'1 Month',active:true,verified:true,citizen:true,reloc:true,remote:false,score:88,avatar:'NR',dob:'1993-07-22',gender:'Female',nationality:'Malaysian',visa:'Citizen',languages:['Bahasa Malaysia','English'],certs:['BLS','ACLS','MNB'],summary:'ICU nurse, 3 years KPJ. BLS & ACLS certified. MNB registered.',experience:[{co:'KPJ Johor',role:'Staff Nurse',period:'2023–Present',desc:'ICU critical care, 4 patients/shift.'},{co:'Hospital Sultanah',role:'Junior Nurse',period:'2021–2023',desc:'General ward surgical nursing.'}],status:'active',source:'referral',regDate:'2025-01-08',lastLogin:'2026-05-26',views:87,applications:4},
{id:'C003',name:'Lim Wei Jian',email:'lim.weijian@email.com',phone:'+60 16-445 6789',country:'MY',state:'Penang',title:'Financial Analyst',exp:'3-5 Years',edu:"Bachelor's",skills:['Excel VBA','Bloomberg','CFA','Power BI','SAP'],salaryExpect:8000,currency:'RM',avail:'2 Weeks',active:false,verified:true,citizen:true,reloc:true,remote:true,score:91,avatar:'LW',dob:'1991-05-10',gender:'Male',nationality:'Malaysian',visa:'Citizen',languages:['English','Mandarin','Bahasa Malaysia'],certs:['CFA L2','Bloomberg Market Concepts'],summary:'4 years equity research & M&A advisory at Maybank IB. CFA Level 2 candidate.',experience:[{co:'Maybank Investment Bank',role:'Financial Analyst',period:'2022–Present',desc:'Equity research, 12 listed companies.'},{co:'KPMG',role:'Associate Corporate Finance',period:'2020–2022',desc:'M&A due diligence and valuations.'}],status:'active',source:'linkedin',regDate:'2024-09-20',lastLogin:'2026-05-25',views:112,applications:6},
{id:'C004',name:'Kavitha Rajendran',email:'kavitha.raj@email.com',phone:'+60 13-556 7890',country:'MY',state:'Selangor',title:'HR Manager',exp:'5-10 Years',edu:"Bachelor's",skills:['Recruitment','Employment Act 1955','Payroll','HRMS','Training'],salaryExpect:9000,currency:'RM',avail:'1 Month',active:true,verified:true,citizen:true,reloc:false,remote:false,score:89,avatar:'KR',dob:'1988-11-03',gender:'Female',nationality:'Malaysian',visa:'Citizen',languages:['English','Tamil','Bahasa Malaysia'],certs:['SHRM-CP','HRDF Certified Trainer'],summary:'6 years full-spectrum HR. Expert in Employment Act 1955 and Malaysian IR.',experience:[{co:'Top Glove',role:'HR Manager',period:'2021–Present',desc:'Managed HR for 800-staff facility. Turnover -25%.'},{co:'Grab',role:'HR Executive',period:'2019–2021',desc:'End-to-end recruitment, payroll 200 staff.'}],status:'active',source:'organic',regDate:'2024-12-05',lastLogin:'2026-05-24',views:95,applications:3},
{id:'C005',name:'Chen Xiao Ming',email:'chen.xiaoming@email.com',phone:'+65 9123 4567',country:'SG',state:'Central Region',title:'Data Scientist',exp:'1-3 Years',edu:"Master's",skills:['Python','TensorFlow','PyTorch','SQL','NLP','Spark'],salaryExpect:8500,currency:'SGD',avail:'Immediately',active:true,verified:true,citizen:false,reloc:true,remote:true,score:96,avatar:'CX',dob:'1994-02-28',gender:'Male',nationality:'Malaysian',visa:'EP',languages:['English','Mandarin','Cantonese'],certs:['TF Developer Certificate','AWS ML Specialty'],summary:'NLP & recommendation systems. Master\'s from NUS. Built ML serving 5M+ users.',experience:[{co:'Shopee SG',role:'Data Scientist',period:'2023–Present',desc:'Recommendation engine CTR +18%, fraud detection 97% accuracy.'},{co:'AirAsia',role:'Data Analyst',period:'2021–2023',desc:'Pricing model optimisation and A/B testing.'}],status:'active',source:'linkedin',regDate:'2025-02-14',lastLogin:'2026-05-27',views:203,applications:12},
{id:'C006',name:'Siti Aishah binti Hamid',email:'siti.aishah@email.com',phone:'+60 11-778 9012',country:'MY',state:'Kuala Lumpur',title:'Digital Marketing Manager',exp:'3-5 Years',edu:"Bachelor's",skills:['Google Ads','Meta Ads','SEO','GA4','HubSpot','Content Strategy'],salaryExpect:9000,currency:'RM',avail:'2 Weeks',active:true,verified:true,citizen:true,reloc:false,remote:true,score:87,avatar:'SA',dob:'1992-09-14',gender:'Female',nationality:'Malaysian',visa:'Citizen',languages:['Bahasa Malaysia','English'],certs:['Google Ads Certified','Meta Blueprint'],summary:'5 years performance marketing. Managed RM2M+ annual ad spend at Lazada.',experience:[{co:'Lazada',role:'Digital Marketing Manager',period:'2022–Present',desc:'Led team of 5. Managed RM 2M budget across Google & Meta.'},{co:'Petronas Dagangan',role:'Marketing Executive',period:'2020–2022',desc:'Social media, organic reach +120%.'}],status:'active',source:'referral',regDate:'2025-03-01',lastLogin:'2026-05-22',views:76,applications:5},
{id:'C007',name:'Mohd Faiz bin Ismail',email:'mohd.faiz@email.com',phone:'+60 14-889 0123',country:'MY',state:'Selangor',title:'Civil & Structural Engineer',exp:'3-5 Years',edu:"Bachelor's",skills:['AutoCAD','Civil 3D','STAAD Pro','MS Project','Primavera'],salaryExpect:7000,currency:'RM',avail:'Immediately',active:true,verified:false,citizen:true,reloc:true,remote:false,score:85,avatar:'MF',dob:'1993-04-20',gender:'Male',nationality:'Malaysian',visa:'Citizen',languages:['Bahasa Malaysia','English'],certs:['BEM Graduate Engineer','ISO 9001 Internal Auditor'],summary:'4 years highway and MRT3 viaduct projects. BEM registered Graduate Engineer.',experience:[{co:'Gamuda Engineering',role:'Civil Engineer',period:'2022–Present',desc:'MRT3 viaduct structural design. Managed subcontractors.'},{co:'IJM Corporation',role:'Site Engineer',period:'2021–2022',desc:'Highway earthworks supervision.'}],status:'active',source:'organic',regDate:'2025-01-22',lastLogin:'2026-05-20',views:54,applications:2},
{id:'C008',name:'Ravi Kumar s/o Subramaniam',email:'ravi.kumar@email.com',phone:'+60 13-990 1234',country:'MY',state:'Sabah',title:'Petroleum Engineer',exp:'5-10 Years',edu:"Bachelor's",skills:['Petrel','Eclipse','Reservoir Engineering','HSSE','Production Optimisation'],salaryExpect:16000,currency:'RM',avail:'1 Month',active:false,verified:true,citizen:true,reloc:true,remote:false,score:92,avatar:'RK',dob:'1985-12-08',gender:'Male',nationality:'Malaysian',visa:'Citizen',languages:['English','Tamil','Bahasa Malaysia'],certs:['SPE Member','HSSE Gold Card (PETRONAS)','IWCF Well Control'],summary:'8 years deepwater reservoir management. PETRONAS Carigali & Shell experience.',experience:[{co:'PETRONAS Carigali',role:'Sr Reservoir Engineer',period:'2020–Present',desc:'3 deepwater Sabah fields, production +12%.'},{co:'Shell Malaysia',role:'Reservoir Engineer',period:'2017–2020',desc:'Sarawak gas field reserve estimation.'}],status:'active',source:'organic',regDate:'2024-10-15',lastLogin:'2026-05-18',views:68,applications:3},
{id:'C009',name:"James O'Brien",email:'james.obrien@email.com',phone:'+44 79 1234 5678',country:'GB',state:'London',title:'Software Architect',exp:'10+ Years',edu:"Bachelor's",skills:['Java','Kubernetes','AWS','Microservices','Terraform'],salaryExpect:8500,currency:'GBP',avail:'1 Month',active:true,verified:true,citizen:true,reloc:false,remote:true,score:93,avatar:'JO',dob:'1984-06-15',gender:'Male',nationality:'British',visa:'Citizen',languages:['English'],certs:['AWS SA Professional','CKA'],summary:'10 years cloud-native enterprise systems at HSBC & Barclays. Led architecture for 3M+ banking customers.',experience:[{co:'HSBC',role:'Software Architect',period:'2020–Present',desc:'Microservices for 3M banking customers.'},{co:'Barclays',role:'Sr Engineer',period:'2016–2020',desc:'Core banking modernisation program.'}],status:'active',source:'linkedin',regDate:'2025-04-10',lastLogin:'2026-05-27',views:189,applications:9},
{id:'C010',name:'Maria Santos',email:'maria.santos@email.com',phone:'+971 50 123 4567',country:'AE',state:'Dubai',title:'Finance Manager',exp:'5-10 Years',edu:"Master's",skills:['IFRS','SAP','Financial Modelling','Treasury Management'],salaryExpect:22000,currency:'AED',avail:'2 Weeks',active:true,verified:true,citizen:false,reloc:true,remote:false,score:90,avatar:'MS',dob:'1987-09-25',gender:'Female',nationality:'Filipino',visa:'Work Permit',languages:['English','Filipino'],certs:['CPA','CMA'],summary:'7 years UAE finance. IFRS expert, managed AED 500M treasury at Emirates Group.',experience:[{co:'Emirates Group',role:'Finance Manager',period:'2021–Present',desc:'Treasury and IFRS consolidated reporting.'},{co:'ADNOC',role:'Sr Accountant',period:'2019–2021',desc:'Project accounting and capex tracking.'}],status:'active',source:'referral',regDate:'2025-05-01',lastLogin:'2026-05-26',views:134,applications:7},
{id:'C011',name:'Tanaka Hiroshi',email:'tanaka.h@email.com',phone:'+81 90 1234 5678',country:'JP',state:'Tokyo',title:'IT Project Manager',exp:'5-10 Years',edu:"Bachelor's",skills:['Agile','PMP','JIRA','Stakeholder Management','ITIL'],salaryExpect:450000,currency:'JPY',avail:'3 Months',active:true,verified:true,citizen:true,reloc:false,remote:true,score:88,avatar:'TH',dob:'1990-01-12',gender:'Male',nationality:'Japanese',visa:'Citizen',languages:['Japanese','English'],certs:['PMP','PMI-ACP','Prince2'],summary:'6 years IT PM at Sony & Toyota. Led 20+ cross-functional digital transformation projects.',experience:[{co:'Sony',role:'IT Project Manager',period:'2022–Present',desc:'Digital transformation, JPY 2B budget.'},{co:'Toyota',role:'Project Manager',period:'2020–2022',desc:'ERP implementation across 5 plants.'}],status:'active',source:'organic',regDate:'2025-03-18',lastLogin:'2026-05-25',views:77,applications:4},
{id:'C012',name:'Priya Sharma',email:'priya.sharma@email.com',phone:'+91 98 1234 5678',country:'IN',state:'Bangalore',title:'UX Designer',exp:'3-5 Years',edu:"Bachelor's",skills:['Figma','Adobe XD','User Research','Prototyping','Design Systems'],salaryExpect:80000,currency:'INR',avail:'Immediately',active:true,verified:true,citizen:true,reloc:true,remote:true,score:86,avatar:'PS',dob:'1994-11-30',gender:'Female',nationality:'Indian',visa:'Citizen',languages:['English','Hindi'],certs:['Google UX Design','Interaction Design Foundation'],summary:'4 years UX at Infosys & Flipkart. Checkout redesign improved conversion +35%.',experience:[{co:'Flipkart',role:'UX Designer',period:'2023–Present',desc:'Checkout redesign, conversion +35%.'},{co:'Infosys',role:'UI/UX Designer',period:'2021–2023',desc:'Enterprise app design systems for BFSI clients.'}],status:'active',source:'linkedin',regDate:'2025-02-28',lastLogin:'2026-05-24',views:98,applications:6}
],
employers:[
{id:'E001',company:'Grab Malaysia Sdn Bhd',country:'MY',industry:'Technology & IT',size:'500+',plan:'Enterprise',status:'verified',contact:'Sarah Lee',email:'hr@grab.com',phone:'+60 3-2263 8888',regNo:'SSM: 1234567-A',taxNo:'TIN: C1234567890',website:'grab.com',jobsPosted:24,creditsRemain:85,adsRemain:12,totalSpent:18500,regDate:'2024-06-15',lastActive:'2026-05-27',verified:true},
{id:'E002',company:'Maybank Berhad',country:'MY',industry:'Finance & Banking',size:'500+',plan:'Pro',status:'verified',contact:'Ahmad Rashid',email:'hr@maybank.com',phone:'+60 3-2074 8888',regNo:'SSM: 2345678-B',taxNo:'TIN: C2345678901',website:'maybank2u.com',jobsPosted:18,creditsRemain:62,adsRemain:8,totalSpent:12200,regDate:'2024-08-20',lastActive:'2026-05-26',verified:true},
{id:'E003',company:'Shopee Singapore Pte Ltd',country:'SG',industry:'Retail & E-commerce',size:'500+',plan:'Enterprise',status:'verified',contact:'Jenny Tan',email:'talent@shopee.com',phone:'+65 6232 2200',regNo:'UEN: 201632637W',taxNo:'GST: M90123456B',website:'shopee.sg',jobsPosted:31,creditsRemain:120,adsRemain:18,totalSpent:32000,regDate:'2024-07-10',lastActive:'2026-05-27',verified:true},
{id:'E004',company:'HSBC UK Plc',country:'GB',industry:'Finance & Banking',size:'500+',plan:'Enterprise',status:'verified',contact:'David Brown',email:'careers@hsbc.com',phone:'+44 20 7991 8888',regNo:'CRN: 00014259',taxNo:'VAT: GB365684514',website:'hsbc.co.uk',jobsPosted:42,creditsRemain:200,adsRemain:25,totalSpent:58000,regDate:'2024-05-05',lastActive:'2026-05-25',verified:true},
{id:'E005',company:'Google LLC',country:'US',industry:'Technology & IT',size:'500+',plan:'Enterprise',status:'verified',contact:'Mike Johnson',email:'careers@google.com',phone:'+1 650-253-0000',regNo:'EIN: 77-0493581',taxNo:'EIN: 77-0493581',website:'careers.google.com',jobsPosted:67,creditsRemain:500,adsRemain:50,totalSpent:95000,regDate:'2024-04-01',lastActive:'2026-05-27',verified:true},
{id:'E006',company:'Emirates Group',country:'AE',industry:'Hospitality & Tourism',size:'500+',plan:'Pro',status:'verified',contact:'Ahmed Al-Maktoum',email:'careers@emirates.com',phone:'+971 4 215 1111',regNo:'CR: 12345-UAE',taxNo:'TRN: 100123456789003',website:'emirates.com',jobsPosted:29,creditsRemain:95,adsRemain:15,totalSpent:24500,regDate:'2024-09-12',lastActive:'2026-05-24',verified:true},
{id:'E007',company:'Sony Corporation',country:'JP',industry:'Manufacturing',size:'500+',plan:'Pro',status:'verified',contact:'Kenji Tanaka',email:'recruit@sony.com',phone:'+81 3-6748-2111',regNo:'Corp: 1234567890',taxNo:'InvReg: T-12345678901',website:'sony.com',jobsPosted:15,creditsRemain:45,adsRemain:6,totalSpent:8800,regDate:'2025-01-30',lastActive:'2026-05-22',verified:true},
{id:'E008',company:'Infosys Limited',country:'IN',industry:'Technology & IT',size:'500+',plan:'Enterprise',status:'verified',contact:'Raj Patel',email:'careers@infosys.com',phone:'+91 80-2852-0261',regNo:'CIN: L85110KA1981PLC013133',taxNo:'GST: 29AAACI1681G1ZL',website:'infosys.com',jobsPosted:88,creditsRemain:350,adsRemain:40,totalSpent:72000,regDate:'2024-03-20',lastActive:'2026-05-27',verified:true},
{id:'E009',company:'BMW Group Germany',country:'DE',industry:'Manufacturing',size:'500+',plan:'Pro',status:'verified',contact:'Klaus Mueller',email:'jobs@bmw.de',phone:'+49 89 382-0',regNo:'HRB: 42243',taxNo:'VAT: DE129273398',website:'bmw.com',jobsPosted:22,creditsRemain:70,adsRemain:10,totalSpent:16200,regDate:'2024-11-08',lastActive:'2026-05-23',verified:true},
{id:'E010',company:'Nexus Tech Sdn Bhd',country:'MY',industry:'Technology & IT',size:'51-200',plan:'Basic',status:'pending',contact:'Jason Wong',email:'hr@nexustech.com.my',phone:'+60 3-7890 1234',regNo:'SSM: 9876543-Z',taxNo:'TIN: C9876543210',website:'nexustech.com.my',jobsPosted:5,creditsRemain:15,adsRemain:3,totalSpent:1500,regDate:'2026-05-20',lastActive:'2026-05-27',verified:false}
],
jobs:[
{id:'J001',title:'Senior Software Engineer',company:'Grab Malaysia',empId:'E001',country:'MY',state:'Kuala Lumpur',industry:'Technology & IT',type:'Full-Time',exp:'3-5 Years',edu:"Bachelor's",salMin:8000,salMax:14000,currency:'RM',tags:['React','Node.js','AWS','Python'],desc:'Build scalable APIs and microservices for our ride-hailing platform serving 6M users across SE Asia.',reqs:'5+ years full-stack. Strong cloud architecture. Experience with high-traffic systems.',benefits:'Medical, EPF, SOCSO, Annual leave, Stock options',status:'active',featured:true,urgent:false,posted:'2026-05-20',views:842,applications:48,country_reg:'MY'},
{id:'J002',title:'Financial Analyst',company:'Maybank Berhad',empId:'E002',country:'MY',state:'Kuala Lumpur',industry:'Finance & Banking',type:'Full-Time',exp:'1-3 Years',edu:"Bachelor's",salMin:4500,salMax:8000,currency:'RM',tags:['Excel','Bloomberg','Financial Modelling','CFA'],desc:'Join our investment banking division for equity research and M&A advisory across SE Asia markets.',reqs:'CFA progress preferred. Bloomberg proficient. Strong financial modelling skills.',benefits:'Medical, EPF, Annual bonus, Flexible hours, Learning allowance',status:'active',featured:false,urgent:false,posted:'2026-05-22',views:312,applications:22,country_reg:'MY'},
{id:'J003',title:'Data Scientist',company:'Shopee Singapore',empId:'E003',country:'SG',state:'Central Region',industry:'Technology & IT',type:'Full-Time',exp:'3-5 Years',edu:"Master's",salMin:7000,salMax:12000,currency:'SGD',tags:['Python','TensorFlow','SQL','Spark','NLP'],desc:'Build recommendation engines and fraud detection models for our 300M+ user marketplace.',reqs:"Master's in Data Science or CS. 3+ years ML engineering. LLM experience a plus.",benefits:'Health insurance, Stock options, Flexible WFH, SGD 3K training allowance',status:'active',featured:true,urgent:true,posted:'2026-05-24',views:624,applications:35,country_reg:'SG'},
{id:'J004',title:'HR Business Partner',company:'HSBC UK',empId:'E004',country:'GB',state:'London',industry:'Finance & Banking',type:'Full-Time',exp:'5-10 Years',edu:"Bachelor's",salMin:55000,salMax:75000,currency:'GBP',tags:['HR Strategy','Talent Management','Employment Law','CIPD'],desc:'Strategic HR partnering for our 8,000-strong technology division across London and Edinburgh.',reqs:'CIPD Level 7. 5+ years HRBP in financial services. Strong employment law knowledge.',benefits:'Pension 15%, Private health, 25 days annual leave, Performance bonus',status:'active',featured:false,urgent:false,posted:'2026-05-18',views:445,applications:28,country_reg:'GB'},
{id:'J005',title:'Cloud Solutions Architect',company:'Google LLC',empId:'E005',country:'US',state:'California',industry:'Technology & IT',type:'Full-Time',exp:'5-10 Years',edu:"Bachelor's",salMin:140000,salMax:220000,currency:'USD',tags:['GCP','Kubernetes','Terraform','Python','Architecture'],desc:'Design enterprise cloud solutions and lead technical presales for Fortune 500 clients globally.',reqs:'8+ years cloud architecture. GCP Professional preferred. Technical presentation skills.',benefits:'Full medical/dental/vision, 401k 6% match, RSU, 20 days PTO, Gym stipend',status:'active',featured:true,urgent:false,posted:'2026-05-21',views:1240,applications:62,country_reg:'US'},
{id:'J006',title:'Cabin Crew — International',company:'Emirates Group',empId:'E006',country:'AE',state:'Dubai',industry:'Hospitality & Tourism',type:'Full-Time',exp:'Fresh Graduate',edu:'High School / Diploma',salMin:6500,salMax:9000,currency:'AED',tags:['Customer Service','Languages','Safety','Teamwork'],desc:'Join the world\'s most international airline. Explore 140+ destinations across 6 continents.',reqs:'Min 21 years old. 212cm arm reach. Fluent English. Customer-facing exp preferred.',benefits:'Tax-free salary, Free accommodation, Medical, Travel benefits, 30 days leave',status:'active',featured:true,urgent:true,posted:'2026-05-23',views:2840,applications:186,country_reg:'AE'},
{id:'J007',title:'IT Project Manager',company:'Sony Corporation',empId:'E007',country:'JP',state:'Tokyo',industry:'Manufacturing',type:'Full-Time',exp:'5-10 Years',edu:"Bachelor's",salMin:600000,salMax:900000,currency:'JPY',tags:['PMP','Agile','JIRA','Stakeholder Management'],desc:'Lead digital transformation projects across Sony\'s global product divisions from Tokyo HQ.',reqs:'PMP certified. Bilingual English/Japanese essential. 5+ years IT project delivery.',benefits:'Health insurance, Pension, Annual bonus, Flexitime, Commuter allowance',status:'active',featured:false,urgent:false,posted:'2026-05-19',views:228,applications:15,country_reg:'JP'},
{id:'J008',title:'Software Engineer — AI/ML',company:'Infosys Limited',empId:'E008',country:'IN',state:'Bangalore',industry:'Technology & IT',type:'Full-Time',exp:'3-5 Years',edu:"Bachelor's",salMin:1200000,salMax:2200000,currency:'INR',tags:['Python','TensorFlow','LangChain','NLP','GenAI'],desc:'Build next-gen AI solutions for enterprise clients across healthcare, banking and retail sectors.',reqs:'3+ years ML engineering. LLM/GenAI experience preferred. Strong Python skills.',benefits:'Medical, PF, Gratuity, ESOPs, Flexible WFH 3 days/week',status:'active',featured:true,urgent:false,posted:'2026-05-25',views:978,applications:74,country_reg:'IN'},
{id:'J009',title:'Automotive Engineer',company:'BMW Group',empId:'E009',country:'DE',state:'Munich',industry:'Manufacturing',type:'Full-Time',exp:'3-5 Years',edu:"Bachelor's",salMin:55000,salMax:80000,currency:'EUR',tags:['CAD','CATIA','Automotive Engineering','MATLAB','EV'],desc:'Develop next-generation electric vehicle powertrain systems at our Munich R&D centre.',reqs:'Degree in Automotive/Mechanical Engineering. CATIA proficient. German or English.',benefits:'Company car, Pension 15%, 30 days annual leave, Relocation support EUR 5K',status:'active',featured:false,urgent:false,posted:'2026-05-17',views:334,applications:21,country_reg:'DE'},
{id:'J010',title:'Full Stack Developer',company:'Nexus Tech Sdn Bhd',empId:'E010',country:'MY',state:'Selangor',industry:'Technology & IT',type:'Full-Time',exp:'1-3 Years',edu:"Bachelor's",salMin:4000,salMax:7000,currency:'RM',tags:['Vue.js','Laravel','MySQL','Docker','REST API'],desc:'Build SaaS products for Malaysian SMEs. Fast-growing startup with great culture.',reqs:'2+ years full-stack. Vue.js or React + Laravel/Node. Good English communication.',benefits:'Medical, EPF, Flexible hours, Work from home 2 days/week',status:'active',featured:false,urgent:true,posted:'2026-05-26',views:156,applications:12,country_reg:'MY'},
{id:'J011',title:'Registered Nurse',company:'Sunway Medical Centre',empId:'E001',country:'MY',state:'Selangor',industry:'Healthcare & Medical',type:'Full-Time',exp:'1-3 Years',edu:'Diploma / Degree',salMin:2800,salMax:4500,currency:'RM',tags:['Patient Care','BLS','ICU','EMR','Clinical'],desc:'Join our JCI-accredited medical centre as a registered nurse in our ICU department.',reqs:'MNB registered. BLS certified. Good English. Willing to do shift work.',benefits:'Medical, EPF, Annual leave, Shift allowance, Study sponsorship',status:'active',featured:false,urgent:false,posted:'2026-05-21',views:187,applications:18,country_reg:'MY'},
{id:'J012',title:'Digital Marketing Manager',company:'Grab Malaysia',empId:'E001',country:'MY',state:'Kuala Lumpur',industry:'Marketing & Advertising',type:'Full-Time',exp:'3-5 Years',edu:"Bachelor's",salMin:6000,salMax:10000,currency:'RM',tags:['Google Ads','Meta Ads','SEO','Analytics','Performance Marketing'],desc:'Lead performance marketing for GrabFood and GrabMart across Malaysia and Singapore.',reqs:'5+ years digital marketing. RM1M+ ad spend experience. Google Ads & Meta certified.',benefits:'Medical, EPF, Annual bonus, Flexible hours, ESOP, Free GrabFood credits',status:'active',featured:false,urgent:false,posted:'2026-05-22',views:244,applications:19,country_reg:'MY'}
],
applications:[
{id:'A001',candId:'C001',jobId:'J001',empId:'E001',status:'interview',appliedDate:'2026-05-15',stage:'Screened',notes:'Strong React & AWS. Phone screen passed.',resumeViewed:true},
{id:'A002',candId:'C002',jobId:'J011',empId:'E001',status:'shortlisted',appliedDate:'2026-05-18',stage:'Applied',notes:'MNB registered, BLS certified.',resumeViewed:true},
{id:'A003',candId:'C003',jobId:'J002',empId:'E002',status:'pending',appliedDate:'2026-05-20',stage:'Applied',notes:'CFA L2 in progress.',resumeViewed:false},
{id:'A004',candId:'C005',jobId:'J003',empId:'E003',status:'offer',appliedDate:'2026-05-10',stage:'Offer Sent',notes:'Excellent ML background. Offer SGD 10,500.',resumeViewed:true},
{id:'A005',candId:'C009',jobId:'J004',empId:'E004',status:'interview',appliedDate:'2026-05-12',stage:'Interviewed',notes:'CIPD L7 qualified. Strong banking HR.',resumeViewed:true},
{id:'A006',candId:'C010',jobId:'J006',empId:'E006',status:'hired',appliedDate:'2026-04-28',stage:'Hired',notes:'Excellent candidate. Start date 1 June 2026.',resumeViewed:true},
{id:'A007',candId:'C012',jobId:'J008',empId:'E008',status:'pending',appliedDate:'2026-05-25',stage:'Applied',notes:'',resumeViewed:false},
{id:'A008',candId:'C001',jobId:'J012',empId:'E001',status:'rejected',appliedDate:'2026-05-14',stage:'Rejected',notes:'Prefers SE Asia marketing experience.',resumeViewed:true}
],
users:[
{id:'U001',type:'admin',name:'Super Admin',email:'admin@mytalentjobs.com',pass:'admin123',country:'MY',role:'Platform Administrator',perms:['all'],regDate:'2024-01-01',lastLogin:'2026-05-27',status:'active'},
{id:'U002',type:'employer',name:'Sarah Lee',email:'hr@grab.com',pass:'grab123',country:'MY',empId:'E001',role:'HR Manager',perms:['post_job','search_resume','analytics'],regDate:'2024-06-15',lastLogin:'2026-05-27',status:'active'},
{id:'U003',type:'employer',name:'Jenny Tan',email:'talent@shopee.com',pass:'shopee123',country:'SG',empId:'E003',role:'Talent Lead',perms:['post_job','search_resume'],regDate:'2024-07-10',lastLogin:'2026-05-26',status:'active'},
{id:'U004',type:'jobseeker',name:'Ahmad Hafiz',email:'ahmad.hafiz@email.com',pass:'test123',country:'MY',candId:'C001',role:'Job Seeker',perms:['apply','view_jobs'],regDate:'2024-11-12',lastLogin:'2026-05-27',status:'active'},
{id:'U005',type:'jobseeker',name:'Chen Xiao Ming',email:'chen.xiaoming@email.com',pass:'test123',country:'SG',candId:'C005',role:'Job Seeker',perms:['apply','view_jobs'],regDate:'2025-02-14',lastLogin:'2026-05-27',status:'active'},
{id:'U006',type:'employer',name:'David Brown',email:'careers@hsbc.com',pass:'hsbc123',country:'GB',empId:'E004',role:'Head of Talent',perms:['post_job','search_resume'],regDate:'2024-05-05',lastLogin:'2026-05-25',status:'active'}
],
transactions:[
{id:'T001',empId:'E001',type:'subscription',plan:'Enterprise',amount:4500,currency:'RM',method:'Credit Card \u00b7\u00b7\u00b7\u00b74242',status:'paid',date:'2026-05-01',invoice:'INV-2026-001',sst:360},
{id:'T002',empId:'E001',type:'ad_package',plan:'50 Job Ads',amount:2000,currency:'RM',method:'FPX \u2014 Maybank2u',status:'paid',date:'2026-05-05',invoice:'INV-2026-002',sst:160},
{id:'T003',empId:'E001',type:'credits',plan:'100 Search Credits',amount:800,currency:'RM',method:'Credit Card \u00b7\u00b7\u00b7\u00b74242',status:'paid',date:'2026-05-10',invoice:'INV-2026-003',sst:64},
{id:'T004',empId:'E003',type:'subscription',plan:'Enterprise',amount:4500,currency:'SGD',method:'PayNow',status:'paid',date:'2026-05-02',invoice:'INV-2026-004',gst:405},
{id:'T005',empId:'E004',type:'subscription',plan:'Enterprise',amount:2200,currency:'GBP',method:'Faster Payments',status:'paid',date:'2026-05-03',invoice:'INV-2026-005',vat:440},
{id:'T006',empId:'E005',type:'subscription',plan:'Enterprise',amount:5000,currency:'USD',method:'ACH Transfer',status:'paid',date:'2026-05-01',invoice:'INV-2026-006',tax:0},
{id:'T007',empId:'E010',type:'subscription',plan:'Basic',amount:299,currency:'RM',method:'TNG eWallet',status:'paid',date:'2026-05-20',invoice:'INV-2026-007',sst:24},
{id:'T008',empId:'E002',type:'ad_package',plan:'10 Job Ads',amount:750,currency:'RM',method:'FPX \u2014 CIMB Clicks',status:'paid',date:'2026-05-15',invoice:'INV-2026-008',sst:60},
{id:'T009',empId:'E002',type:'credits',plan:'50 Search Credits',amount:500,currency:'RM',method:'Credit Card \u00b7\u00b7\u00b7\u00b78888',status:'paid',date:'2026-05-16',invoice:'INV-2026-009',sst:40},
{id:'T010',empId:'E006',type:'subscription',plan:'Pro',amount:1400,currency:'AED',method:'Network International',status:'paid',date:'2026-05-04',invoice:'INV-2026-010',vat:70}
],
sessions:[],
audit_log:[
{id:'L001',userId:'U001',action:'LOGIN',detail:'Admin login from KL',timestamp:'2026-05-27 09:00:00',ip:'103.12.34.56'},
{id:'L002',userId:'U002',action:'POST_JOB',detail:'Posted J001 Senior Software Engineer',timestamp:'2026-05-20 10:22:11',ip:'103.12.34.78'},
{id:'L003',userId:'U002',action:'VIEW_RESUME',detail:'Viewed C001 Ahmad Hafiz resume',timestamp:'2026-05-22 14:15:33',ip:'103.12.34.78'},
{id:'L004',userId:'U004',action:'APPLY_JOB',detail:'Applied for J001 at Grab Malaysia',timestamp:'2026-05-15 11:30:00',ip:'175.22.11.44'},
{id:'L005',userId:'U003',action:'POST_JOB',detail:'Posted J003 Data Scientist at Shopee SG',timestamp:'2026-05-24 09:44:22',ip:'119.74.23.11'}
],
balances:{
E001:{adSlots:12,adTotal:50,credits:85,creditTotal:100,plan:'Enterprise'},
E002:{adSlots:8,adTotal:10,credits:62,creditTotal:100,plan:'Pro'},
E003:{adSlots:18,adTotal:50,credits:120,creditTotal:200,plan:'Enterprise'},
E004:{adSlots:25,adTotal:50,credits:200,creditTotal:200,plan:'Enterprise'},
E005:{adSlots:50,adTotal:50,credits:300,creditTotal:500,plan:'Enterprise'},
E006:{adSlots:15,adTotal:20,credits:95,creditTotal:100,plan:'Pro'},
E007:{adSlots:6,adTotal:10,credits:45,creditTotal:50,plan:'Pro'},
E008:{adSlots:40,adTotal:50,credits:350,creditTotal:500,plan:'Enterprise'},
E009:{adSlots:10,adTotal:20,credits:70,creditTotal:100,plan:'Pro'},
E010:{adSlots:1,adTotal:5,credits:15,creditTotal:50,plan:'Basic'}
},
save(){try{const s={version:this.version,candidates:this.candidates,employers:this.employers,jobs:this.jobs,applications:this.applications,users:this.users,transactions:this.transactions,balances:this.balances,audit_log:this.audit_log,savedAt:new Date().toISOString()};localStorage.setItem('tn_db_v2',JSON.stringify(s));return true;}catch(e){return false;}},
load(){try{const r=localStorage.getItem('tn_db_v2');if(!r)return false;const s=JSON.parse(r);if(s.version!==this.version)return false;Object.assign(this,s);return true;}catch(e){return false;}},
reset(){localStorage.removeItem('tn_db_v2');},
addAudit(userId,action,detail){const id='L'+String(this.audit_log.length+100).padStart(3,'0');this.audit_log.push({id,userId,action,detail,timestamp:new Date().toLocaleString(),ip:'—'});if(this.audit_log.length>500)this.audit_log=this.audit_log.slice(-500);},
getStats(){return{activeCands:this.candidates.filter(c=>c.status==='active').length,activeEmps:this.employers.filter(e=>e.verified).length,activeJobs:this.jobs.filter(j=>j.status==='active').length,totalApps:this.applications.length,totalRevenue:this.transactions.reduce((s,t)=>s+(t.amount||0),0),hired:this.applications.filter(a=>a.status==='hired').length,pendingVerif:this.employers.filter(e=>!e.verified).length};},
searchCandidates(f={}){return this.candidates.filter(c=>{if(f.keyword){const k=f.keyword.toLowerCase();if(!c.name.toLowerCase().includes(k)&&!c.title.toLowerCase().includes(k)&&!(c.skills||[]).some(s=>s.toLowerCase().includes(k))&&!(c.summary||'').toLowerCase().includes(k))return false;}if(f.country&&c.country!==f.country)return false;if(f.state&&!c.state.includes(f.state))return false;if(f.exp&&c.exp!==f.exp)return false;if(f.edu&&!c.edu.includes(f.edu))return false;if(f.active&&!c.active)return false;if(f.verified&&!c.verified)return false;if(f.remote&&!c.remote)return false;if(f.reloc&&!c.reloc)return false;return true;});},
searchJobs(f={}){return this.jobs.filter(j=>{if(j.status!=='active')return false;if(f.keyword){const k=f.keyword.toLowerCase();if(!j.title.toLowerCase().includes(k)&&!j.company.toLowerCase().includes(k)&&!j.industry.toLowerCase().includes(k)&&!(j.tags||[]).some(t=>t.toLowerCase().includes(k)))return false;}if(f.country&&j.country!==f.country)return false;if(f.state&&j.state!==f.state)return false;if(f.industry&&j.industry!==f.industry)return false;if(f.type&&j.type!==f.type)return false;return true;});},
addJob(data){const id='J'+String(this.jobs.length+100).padStart(3,'0');const job={id,...data,posted:new Date().toISOString().split('T')[0],views:0,applications:0,status:'active'};this.jobs.push(job);const e=this.employers.find(x=>x.id===data.empId);if(e)e.jobsPosted++;if(this.balances[data.empId])this.balances[data.empId].adSlots=Math.max(0,this.balances[data.empId].adSlots-1);this.addAudit('SYSTEM','POST_JOB',`Posted ${job.title}`);this.save();return job;},
addTransaction(data){const id='T'+String(this.transactions.length+100).padStart(3,'0');const txn={id,...data,date:new Date().toISOString().split('T')[0],invoice:`INV-${new Date().getFullYear()}-${String(this.transactions.length+1).padStart(3,'0')}`};this.transactions.push(txn);this.save();return txn;},
addCredits(empId,qty,amount,currency,method){if(!this.balances[empId])this.balances[empId]={adSlots:0,adTotal:0,credits:0,creditTotal:0,plan:'Basic'};this.balances[empId].credits+=qty;this.balances[empId].creditTotal+=qty;this.addTransaction({empId,type:'credits',plan:`${qty} Search Credits`,amount,currency,method,status:'paid'});this.save();return this.balances[empId];},
addAdSlots(empId,qty,amount,currency,method){if(!this.balances[empId])this.balances[empId]={adSlots:0,adTotal:0,credits:0,creditTotal:0,plan:'Basic'};this.balances[empId].adSlots+=qty;this.balances[empId].adTotal+=qty;this.addTransaction({empId,type:'ad_package',plan:`${qty} Job Ads`,amount,currency,method,status:'paid'});this.save();return this.balances[empId];},
deductCredit(empId){if(!this.balances[empId]||this.balances[empId].credits<=0)return false;this.balances[empId].credits--;this.save();return true;},
deductAdSlot(empId){if(!this.balances[empId]||this.balances[empId].adSlots<=0)return false;this.balances[empId].adSlots--;this.save();return true;},
updateEmployer(id,data){const i=this.employers.findIndex(e=>e.id===id);if(i===-1)return null;this.employers[i]={...this.employers[i],...data};this.save();return this.employers[i];},
addCandidate(data){const id='C'+String(this.candidates.length+100).padStart(3,'0');const c={id,...data,regDate:new Date().toISOString().split('T')[0],views:0,applications:0,status:'active'};this.candidates.push(c);this.addAudit('SYSTEM','ADD_CANDIDATE',`Added ${c.name}`);this.save();return c;},
updateCandidate(id,data){const i=this.candidates.findIndex(c=>c.id===id);if(i===-1)return null;this.candidates[i]={...this.candidates[i],...data};this.save();return this.candidates[i];},
deleteCandidate(id){this.candidates=this.candidates.filter(c=>c.id!==id);this.applications=this.applications.filter(a=>a.candId!==id);this.save();},
addEmployer(data){const id='E'+String(this.employers.length+100).padStart(3,'0');const e={id,...data,jobsPosted:0,creditsRemain:0,adsRemain:0,totalSpent:0,regDate:new Date().toISOString().split('T')[0],lastActive:new Date().toISOString().split('T')[0],verified:false};this.employers.push(e);this.balances[id]={adSlots:0,adTotal:0,credits:0,creditTotal:0,plan:data.plan||'Basic'};this.addAudit('SYSTEM','ADD_EMPLOYER',`Registered ${e.company}`);this.save();return e;},
updateApplicationStatus(appId,status,stage,notes=''){const a=this.applications.find(x=>x.id===appId);if(!a)return null;a.status=status;a.stage=stage;if(notes)a.notes=notes;this.save();return a;}
};
var CURRENT_USER=null;
var CURRENT_EMP_ID='E001';
DB.load();
var dbTab = 'candidates';
var dbCandPage = 1, dbEmpPage = 1;
const DB_PAGE_SIZE = 8;
var dbCandSearch = '', dbEmpSearch = '';
var dbCandFilter = {}, dbEmpFilter = {};
var dbEditingCand = null, dbEditingEmp = null;
function renderDBPage(){
const stats = DB.getStats();
const totalRevRM = DB.transactions.filter(t=>t.currency==='RM').reduce((s,t)=>s + (t.amount||0), 0);
const el = document.getElementById('adminContent');
if (!el) return;
el.innerHTML = `
🗄️ MyTalent Jobs Database Management System
localStorage persistence · Version ${DB.version} · Last saved: —
💾 Save DB 📤 Export JSON 📊 Export CSV 🔄 Reset DB
${[
{ico:'👤',val:DB.candidates.length,lbl:'Candidates',cls:'sc-a'},
{ico:'🟢',val:DB.candidates.filter(c=>c.active).length,lbl:'Active',cls:'sc-g'},
{ico:'✅',val:DB.candidates.filter(c=>c.verified).length,lbl:'Verified',cls:'sc-a'},
{ico:'🏢',val:DB.employers.length,lbl:'Employers',cls:'sc-g'},
{ico:'💼',val:DB.jobs.filter(j=>j.status==='active').length,lbl:'Active Jobs',cls:'sc-o'},
{ico:'📋',val:DB.applications.length,lbl:'Applications',cls:'sc-p'},
{ico:'🎉',val:stats.hired,lbl:'Hired',cls:'sc-g'},
{ico:'💰',val:'RM '+totalRevRM.toLocaleString(),lbl:'Revenue',cls:'sc-y'},
].map(s=>`
`).join('')}
${[
{id:'candidates',label:'👤 Candidates',count:DB.candidates.length},
{id:'customers',label:'🏢 Customers (Employers)',count:DB.employers.length},
{id:'applications',label:'📋 Applications',count:DB.applications.length},
{id:'transactions',label:'💳 Transactions',count:DB.transactions.length},
{id:'auditlog',label:'📝 Audit Log',count:DB.audit_log.length},
].map(t=>`
${t.label} ${t.count}
`).join('')}
${renderDBTabContent()}
${renderDBModals()}
`;
highlightDBTab();
}
function switchDBTab(tab){
dbTab = tab;
dbCandPage = 1; dbEmpPage = 1;
highlightDBTab();
document.getElementById('dbTabContent').innerHTML = renderDBTabContent();
}
function highlightDBTab(){
document.querySelectorAll('[id^="dbtab_"]').forEach(el =>{
const isActive = el.id==='dbtab_' + dbTab;
el.style.background = isActive ? 'var(--surface)' : 'transparent';
el.style.color = isActive ? 'var(--accent)' : 'var(--muted)';
el.style.boxShadow = isActive ? '0 2px 8px rgba(0,0,0,.3)' : 'none';
});
}
function renderDBTabContent(){
if (dbTab==='candidates') return renderDBCandidates();
if (dbTab==='customers') return renderDBEmployers();
if (dbTab==='applications') return renderDBApplications();
if (dbTab==='transactions') return renderDBTransactions();
if (dbTab==='auditlog') return renderDBAuditLog();
return '';
}
function renderDBCandidates(){
var cands = DB.candidates.filter(c =>{
if (!dbCandSearch) return true;
const q = dbCandSearch.toLowerCase();
return c.name.toLowerCase().includes(q)||c.email.toLowerCase().includes(q) ||
c.title.toLowerCase().includes(q)||(c.skills||[]).some(s=>s.toLowerCase().includes(q)) ||
(c.country||'').toLowerCase().includes(q)||(c.state||'').toLowerCase().includes(q);
});
if (dbCandFilter.country) cands = cands.filter(c=>c.country===dbCandFilter.country);
if (dbCandFilter.status==='active') cands = cands.filter(c=>c.active);
if (dbCandFilter.status==='passive') cands = cands.filter(c=>!c.active);
if (dbCandFilter.verified==='yes') cands = cands.filter(c=>c.verified);
if (dbCandFilter.verified==='no') cands = cands.filter(c=>!c.verified);
if (dbCandFilter.exp) cands = cands.filter(c=>c.exp===dbCandFilter.exp);
const total = cands.length;
const pages = Math.max(1, Math.ceil(total / DB_PAGE_SIZE));
dbCandPage = Math.min(dbCandPage, pages);
const paginated = cands.slice((dbCandPage-1)*DB_PAGE_SIZE, dbCandPage*DB_PAGE_SIZE);
return `
Showing ${paginated.length} of ${total} candidates
${paginated.map(c=>renderCandCard(c)).join('')}
${renderPagination(pages, dbCandPage, 'dbCandPage', 'renderDBCandidates')}
`;
}
function renderCandCard(c){
const cc = typeof COUNTRIES!=='undefined' ? (COUNTRIES[c.country]||{}) : {};
const apps = DB.applications.filter(a=>a.candId===c.id);
const hired = apps.filter(a=>a.status==='hired').length;
return `
${c.avatar||c.name.slice(0,2).toUpperCase()}
${c.name}
${c.title}
${cc.flag||''} ${cc.name||c.country} ${c.state} ${c.exp}
${c.summary||'No summary provided.'}
${(c.skills||[]).slice(0,5).map(s=>`${s} `).join('')}
${(c.skills||[]).length>5?`+${(c.skills||[]).length-5} more `:''}
${c.currency} ${(c.salaryExpect||0).toLocaleString()}
Expected
${apps.length}
Applications
${c.active?'🟢 Active':'⚪ Passive'}
${c.verified?'✅ Verified ':'⏳ Unverified '}
${c.remote?'💻 Remote ':''}
${c.reloc?'🚗 Reloc ':''}
✏️ Edit 📄 Resume ${c.active?'⏸ Deactivate':'▶ Activate'}
${c.verified?'':`✅ Verify `}
🗑
ID: ${c.id} Reg: ${c.regDate||'—'} Views: ${c.views||0}
`;
}
function renderDBEmployers(){
var emps = DB.employers.filter(e =>{
if (!dbEmpSearch) return true;
const q = dbEmpSearch.toLowerCase();
return e.company.toLowerCase().includes(q)||e.email.toLowerCase().includes(q) ||
e.contact.toLowerCase().includes(q)||(e.country||'').toLowerCase().includes(q) ||
(e.industry||'').toLowerCase().includes(q);
});
if (dbEmpFilter.country) emps = emps.filter(e=>e.country===dbEmpFilter.country);
if (dbEmpFilter.plan) emps = emps.filter(e=>e.plan===dbEmpFilter.plan);
if (dbEmpFilter.verified==='yes') emps = emps.filter(e=>e.verified);
if (dbEmpFilter.verified==='no') emps = emps.filter(e=>!e.verified);
const total = emps.length;
const pages = Math.max(1, Math.ceil(total / DB_PAGE_SIZE));
dbEmpPage = Math.min(dbEmpPage, pages);
const paginated = emps.slice((dbEmpPage-1)*DB_PAGE_SIZE, dbEmpPage*DB_PAGE_SIZE);
const totalRevenue = DB.transactions.reduce((s,t)=>s + (t.amount||0), 0);
return `
${[
{ico:'🏢',val:DB.employers.length,lbl:'Total Employers',col:'var(--accent)'},
{ico:'✅',val:DB.employers.filter(e=>e.verified).length,lbl:'Verified',col:'var(--green)'},
{ico:'⏳',val:DB.employers.filter(e=>!e.verified).length,lbl:'Pending',col:'var(--yellow)'},
{ico:'💰',val:'RM '+totalRevenue.toLocaleString(),lbl:'Total Revenue',col:'var(--accent)'},
].map(s=>`
`).join('')}
Showing ${paginated.length} of ${total} customers
${paginated.map(e=>renderEmpCard(e)).join('')}
${renderPagination(pages, dbEmpPage, 'dbEmpPage', 'renderDBEmployers')}
`;
}
function renderEmpCard(e){
const cc = typeof COUNTRIES!=='undefined' ? (COUNTRIES[e.country]||{}) : {};
const bal = DB.balances[e.id]||{};
const txns = DB.transactions.filter(t=>t.empId===e.id);
const spent = txns.reduce((s,t)=>s+(t.amount||0), 0);
const jobs = DB.jobs.filter(j=>j.empId===e.id);
const planColor = {Enterprise:'var(--accent)',Pro:'#a78bfa',Basic:'var(--yellow)', 'Free Trial':'var(--muted)'}[e.plan]||'var(--muted)';
return `
${e.plan}
${e.company.split(' ').map(w=>w[0]).join('').slice(0,2)}
${e.company}
${cc.flag||''} ${cc.name||e.country} · ${e.industry}
${e.contact} · ${e.email}
${bal.adSlots||0}/${bal.adTotal||0}
Ad Slots
${bal.credits||0}/${bal.creditTotal||0}
Credits
${jobs.length}
Jobs Posted
Total Spent ${e.currency||'RM'} ${spent.toLocaleString()}
${e.verified?'✅ Verified ':'⏳ Pending Verification '}
${e.size} Reg: ${e.regDate||'—'}
✏️ Edit
${!e.verified?`✅ Verify `:''}
💳 Txns ${e.status==='suspended'?'▶ Restore':'🚫 Suspend'}
ID: ${e.id} · Reg: ${e.regNo||'—'}
`;
}
function renderDBApplications(){
const apps = [...DB.applications].reverse();
return `
📋 All Applications (${apps.length}) All Status pending shortlisted interview offer hired rejected
ID Candidate Job Employer Stage Status Applied Resume Actions
${apps.map(a =>{
const c = DB.candidates.find(x=>x.id===a.candId);
const j = DB.jobs.find(x=>x.id===a.jobId);
const e = DB.employers.find(x=>x.id===a.empId);
const sCol = {pending:'p-yellow',shortlisted:'p-blue',interview:'p-blue',offer:'p-blue',hired:'p-green',rejected:'p-red'}[a.status]||'p-yellow';
return `${a.id} ${c?c.name:'—'}
${c?c.title:'—'}
${j?j.title:'—'}
${j?j.company:'—'}
${e?e.company:'—'}
${a.stage} ${a.status} ${a.appliedDate} ${a.resumeViewed?'👁':'—'} Hire Reject Interview
`;
}).join('')}
`;
}
function renderDBTransactions(){
const txns = [...DB.transactions].reverse();
const totalRM = DB.transactions.filter(t=>t.currency==='RM').reduce((s,t)=>s+(t.amount||0),0);
const totalAll = DB.transactions.reduce((s,t)=>s+(t.amount||0),0);
return `
${[
{ico:'💳',val:txns.length,lbl:'Total Transactions'},
{ico:'💰',val:'RM '+totalRM.toLocaleString(),lbl:'RM Revenue'},
{ico:'📈',val:DB.transactions.filter(t=>t.type==='subscription').length,lbl:'Subscriptions'},
{ico:'🎯',val:DB.transactions.filter(t=>t.type!=='subscription').length,lbl:'Ad/Credit Purch.'},
].map(s=>`
`).join('')}
💳 Transactions (${txns.length})
Invoice Employer / Customer Type Package Subtotal Tax Total Method Date Status
${txns.map(t =>{
const emp = DB.employers.find(e=>e.id===t.empId);
const tax = t.sst||t.gst||t.vat||t.tax||0;
return `${t.invoice||t.id} ${emp?emp.company:'—'}
${t.empId}
${t.type} ${t.plan} ${t.currency} ${((t.amount||0)-tax).toLocaleString()} ${t.currency} ${tax} ${t.currency} ${(t.amount||0).toLocaleString()} ${t.method} ${t.date} ✅ Paid `;
}).join('')}
`;
}
function renderDBAuditLog(){
const logs = [...DB.audit_log].reverse().slice(0,100);
return `
`;
}
function renderPagination(pages, current, pageVar, renderFn){
if (pages<=1) return '';
const btns = [];
for (var i = 1; i<=pages; i++){
btns.push(`${i} `);
}
return `${btns.join('')}
`;
}
function renderDBModals(){
return `
✕ ➕ Add New Candidate
Fill in the candidate's profile details
Email *
Phone
Country * Select
${Object.entries(typeof COUNTRIES!=='undefined'?COUNTRIES:{}).map(([code,c])=>`${c.flag||''} ${c.name||code} `).join('')}
State / City
Experience * Select
${['Fresh Graduate','1-3 Years','3-5 Years','5-10 Years','10+ Years'].map(e=>`${e} `).join('')}
Education * High School Diploma Bachelor's Master's PhD
Gender Male Female Prefer not to say
Date of Birth
Nationality
Visa Status Citizen PR EP Work Permit Student Tourist
Expected Salary *
Currency
${['RM','SGD','USD','GBP','AED','AUD','JPY','INR','EUR','CAD'].map(c=>`${c} `).join('')}
Availability Immediately 1 Week 2 Weeks 1 Month 3 Months
Match Score (0–100)
Source organic linkedin referral jobstreet other
Status Active Passive
Skills (comma-separated)
Languages (comma-separated)
Certifications (comma-separated)
Professional Summary
✅ Verified 🇲🇾 Citizen 🚗 Open to Reloc 💻 Remote OK
Cancel 💾 Save Candidate
✕ ➕ Add New Customer (Employer)
Fill in the employer company details
Company Name *
Company Type Private Limited Public Listed Sole Proprietor Partnership Government NGO
Country * Select
${Object.entries(typeof COUNTRIES!=='undefined'?COUNTRIES:{}).map(([code,c])=>`${c.flag||''} ${c.name||code} `).join('')}
Industry *
${['Technology & IT','Finance & Banking','Healthcare & Medical','Manufacturing','Construction & Engineering','Education','Retail & E-commerce','Hospitality & Tourism','Oil & Gas','Logistics & Supply Chain','Marketing & Advertising','HR & Recruitment','Legal','Others'].map(i=>`${i} `).join('')}
Company Size 1–10 11–50 51–200 201–500 500+
Subscription Plan Free Trial Basic Pro Enterprise
Contact Person * /label>
Work Email *
Phone
Website
Reg. Number
Tax Number
Ad Slots
Search Credits
Status ✅ Verified ⏳ Pending 🚫 Suspended
Cancel 💾 Save Customer
`;
}
function openAddCandForm(){
dbEditingCand = null;
document.getElementById('candModalTitle').textContent = '➕ Add New Candidate';
['dcf_name','dcf_title','dcf_email','dcf_phone','dcf_state','dcf_nationality','dcf_salary','dcf_skills','dcf_languages','dcf_certs','dcf_summary'].forEach(id=>{ const el=document.getElementById(id); if(el) el.value=''; });
['dcf_country','dcf_exp','dcf_edu','dcf_gender','dcf_dob','dcf_visa','dcf_currency','dcf_avail','dcf_score','dcf_source','dcf_status'].forEach(id=>{ const el=document.getElementById(id); if(el) el.value=''; });
['dcf_verified','dcf_citizen','dcf_reloc','dcf_remote'].forEach(id=>{ const el=document.getElementById(id); if(el) el.checked=(id==='dcf_citizen'); });
document.getElementById('dbCandModal').style.display = 'flex';
}
function openEditCandForm(id){
const c = DB.candidates.find(x=>x.id===id);
if(!c) return;
dbEditingCand = id;
document.getElementById('candModalTitle').textContent = '✏️ Edit Candidate — ' + c.name;
const set = (fid, val)=>{ const el=document.getElementById(fid); if(el) el.value=val||''; };
const setChk = (fid, val)=>{ const el=document.getElementById(fid); if(el) el.checked=!!val; };
set('dcf_name', c.name); set('dcf_title', c.title); set('dcf_email', c.email);
set('dcf_phone', c.phone); set('dcf_country', c.country); set('dcf_state', c.state);
set('dcf_exp', c.exp); set('dcf_edu', c.edu); set('dcf_gender', c.gender);
set('dcf_dob', c.dob); set('dcf_nationality', c.nationality); set('dcf_visa', c.visa);
set('dcf_salary', c.salaryExpect); set('dcf_currency', c.currency);
set('dcf_avail', c.avail); set('dcf_score', c.score); set('dcf_source', c.source);
set('dcf_status', c.active?'active':'passive');
set('dcf_skills', (c.skills||[]).join(', '));
set('dcf_languages', (c.languages||[]).join(', '));
set('dcf_certs', (c.certs||[]).join(', '));
set('dcf_summary', c.summary);
setChk('dcf_verified', c.verified); setChk('dcf_citizen', c.citizen);
setChk('dcf_reloc', c.reloc); setChk('dcf_remote', c.remote);
document.getElementById('dbCandModal').style.display = 'flex';
}
function saveCandForm(){
const g = id=>(document.getElementById(id)||{}).value||'';
const gc = id=>!!(document.getElementById(id)||{}).checked;
const name = g('dcf_name').trim();
const email = g('dcf_email').trim();
const country = g('dcf_country');
if(!name||!email||!country) { showToast('Please fill in Name, Email and Country','⚠️'); return; }
const data ={
name, title:g('dcf_title'), email, phone:g('dcf_phone'),
country, state:g('dcf_state'), exp:g('dcf_exp'), edu:g('dcf_edu'),
gender:g('dcf_gender'), dob:g('dcf_dob'), nationality:g('dcf_nationality'),
visa:g('dcf_visa'), salaryExpect:parseInt(g('dcf_salary'))||0,
currency:g('dcf_currency')||'RM', avail:g('dcf_avail')||'Immediately',
tin:(g('dcf_tin')||'').toUpperCase(),
score:parseInt(g('dcf_score'))||75, source:g('dcf_source')||'organic',
active:g('dcf_status')==='active', verified:gc('dcf_verified'),
citizen:gc('dcf_citizen'), reloc:gc('dcf_reloc'), remote:gc('dcf_remote'),
skills:g('dcf_skills').split(',').map(s=>s.trim()).filter(Boolean),
languages:g('dcf_languages').split(',').map(s=>s.trim()).filter(Boolean),
certs:g('dcf_certs').split(',').map(s=>s.trim()).filter(Boolean),
summary:g('dcf_summary'),
avatar:name.split(' ').map(w=>w[0]).join('').slice(0,2).toUpperCase(),
};
if(dbEditingCand){
DB.updateCandidate(dbEditingCand, data);
showToast(`${name} updated ✅`, '✅');
} else{
DB.addCandidate({...data, experience:[], status:'active'});
showToast(`${name} added to database ✅`, '👤');
}
closeDBModal('dbCandModal');
dbTab = 'candidates';
renderDBPage();
}
function openAddEmpForm(){
dbEditingEmp = null;
document.getElementById('empModalTitle').textContent = '➕ Add New Customer (Employer)';
['def_company','def_contact','def_jobtitle','def_email','def_phone','def_website','def_regno','def_taxno','def_adSlots','def_credits'].forEach(id=>{ const el=document.getElementById(id); if(el) el.value=''; });
['def_country','def_type','def_industry','def_size','def_plan','def_status'].forEach(id=>{ const el=document.getElementById(id); if(el) el.value=''; });
document.getElementById('dbEmpModal').style.display = 'flex';
}
function openEditEmpForm(id){
const e = DB.employers.find(x=>x.id===id);
if(!e) return;
dbEditingEmp = id;
document.getElementById('empModalTitle').textContent = '✏️ Edit Customer — ' + e.company;
const set = (fid, val)=>{ const el=document.getElementById(fid); if(el) el.value=val||''; };
set('def_company',e.company); set('def_contact',e.contact); set('def_email',e.email);
set('def_phone',e.phone); set('def_website',e.website||''); set('def_country',e.country);
set('def_industry',e.industry); set('def_size',e.size); set('def_plan',e.plan);
set('def_regno',e.regNo); set('def_taxno',e.taxNo);
set('def_status',e.verified?'verified':e.status||'pending');
const bal = DB.balances[id]||{};
set('def_adSlots', bal.adSlots||0); set('def_credits', bal.credits||0);
document.getElementById('dbEmpModal').style.display = 'flex';
}
function saveEmpForm(){
const g = id=>(document.getElementById(id)||{}).value||'';
const company = g('def_company').trim();
const email = g('def_email').trim();
const country = g('def_country');
if(!company||!email||!country) { showToast('Please fill in Company, Email and Country','⚠️'); return; }
const status = g('def_status');
const verified = status==='verified';
const data ={
company, contact:g('def_contact'), email, phone:g('def_phone'),
website:g('def_website'), country, industry:g('def_industry'),
size:g('def_size'), plan:g('def_plan'), regNo:g('def_regno'),
taxNo:g('def_taxno'), status, verified,
currency:(typeof COUNTRIES!=='undefined'&&COUNTRIES[country]?COUNTRIES[country].currency:'RM'),
};
const adSlots = parseInt(g('def_adSlots'))||0;
const credits = parseInt(g('def_credits'))||0;
if(dbEditingEmp){
DB.updateEmployer(dbEditingEmp, data);
if(DB.balances[dbEditingEmp]){
DB.balances[dbEditingEmp].adSlots = adSlots;
DB.balances[dbEditingEmp].credits = credits;
DB.balances[dbEditingEmp].plan = data.plan;
}
DB.save();
showToast(`${company} updated ✅`, '✅');
} else{
const e = DB.addEmployer(data);
if(DB.balances[e.id]){
DB.balances[e.id].adSlots = adSlots;
DB.balances[e.id].adTotal = adSlots;
DB.balances[e.id].credits = credits;
DB.balances[e.id].creditTotal = credits;
}
DB.save();
showToast(`${company} added ✅`, '🏢');
}
closeDBModal('dbEmpModal');
dbTab = 'customers';
renderDBPage();
}
function closeDBModal(id){
const el = document.getElementById(id);
if(el) el.style.display = 'none';
}
function dbFilter(tableId, q){
document.querySelectorAll(`#${tableId} tbody tr`).forEach(r =>{
r.style.display = r.textContent.toLowerCase().includes(q.toLowerCase()) ? '' : 'none';
});
}
function filterAppsTable(status){
document.querySelectorAll('#dbt-apps tbody tr').forEach(r =>{
r.style.display = (!status||r.textContent.toLowerCase().includes(status)) ? '' : 'none';
});
}
function dbToggleCand(id){
const c = DB.candidates.find(x=>x.id===id);
if(!c) return;
DB.updateCandidate(id, {active:!c.active});
showToast(`${c.name} → ${!c.active?'Active':'Passive'}`, '✅');
dbTab = 'candidates'; renderDBPage();
}
function dbVerifyCand(id){
DB.updateCandidate(id, {verified:true});
const c = DB.candidates.find(x=>x.id===id);
showToast(`${c?c.name:id} verified ✅`, '✅');
dbTab = 'candidates'; renderDBPage();
}
function dbDelCand(id, name){
if(!confirm(`Delete candidate "${name}"? This cannot be undone.`)) return;
DB.deleteCandidate(id);
showToast(`${name} deleted`, '🗑️');
dbTab = 'candidates'; renderDBPage();
}
function dbVerifyEmp(id){
DB.updateEmployer(id, {verified:true, status:'verified'});
const e = DB.employers.find(x=>x.id===id);
showToast(`${e?e.company:id} verified ✅`, '✅');
dbTab = 'customers'; renderDBPage();
}
function dbSuspendEmp(id, name, currentStatus){
const newStatus = currentStatus==='suspended' ? 'verified' : 'suspended';
const verified = newStatus==='verified';
DB.updateEmployer(id, {status:newStatus, verified});
showToast(`${name} ${newStatus==='suspended'?'suspended 🚫':'restored ✅'}`, newStatus==='suspended'?'🚫':'✅');
dbTab = 'customers'; renderDBPage();
}
function dbViewEmpTxns(empId){
dbEmpSearch = empId;
switchDBTab('transactions');
}
function exportDBJson(){
const data = JSON.stringify({
exportedAt: new Date().toISOString(),
version: DB.version,
candidates: DB.candidates,
employers: DB.employers,
jobs: DB.jobs,
applications: DB.applications,
transactions: DB.transactions,
users: DB.users,
balances: DB.balances,
}, null, 2);
const blob = new Blob([data], {type:'application/json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'MyTalent Jobs_DB_Export.json'; a.click();
showToast('Database exported as JSON 📤', '📤');
}
function exportDBCsv(){
exportCandidatesCSV();
}
function exportCandidatesCSV(){
const header = ['ID','Name','Email','Phone','Country','State','Title','Experience','Education','Salary','Currency','Skills','Languages','Certs','Active','Verified','Score','RegDate'];
const rows = DB.candidates.map(c=>[
c.id, c.name, c.email, c.phone||'', c.country, c.state||'', c.title,
c.exp, c.edu, c.salaryExpect||0, c.currency||'RM',
(c.skills||[]).join('; '), (c.languages||[]).join('; '), (c.certs||[]).join('; '),
c.active?'Yes':'No', c.verified?'Yes':'No', c.score||0, c.regDate||''
].map(v=>`"${String(v).replace(/"/g,'""')}"`));
const csv = [header.join(','), ...rows.map(r=>r.join(','))].join('\n');
const blob = new Blob([csv], {type:'text/csv'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'MyTalent Jobs_Candidates.csv'; a.click();
showToast('Candidates exported as CSV 📊', '📊');
}
function exportEmployersCSV(){
const header = ['ID','Company','Country','Industry','Size','Plan','Contact','Email','Phone','RegNo','TaxNo','Verified','Status','AdSlots','Credits','TotalSpent','RegDate'];
const rows = DB.employers.map(e =>{
const bal = DB.balances[e.id]||{};
const spent = DB.transactions.filter(t=>t.empId===e.id).reduce((s,t)=>s+(t.amount||0),0);
return [
e.id, e.company, e.country, e.industry||'', e.size||'', e.plan||'',
e.contact||'', e.email, e.phone||'', e.regNo||'', e.taxNo||'',
e.verified?'Yes':'No', e.status||'', bal.adSlots||0, bal.credits||0,
spent, e.regDate||''
].map(v=>`"${String(v).replace(/"/g,'""')}"`);
});
const csv = [header.join(','), ...rows.map(r=>r.join(','))].join('\n');
const blob = new Blob([csv], {type:'text/csv'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'MyTalent Jobs_Customers.csv'; a.click();
showToast('Customers exported as CSV 📊', '📊');
}
const _origSAP2 = window.showAdminPage;
window.showAdminPage = function(id, el){
if(_origSAP2) _origSAP2(id, el);
if(id==='database') setTimeout(renderDBPage, 80);
};
const _origFJ=window.filterJobs;
window.filterJobs=function(){
const kw=(document.getElementById('searchKeyword')||{value:''}).value;
const loc=(document.getElementById('searchLocation')||{value:''}).value;
const fc=(document.getElementById('filterCountry')||{value:''}).value;
const fs=(document.getElementById('filterState')||{value:''}).value;
const fi=(document.getElementById('filterIndustry')||{value:''}).value;
const fe=(document.getElementById('filterExp')||{value:''}).value;
var res=DB.searchJobs({keyword:kw||undefined,country:fc||undefined,state:fs||undefined,industry:fi||undefined,exp:fe||undefined});
if(loc)res=res.filter(j=>j.state.toLowerCase().includes(loc.toLowerCase())||j.country.toLowerCase().includes(loc.toLowerCase()));
const types=[];
if((document.getElementById('ft')||{}).checked)types.push('Full-Time');
if((document.getElementById('pt')||{}).checked)types.push('Part-Time');
if((document.getElementById('ct')||{}).checked)types.push('Contract');
if((document.getElementById('rm')||{}).checked)types.push('Remote');
if((document.getElementById('in')||{}).checked)types.push('Internship');
if(types.length)res=res.filter(j=>types.includes(j.type));
renderDBJobsList(res);
if(typeof showAIBIPanel==='function'&&kw){
showAIBIPanel(typeof parseSearchQuery==='function' ? parseSearchQuery(kw) : {q:kw, keywords:[kw], raw:kw});
}
};
function renderDBJobsList(jobs){
const list=document.getElementById('jobsList');
const cnt=document.getElementById('jobCount');
if(cnt)cnt.textContent=jobs.length;
if(!list)return;
if(!jobs.length){list.innerHTML='No jobs match. Try different keywords.
';return;}
list.innerHTML=jobs.map(j=>{
const cc=COUNTRIES[j.country]||{};
const reg=REGULATIONS[j.country];
const regBrief=reg?`${cc.name}: Min wage ${reg.minWage||'—'}`:`${cc.name||j.country}`;
return`${j.company.split(' ').map(w=>w[0]).join('').slice(0,2)}
${j.title}
${j.company} · ${cc.flag||''} ${cc.name||j.country}
${j.featured?'⭐ Featured ':''}
${j.urgent?'🔥 Urgent ':''}
${cc.flag||''} ${j.country} NEW
${(j.tags||[]).map(t=>`${t} `).join('')}
`;
}).join('');
}
function openDBJob(id){
const j=DB.jobs.find(x=>x.id===id); if(!j) return;
j.views=(j.views||0)+1;
const cc=COUNTRIES[j.country]||{};
const reg=REGULATIONS[j.country];
document.getElementById('jmTitle').textContent=j.title;
document.getElementById('jmCo').textContent=`${j.company} · ${cc.flag||''} ${cc.name||j.country} · ${j.type}`;
document.getElementById('jmDesc').textContent=j.desc;
document.getElementById('jmReqs').textContent=j.reqs;
document.getElementById('jmSal').textContent=`${j.currency} ${j.salMin.toLocaleString()} – ${j.salMax.toLocaleString()} · ${j.state}, ${cc.name||j.country}`;
document.getElementById('jmReg').textContent=reg?`${cc.name}: Min wage ${reg.minWage||'—'} · Notice: ${reg.noticePeriod||'—'} · ${reg.workHours||'—'}`:`See ${cc.name||j.country} employment regulations.`;
buildApplyArea(j);
openOv('jobOv');
}
const _origRS=window.runResumeSearch;
window.runResumeSearch=function(){
const kw=(document.getElementById('rs_keyword')||{value:''}).value;
const st=(document.getElementById('rs_state')||{value:''}).value;
const exp=(document.getElementById('rs_exp')||{value:''}).value;
const edu=(document.getElementById('rs_edu')||{value:''}).value;
const active=(document.getElementById('rs_active')||{checked:false}).checked;
const reloc=(document.getElementById('rs_reloc')||{checked:false}).checked;
const remote=(document.getElementById('rs_remote')||{checked:false}).checked;
const verified=(document.getElementById('rs_verified')||{checked:false}).checked;
const res=DB.searchCandidates({keyword:kw||undefined,state:st||undefined,exp:exp||undefined,edu:edu||undefined,active:active||undefined,reloc:reloc||undefined,remote:remote||undefined,verified:verified||undefined});
const list=document.getElementById('resumeResultsList');
const cnt=document.getElementById('rs_count');
if(cnt)cnt.textContent=res.length;
if(!list)return;
list.innerHTML=res.map(c=>`${c.avatar||c.name.slice(0,2).toUpperCase()}
${c.name}
${c.verified?'✅ ':''}
${c.active?'🟢 ':'⚪ '}
${c.title}
📍 ${c.state} ⏱ ${c.exp} 💰 ${c.currency} ${(c.salaryExpect||0).toLocaleString()} 📅 ${c.avail}
${c.summary||'No summary.'}
${(c.skills||[]).slice(0,5).map(s=>`${s} `).join('')}
Expected
${c.currency} ${(c.salaryExpect||0).toLocaleString()}
📄 Resume ⭐ Shortlist 📩 Contact
`).join('');
};
const _origSC=window.searchCandidates;
window.searchCandidates=function(){
const kw=(document.getElementById('cs_keyword')||{value:''}).value;
const st=(document.getElementById('cs_state')||{value:''}).value;
const exp=(document.getElementById('cs_exp')||{value:''}).value;
const edu=(document.getElementById('cs_edu')||{value:''}).value;
const res=DB.searchCandidates({keyword:kw||undefined,state:st||undefined,exp:exp||undefined,edu:edu||undefined});
const grid=document.getElementById('candidateGrid');
const cnt=document.getElementById('cs_count');
if(cnt)cnt.textContent=res.length;
if(grid)grid.innerHTML=res.map(c=>renderCandidateCard(c)).join('');
};
const _origCPP=window.completePricingPurchase;
window.completePricingPurchase=function(){
if(_origCPP)_origCPP();
if(selectedPkgType&&selectedPkgQty&&selectedPkgPrice){
const method=pricingPayMethod==='card'?`Credit Card ····${(document.getElementById('pp_num')||{value:''}).value.replace(/\s/g,'').slice(-4)||'****'}`:pricingPayMethod==='fpx'?`FPX — ${pricingBank||'Bank'}`:pricingWallet||'eWallet';
const cc=COUNTRIES[currentCountry]||{};
if(selectedPkgType==='ad')DB.addAdSlots(CURRENT_EMP_ID,selectedPkgQty,selectedPkgPrice,cc.currency||'RM',method);
else DB.addCredits(CURRENT_EMP_ID,selectedPkgQty,selectedPkgPrice,cc.currency||'RM',method);
DB.save();
}
};
const _origEmpSucc=window.empShowSuccess;
window.empShowSuccess=function(plan,method,amount){
if(_origEmpSucc)_origEmpSucc(plan,method,amount);
const coName=(document.getElementById('e_coName')||{value:'New Company'}).value;
const country=(document.getElementById('e_country')||{value:'MY'}).value;
const ind=(document.getElementById('e_industry')||{value:'Technology'}).value;
const size=(document.getElementById('e_size')||{value:'11-50'}).value;
const email=(document.getElementById('e_email')||{value:'new@company.com'}).value;
const phone=(document.getElementById('e_phone')||{value:''}).value;
const cpName=(document.getElementById('e_cpName')||{value:''}).value;
const existing=DB.employers.find(e=>e.email===email);
if(!existing){
DB.addEmployer({company:coName,country,industry:ind,size,plan:plan||'Basic',status:'pending',contact:cpName,email,phone,regNo:'Pending Verification',taxNo:'Pending Verification',website:''});
DB.save();
}
};
const _origSAP=window.showAdminPage;
window.showAdminPage=function(id,el){
if(_origSAP)_origSAP(id,el);
if(id==='database')setTimeout(renderDBPage,100);
};
setTimeout(()=>{
renderDBJobsList(DB.jobs);
const cf=document.getElementById('filterCountry');
if(cf&&!cf.querySelector('option[value="MY"]')){Object.entries(COUNTRIES).forEach(([code,c])=>{const o=document.createElement('option');o.value=code;o.textContent=`${c.flag} ${c.name}`;cf.appendChild(o);});}
const ns=document.getElementById('navCountrySel');
if(ns&&!ns.querySelector('option[value="MY"]')){Object.entries(COUNTRIES).forEach(([code,c])=>{const o=document.createElement('option');o.value=code;o.textContent=`${c.flag} ${c.name}`;ns.appendChild(o);});}
const ec=document.getElementById('e_country');
if(ec&&!ec.querySelector('option[value="MY"]')){Object.entries(COUNTRIES).forEach(([code,c])=>{const o=document.createElement('option');o.value=code;o.textContent=`${c.flag} ${c.name}`;ec.appendChild(o);});}
const pills=document.getElementById('countryPills');
if(pills&&!pills.querySelector('.cpill')){['MY','SG','ID','AU','GB','US','AE','JP','IN','DE','CA','KR'].forEach(code=>{const c=COUNTRIES[code];if(!c)return;const span=document.createElement('span');span.className='cpill'+(code==='MY'?' active':'');span.id='ctry_'+code;span.textContent=`${c.flag} ${c.name}`;span.onclick=()=>switchCountry(code);pills.appendChild(span);});}
const cg=document.getElementById('countriesGrid');
if(cg&&!cg.querySelector('.ctry-card')){const cjs=DB.jobs.reduce((m,j)=>{m[j.country]=(m[j.country]||0)+1;return m;},{});Object.entries(COUNTRIES).forEach(([code,c])=>{const div=document.createElement('div');div.className='ctry-card'+(code==='MY'?' active':'');div.id='ctry_card_'+code;div.onclick=()=>switchCountry(code);div.innerHTML=`${c.name}
${cjs[code]||0} jobs now · ${c.jobs} total
Avg ${c.avgSal}
`;cg.appendChild(div);});}
const stats=DB.getStats();
const dashEl=id2=>document.getElementById(id2);
if(dashEl('dash_activejobs'))dashEl('dash_activejobs').textContent=stats.activeJobs.toLocaleString();
if(dashEl('dash_employers'))dashEl('dash_employers').textContent=stats.activeEmps.toLocaleString();
if(dashEl('dash_candidates'))dashEl('dash_candidates').textContent=DB.candidates.length.toLocaleString();
if(dashEl('dash_applications'))dashEl('dash_applications').textContent=stats.totalApps.toLocaleString();
const indMap=DB.jobs.reduce((m,j)=>{m[j.industry]=(m[j.industry]||0)+1;return m;},{});
for(var i=0;i<12;i++){const el2=document.getElementById('ind'+i);if(el2){const vals=Object.values(indMap);el2.textContent=(vals[i]||Math.floor(Math.random()*200+30))+' jobs';}}
DB.save();
},350);
filterJobs();
pt>MyTalent Jobs is a neutral job-matching platform that connects employers and candidates. By using this platform, you acknowledge the following:
${[
['🔗','Connecting Platform Only','We are not an employment agency, staffing firm, or recruiter. We facilitate connections — we are not a party to any employment agreement.'],
['📋','No Endorsement','We do not endorse, verify, or guarantee any job listing, employer, candidate, or resume on this platform.'],
['⚠️','No Warranties','We make no representations as to the accuracy, legality, safety, or completeness of any content submitted by users.'],
['🚫','Fraud Awareness','Always be alert to scam jobs. Never pay upfront fees or share banking details before employment begins.'],
['⚖️','Your Responsibility','Candidates and employers are solely responsible for verifying information and complying with applicable employment laws.'],
['🌍','Governing Law','This platform is governed by the laws of Malaysia. Disputes fall under Malaysian jurisdiction.'],
].map(([i,t,d])=>`
`).join('')}
By continuing to use MyTalent Jobs, you confirm you have read and accepted this disclaimer. Contact: legal@mytalentjobs.com
✅ I Understand ⬇️ Download Close
und:#e2e8f0">ALREADY A MEMBER?
🔑 Log In to Apply
${['Free to create, free to apply','One-click apply with saved profile','Track all your applications','AI-powered job matching'].map(b=>`
✓ ${b}
`).join('')}
Maybe later
`;
m.addEventListener('click', e=>{ if (e.target===m) m.style.display = 'none'; });
}
function showRegisterModal(jobId){
const btn = document.querySelector('[onclick*="register"],[onclick*="Register"]');
if (btn) btn.click();
else showToast('Please sign up to apply', '📋');
if (jobId) sessionStorage.setItem('pendingApplyJobId', String(jobId));
}
function showLoginModal(jobId){
const btn = document.querySelector('[onclick*="login"],[onclick*="Login"],[onclick*="doLogin"]');
if (btn) btn.click();
else showToast('Please log in to apply', '🔑');
if (jobId) sessionStorage.setItem('pendingApplyJobId', String(jobId));
}
(function checkPendingApply(){
const orig = window.doLogin;
if (typeof orig==='function'){
window.doLogin = function(...args){
const result = orig.apply(this, args);
setTimeout(() =>{
const pending = sessionStorage.getItem('pendingApplyJobId');
if (pending&&typeof currentUser!=='undefined'&¤tUser?.role==='seeker'){
sessionStorage.removeItem('pendingApplyJobId');
handleApplyClick(pending);
}
}, 800);
return result;
};
}
})();
window.handleApplyClick = handleApplyClick;
window.showApplyAuthGate = showApplyAuthGate;
t>', user.name || '');
const title = prompt('Your job title / headline:', user.title || user.jobTitle || '');
if (name !== null) {
user.name = name;
user.title = title || user.title;
localStorage.setItem('tn_user_session', JSON.stringify(user));
// Update in DB
if (typeof DB !== 'undefined') {
const cand = DB.candidates.find(c => String(c.id) === String(user.id));
if (cand) { cand.name = name; cand.title = title; DB.save(); }
}
showToast('Profile updated ✅', '👤');
openCandidateProfile(); // refresh
}
}
// ── Resume pending apply after login ──
window.addEventListener('mtj_auth_success', () => {
const pendingJob = sessionStorage.getItem('mtj_pending_apply');
if (pendingJob) {
sessionStorage.removeItem('mtj_pending_apply');
setTimeout(() => openJobApply(pendingJob), 500);
}
});
// Wire global access
window.openJobApply = openJobApply;
window.submitJobApplication = submitJobApplication;
window.openCandidateProfile = openCandidateProfile;
window.editCandidateProfile = editCandidateProfile;
window.getLoggedInUser = getLoggedInUser;
window.handleApplyResumeUpload = handleApplyResumeUpload;
querySelectorAll('.crm-client-row').forEach(row=>{
row.style.display = (status==='all' || row.dataset.status===status) ? '' : 'none';
});
};
// ── Export clients to CSV ──
window.exportClients = function(){
const clients = CRM_DB.clients;
const rows = [['Name','Industry','Contact','Email','Phone','Status','Tier','Open Jobs','Total Placements','Joined']].concat(
clients.map(c=>[c.name,c.industry,c.contact||'',c.email||'',c.phone||'',c.status,c.tier,c.jobsOpen||0,c.totalPlacements||0,c.joinedAt||''])
);
const csv = rows.map(r=>r.map(v=>'"'+String(v).replace(/"/g,'""')+'"').join(',')).join('\n');
const a = document.createElement('a');
a.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv);
a.download = 'clients-' + new Date().toISOString().split('T')[0] + '.csv';
a.click();
if(typeof showToast==='function') showToast('Clients exported ✅','📥');
};
// ── Edit client ──
window.openEditClient = function(id){
const c = CRM_DB.clients.find(x=>x.id===id);
if(!c) return;
var modal = document.getElementById('editClientModal');
if(!modal){ modal = document.createElement('div'); modal.id='editClientModal'; document.body.appendChild(modal); }
modal.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:950;display:flex;align-items:center;justify-content:center;padding:1rem';
const industries = ['Technology & IT','Finance & Banking','Healthcare & Medical','Oil, Gas & Energy','Engineering & Construction','Retail & FMCG','Logistics & Supply Chain','Hospitality & Tourism','Education & Training','Other'];
modal.innerHTML=`
${[['Company Name','text','ec_name',c.name],['Contact Person','text','ec_contact',c.contact||''],['Email','email','ec_email',c.email||''],['Phone','tel','ec_phone',c.phone||''],['Open Jobs','number','ec_jobs',c.jobsOpen||0]].map(([l,t,id,val])=>
`
${l}
`
).join('')}
Industry
${industries.map(i=>`${i} `).join('')}
Tier
${['basic','pro','enterprise','prospect'].map(t=>`${t} `).join('')}
Status
${['active','prospect','inactive'].map(s=>`${s} `).join('')}
Save Changes
`;
};
window.updateClient = function(id){
const cl = CRM_DB.clients;
const c = cl.find(x=>x.id===id);
if(!c) return;
c.name = document.getElementById('ec_name')?.value || c.name;
c.contact = document.getElementById('ec_contact')?.value || '';
c.email = document.getElementById('ec_email')?.value || '';
c.phone = document.getElementById('ec_phone')?.value || '';
c.jobsOpen= parseInt(document.getElementById('ec_jobs')?.value||0);
c.industry= document.getElementById('ec_ind')?.value || c.industry;
c.tier = document.getElementById('ec_tier')?.value || c.tier;
c.status = document.getElementById('ec_status')?.value || c.status;
CRM_DB.saveClients(cl);
document.getElementById('editClientModal')?.remove();
if(typeof saGo==='function') saGo('crm_clients');
if(typeof showToast==='function') showToast('Client updated ✅','🏢');
};
// ── Delete client ──
window.deleteClient = function(id){
const c = CRM_DB.clients.find(x=>x.id===id);
if(!c) return;
if(!confirm('Delete client "'+c.name+'"? This cannot be undone.')) return;
const cl = CRM_DB.clients.filter(x=>x.id!==id);
CRM_DB.saveClients(cl);
if(typeof saGo==='function') saGo('crm_clients');
if(typeof showToast==='function') showToast('Client deleted','🗑');
};
// ── Enhanced openClientDetail (dark-theme SA panel version) ──
const _origOpenClientDetail = window.openClientDetail;
window.openClientDetail = function(id){
const c = CRM_DB.clients.find(x=>x.id===id);
if(!c){ if(typeof _origOpenClientDetail==='function') _origOpenClientDetail(id); return; }
const placements = CRM_DB.placements.filter(p=>p.clientId===id);
const revenue = placements.filter(p=>p.feePaid).reduce((s,p)=>s+Math.round(p.salary*12*(p.feeRate/100)),0);
const pendingFees = placements.filter(p=>!p.feePaid).reduce((s,p)=>s+Math.round(p.salary*12*(p.feeRate/100)),0);
const statusColor = {active:'#22c55e',inactive:'#ef4444',prospect:'#f59e0b'};
const tierColor = {enterprise:'#FF7A00',pro:'#4f8ef7',basic:'#22c55e',prospect:'#94a3b8'};
const placementStatus = {active:'#22c55e',guaranteed:'#4f8ef7',fallen_off:'#ef4444',pending:'#f59e0b'};
var modal = document.getElementById('clientDetailModal');
if(!modal){ modal = document.createElement('div'); modal.id='clientDetailModal'; document.body.appendChild(modal); }
modal.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:950;display:flex;align-items:center;justify-content:center;padding:1rem;overflow-y:auto';
modal.innerHTML=`
🏢
${c.tier}
${c.status}
✕
${[['Open Jobs',c.jobsOpen||0,'#FF7A00'],['Placements',placements.length,'#4f8ef7'],['Revenue','RM '+(revenue?revenue.toLocaleString():'0'),'#22c55e'],['Pending','RM '+(pendingFees?pendingFees.toLocaleString():'0'),'#f59e0b']].map(([l,v,clr])=>
`
`
).join('')}
📞 Contact
${[['Contact',c.contact||'—'],['Email',c.email||'—'],['Phone',c.phone||'—'],['Client Since',c.joinedAt||'—']].map(([k,v])=>
`
${k}: ${v}
`
).join('')}
📋 Placements (${placements.length})
+ Add Placement
${placements.length===0
? `
No placements for this client yet.
`
: placements.map(p=>{
const fee = Math.round(p.salary*12*(p.feeRate/100));
const sc = placementStatus[p.status]||'#94a3b8';
return `
${p.candName}
${p.jobTitle} · ${p.recruiterName}
RM ${p.salary.toLocaleString()}/mo
Fee: RM ${fee.toLocaleString()}
${p.status.replace('_',' ')}
${p.feePaid?'✅ Paid':'⏳ Pending'}
`;
}).join('')}
✏️ Edit Client
🗑
`;
modal.style.display='flex';
};
// Expose
window.renderCRMClients = renderCRMClients;
window.renderCRMPlacements = renderCRMPlacements;
window.renderCRMCommissions = renderCRMCommissions;
window.renderCRMRecruiters = renderCRMRecruiters;
window.saGo = function(tab){
if(typeof saTab !== 'undefined') window.saTab = tab;
var content = document.getElementById('saContent');
if(content && typeof renderSATab === 'function'){
content.innerHTML = renderSATab();
// Update nav active state
document.querySelectorAll('.sa-nav-item').forEach(function(n){
n.classList.toggle('active', n.dataset.tab === tab);
});
}
};
function sendEmail(candId){
const to = (document.getElementById('em_to')||{value:''}).value;
const sub = (document.getElementById('em_subject')||{value:''}).value;
const body = (document.getElementById('em_body')||{value:''}).value;
if(!to){ if(typeof showToast==='function') showToast('No recipient email','⚠️'); return; }
if(typeof sendRealEmail==='function'){
sendRealEmail({to:to,subject:sub||'Message from MyTalent Jobs',html:''+body.replace(/\n/g,' ')+'
'})
.then(function(){ if(typeof showToast==='function') showToast('Email sent ✅','📧'); })
.catch(function(e){ if(typeof showToast==='function') showToast('Email failed: '+e.message,'❌'); });
} else {
if(typeof showToast==='function') showToast('Email queued (configure SendGrid in Admin)','ℹ️');
}
const modal = document.getElementById('emailSendModal');
if(modal) modal.style.display='none';
}
window.sendEmail = sendEmail;
function fillEmailModal(key, candId, jobTitle){
const cand = typeof DB!=='undefined' ? DB.candidates.find(function(c){ return c.id===candId; }) : null;
const tpls = typeof atsEmailTpls!=='undefined' ? atsEmailTpls : {};
const tpl = tpls[key]||{subject:'Following up on your application',body:'Dear Candidate,\n\nThank you for applying.\n\nBest regards,\nMyTalent Jobs'};
const fill = function(s){ return (s||'').replace(/{name}/g,(cand&&cand.name)||'Candidate').replace(/{job}/g,jobTitle||'the position'); };
const subEl = document.getElementById('em_subject');
const bodyEl = document.getElementById('em_body');
const toEl = document.getElementById('em_to');
if(subEl) subEl.value = fill(tpl.subject);
if(bodyEl) bodyEl.value = fill(tpl.body);
if(toEl && cand) toEl.value = cand.email||'';
}
window.fillEmailModal = fillEmailModal;
💼 Post Job
👤 Add Candidate