2697a89285
- resume-builder.js in public folder - cleaner React component - script loaded from public
140 lines
4.4 KiB
JavaScript
140 lines
4.4 KiB
JavaScript
// Resume Builder JavaScript
|
|
let resumes = JSON.parse(localStorage.getItem('haitham_resumes_v2') || '{}');
|
|
let currentProfileName = localStorage.getItem('haitham_current_profile_v2') || 'Main Resume';
|
|
|
|
const getEl = (id) => document.getElementById(id);
|
|
|
|
const getInitialContent = () => ({
|
|
name: getEl('userName')?.innerText || '',
|
|
photo: getEl('userPhoto')?.src || '',
|
|
phone: getEl('userPhone')?.innerText || '',
|
|
email: getEl('userEmail')?.innerText || '',
|
|
linkedin: getEl('userLinkedin')?.innerText || '',
|
|
location: getEl('userLocation')?.innerText || '',
|
|
about: getEl('aboutMe')?.innerText || '',
|
|
education: getEl('educationList')?.innerHTML || '',
|
|
skills: getEl('skillsList')?.innerHTML || '',
|
|
language: getEl('languageList')?.innerHTML || '',
|
|
experience: getEl('experienceContainer')?.innerHTML || ''
|
|
});
|
|
|
|
const init = () => {
|
|
if (Object.keys(resumes).length === 0) {
|
|
resumes['Main Resume'] = getInitialContent();
|
|
saveToDisk();
|
|
}
|
|
updateSelect();
|
|
loadProfile(currentProfileName);
|
|
};
|
|
|
|
const handlePhotoUpload = (input) => {
|
|
const file = input.files[0];
|
|
if (file) {
|
|
const reader = new FileReader();
|
|
reader.onload = (e) => {
|
|
getEl('userPhoto').src = e.target.result;
|
|
saveCurrentProfile();
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
};
|
|
|
|
const photoInput = getEl('photoInput');
|
|
const photoFrame = getEl('photoFrame');
|
|
if (photoInput && photoFrame) {
|
|
photoInput.addEventListener('change', (e) => handlePhotoUpload(e.target));
|
|
photoFrame.addEventListener('click', () => photoInput.click());
|
|
}
|
|
|
|
const updateSelect = () => {
|
|
const select = getEl('resumeSelect');
|
|
if (!select) return;
|
|
select.innerHTML = '';
|
|
Object.keys(resumes).forEach(name => {
|
|
const opt = document.createElement('option');
|
|
opt.value = name;
|
|
opt.textContent = name;
|
|
if (name === currentProfileName) opt.selected = true;
|
|
select.appendChild(opt);
|
|
});
|
|
};
|
|
|
|
const loadProfile = (name) => {
|
|
const p = resumes[name] || resumes[Object.keys(resumes)[0]];
|
|
if (!p) return;
|
|
currentProfileName = name;
|
|
localStorage.setItem('haitham_current_profile_v2', name);
|
|
|
|
getEl('userName').innerText = p.name || '';
|
|
getEl('userPhoto').src = p.photo || 'Resume.jpg';
|
|
getEl('userPhone').innerText = p.phone || '';
|
|
getEl('userEmail').innerText = p.email || '';
|
|
getEl('userLinkedin').innerText = p.linkedin || '';
|
|
getEl('userLocation').innerText = p.location || '';
|
|
getEl('aboutMe').innerText = p.about || '';
|
|
getEl('educationList').innerHTML = p.education || '';
|
|
getEl('skillsList').innerHTML = p.skills || '';
|
|
getEl('languageList').innerHTML = p.language || '';
|
|
getEl('experienceContainer').innerHTML = p.experience || '';
|
|
};
|
|
|
|
const saveCurrentProfile = () => {
|
|
resumes[currentProfileName] = getInitialContent();
|
|
saveToDisk();
|
|
showStatus('Changes Saved');
|
|
};
|
|
|
|
const createNewProfile = () => {
|
|
const name = prompt('Name this version (e.g., Geely IT Manager):');
|
|
if (name && !resumes[name]) {
|
|
resumes[name] = { ...resumes[currentProfileName] };
|
|
currentProfileName = name;
|
|
saveToDisk();
|
|
updateSelect();
|
|
loadProfile(name);
|
|
} else if (resumes[name]) {
|
|
alert('This name already exists.');
|
|
}
|
|
};
|
|
|
|
const deleteProfile = () => {
|
|
if (Object.keys(resumes).length <= 1) return alert('You need at least one profile.');
|
|
if (confirm('Delete "' + currentProfileName + '"?')) {
|
|
delete resumes[currentProfileName];
|
|
currentProfileName = Object.keys(resumes)[0];
|
|
saveToDisk();
|
|
updateSelect();
|
|
loadProfile(currentProfileName);
|
|
}
|
|
};
|
|
|
|
const saveToDisk = () => {
|
|
localStorage.setItem('haitham_resumes_v2', JSON.stringify(resumes));
|
|
};
|
|
|
|
const showStatus = (msg) => {
|
|
const btn = getEl('btnSave');
|
|
if (!btn) return;
|
|
const original = btn.textContent;
|
|
btn.textContent = msg;
|
|
btn.style.backgroundColor = '#059669';
|
|
setTimeout(() => {
|
|
btn.textContent = original;
|
|
btn.style.backgroundColor = '';
|
|
}, 2000);
|
|
};
|
|
|
|
const btnNew = getEl('btnNew');
|
|
const btnSave = getEl('btnSave');
|
|
const btnDelete = getEl('btnDelete');
|
|
const btnPrint = getEl('btnPrint');
|
|
const resumeSelect = getEl('resumeSelect');
|
|
|
|
if (btnNew) btnNew.addEventListener('click', createNewProfile);
|
|
if (btnSave) btnSave.addEventListener('click', saveCurrentProfile);
|
|
if (btnDelete) btnDelete.addEventListener('click', deleteProfile);
|
|
if (btnPrint) btnPrint.addEventListener('click', () => window.print());
|
|
if (resumeSelect) resumeSelect.addEventListener('change', (e) => loadProfile(e.target.value));
|
|
|
|
document.addEventListener('DOMContentLoaded', init);
|