458 lines
19 KiB
TypeScript
458 lines
19 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect } from "react";
|
||
import BackToMC from "@/components/mission-control/BackToMC";
|
||
|
||
export default function ResumeBuilderPage() {
|
||
useEffect(() => {
|
||
// Load the resume script after component mounts
|
||
const script = document.createElement("script");
|
||
script.src = "/resume-builder.js";
|
||
script.async = true;
|
||
document.body.appendChild(script);
|
||
}, []);
|
||
|
||
return (
|
||
<div className="min-h-screen bg-slate-200">
|
||
<BackToMC />
|
||
|
||
{/* Include the styles inline */}
|
||
<style>{`
|
||
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
|
||
|
||
:root {
|
||
--sidebar-gray: #f3f3f3;
|
||
--accent-dark: #1a1a1a;
|
||
--accent-blue: #2563eb;
|
||
}
|
||
|
||
.resume-page {
|
||
width: 850px;
|
||
min-height: 1100px;
|
||
background: white;
|
||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||
margin: 2rem auto;
|
||
display: flex;
|
||
}
|
||
|
||
.sidebar {
|
||
width: 280px;
|
||
background-color: var(--sidebar-gray);
|
||
padding: 2.5rem 1.5rem;
|
||
}
|
||
|
||
.main-content {
|
||
flex: 1;
|
||
padding: 3.5rem 3rem;
|
||
background: white;
|
||
}
|
||
|
||
.circle-frame {
|
||
width: 176px;
|
||
height: 176px;
|
||
border-radius: 9999px;
|
||
border: 10px solid #e2e2e2;
|
||
overflow: hidden;
|
||
margin: 0 auto 2rem;
|
||
background: #d1d1d1;
|
||
position: relative;
|
||
}
|
||
|
||
.circle-frame img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.photo-edit-overlay {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(0,0,0,0.4);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
opacity: 0;
|
||
transition: opacity 0.2s;
|
||
cursor: pointer;
|
||
color: white;
|
||
font-size: 0.8rem;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.circle-frame:hover .photo-edit-overlay {
|
||
opacity: 1;
|
||
}
|
||
|
||
.section-header {
|
||
font-size: 1.1rem;
|
||
font-weight: 700;
|
||
color: var(--accent-dark);
|
||
border-bottom: 1px solid #ccc;
|
||
padding-bottom: 4px;
|
||
margin-bottom: 12px;
|
||
text-transform: capitalize;
|
||
}
|
||
|
||
.main-header {
|
||
font-size: 1.6rem;
|
||
font-weight: 800;
|
||
letter-spacing: 0.15em;
|
||
color: var(--accent-dark);
|
||
border-bottom: 2px solid var(--accent-dark);
|
||
padding-bottom: 8px;
|
||
margin-bottom: 24px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
[contenteditable="true"] {
|
||
outline: none;
|
||
border: 1px dashed transparent;
|
||
transition: border 0.2s;
|
||
}
|
||
|
||
[contenteditable="true"]:hover {
|
||
border: 1px dashed #3b82f6;
|
||
background-color: rgba(59, 130, 246, 0.05);
|
||
}
|
||
|
||
[contenteditable="true"]:focus {
|
||
background-color: white;
|
||
border: 1px solid #3b82f6;
|
||
}
|
||
|
||
.experience-dot {
|
||
position: absolute;
|
||
left: -9px;
|
||
top: 6px;
|
||
width: 16px;
|
||
height: 16px;
|
||
background-color: #333;
|
||
border: 3px solid white;
|
||
border-radius: 9999px;
|
||
z-index: 10;
|
||
}
|
||
|
||
.experience-dot-sub {
|
||
background-color: #999;
|
||
}
|
||
|
||
.toolbar {
|
||
height: 60px;
|
||
background: #1f2937;
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 2rem;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
|
||
}
|
||
|
||
@media print {
|
||
.no-print, .toolbar, .photo-edit-overlay { display: none !important; }
|
||
body { background: white; padding: 0; margin: 0; }
|
||
.resume-page { margin: 0; box-shadow: none; width: 100%; }
|
||
[contenteditable="true"]:hover { border-color: transparent; background: transparent; }
|
||
}
|
||
`}</style>
|
||
|
||
{/* Toolbar */}
|
||
<div className="sticky top-0 z-50 bg-gray-800 px-6 py-3 flex items-center justify-between">
|
||
<div className="flex items-center gap-4">
|
||
<h1 className="font-bold text-lg text-blue-400">Haitham's Resume Manager</h1>
|
||
<select id="resumeSelect" className="bg-gray-700 text-white px-3 py-1 rounded border border-gray-600 outline-none">
|
||
</select>
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<button id="btnNew" className="bg-blue-600 hover:bg-blue-700 px-4 py-1 rounded text-sm font-medium transition">New Version</button>
|
||
<button id="btnSave" className="bg-green-600 hover:bg-green-700 px-4 py-1 rounded text-sm font-medium transition">Save Changes</button>
|
||
<button id="btnPrint" className="bg-gray-600 hover:bg-gray-700 px-4 py-1 rounded text-sm font-medium transition">Print to PDF</button>
|
||
<button id="btnDelete" className="bg-red-600 hover:bg-red-700 px-4 py-1 rounded text-sm font-medium transition">Delete</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Resume Container */}
|
||
<div className="resume-page mt-20">
|
||
{/* Sidebar */}
|
||
<div className="sidebar">
|
||
<div className="circle-frame" id="photoFrame">
|
||
<img id="userPhoto" src="Resume.jpg" alt="Haitham Khalifa" />
|
||
<div className="photo-edit-overlay no-print">EDIT PHOTO</div>
|
||
<input type="file" id="photoInput" className="hidden" accept="image/*" />
|
||
</div>
|
||
|
||
<h1 id="userName" contentEditable suppressContentEditableWarning className="text-2xl font-black text-center text-gray-900 mb-8 tracking-tighter uppercase leading-none">HAITHAM KHALIFA</h1>
|
||
|
||
{/* Contact */}
|
||
<div className="space-y-3 text-[11px] text-gray-700 mb-10">
|
||
<div className="flex items-center gap-3">
|
||
<span className="w-5 h-5 flex items-center justify-center bg-gray-800 text-white rounded-full text-[10px]">📞</span>
|
||
<span contentEditable suppressContentEditableWarning id="userPhone" className="font-medium">+34 614 821 331</span>
|
||
</div>
|
||
<div className="flex items-center gap-3">
|
||
<span className="w-5 h-5 flex items-center justify-center bg-gray-800 text-white rounded-full text-[10px]">✉️</span>
|
||
<span contentEditable suppressContentEditableWarning id="userEmail" className="font-medium">Haitham@Khalifa.se</span>
|
||
</div>
|
||
<div className="flex items-center gap-3">
|
||
<span className="w-5 h-5 flex items-center justify-center bg-gray-800 text-white rounded-full text-[10px] font-bold">in</span>
|
||
<span contentEditable suppressContentEditableWarning id="userLinkedin" className="font-medium">linkedin.com/in/haithamekhalifa/</span>
|
||
</div>
|
||
<div className="flex items-center gap-3">
|
||
<span className="w-5 h-5 flex items-center justify-center bg-gray-800 text-white rounded-full text-[10px]">📍</span>
|
||
<span contentEditable suppressContentEditableWarning id="userLocation" className="font-medium">Málaga, Spain</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mb-10">
|
||
<h2 className="section-header">About Me</h2>
|
||
<div id="aboutMe" contentEditable suppressContentEditableWarning className="text-[10px] leading-relaxed text-gray-600 font-medium text-justify">
|
||
A results-oriented leader with 15+ years of experience in driving e-commerce growth, optimizing online platforms, and implementing successful digital marketing strategies. Proven ability to increase online sales, improve customer engagement, and manage cross-functional teams to achieve business objectives.
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mb-10">
|
||
<h2 className="section-header">Education</h2>
|
||
<div id="educationList" contentEditable suppressContentEditableWarning className="space-y-4">
|
||
<div>
|
||
<p className="text-[11px] font-bold text-gray-800 leading-tight">Intensive Software Development Academy</p>
|
||
<p className="text-[10px] text-gray-600">Lund University</p>
|
||
<p className="text-[9px] text-gray-400 font-bold">Sweden, Lund - 2019</p>
|
||
</div>
|
||
<div>
|
||
<p className="text-[11px] font-bold text-gray-800 leading-tight">Bachelor of Computer Science</p>
|
||
<p className="text-[10px] text-gray-600">Modern Academy Maadi</p>
|
||
<p className="text-[9px] text-gray-400 font-bold">Egypt, Cairo 2001 - 2006</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mb-10">
|
||
<h2 className="section-header">Skills</h2>
|
||
<div id="skillsList" contentEditable suppressContentEditableWarning className="text-[11px] text-gray-700 space-y-2 font-medium">
|
||
• E-commerce Strategy<br/>
|
||
• Digital Marketing<br/>
|
||
• SEO/SEM<br/>
|
||
• Product Ownership<br/>
|
||
• Team Leadership
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<h2 className="section-header">Language</h2>
|
||
<div id="languageList" contentEditable suppressContentEditableWarning className="text-[11px] text-gray-700 space-y-1 font-medium">
|
||
• Arabic<br/>
|
||
• English<br/>
|
||
• Swedish
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Main Experience */}
|
||
<div className="main-content">
|
||
<h2 className="main-header">Experience</h2>
|
||
<div id="experienceContainer" contentEditable suppressContentEditableWarning className="space-y-10">
|
||
|
||
{/* Protein.com */}
|
||
<div className="relative pl-8 border-l-2 border-gray-200 pb-2">
|
||
<div className="experience-dot"></div>
|
||
<div className="flex justify-between items-baseline mb-1">
|
||
<h3 className="text-lg font-bold text-gray-800 leading-none">Product Owner & IT Consultant</h3>
|
||
<span className="text-xs font-bold text-gray-400">2020-2025</span>
|
||
</div>
|
||
<p className="text-sm font-bold text-blue-600 mb-3">Protein.com | Sweden, Malmö</p>
|
||
<div className="text-[11px] text-gray-600 space-y-1.5 leading-snug">
|
||
• Managed product backlog to drive e-commerce sales.<br/>
|
||
• Developed/executed SEO strategies (+20% organic traffic).<br/>
|
||
• Implemented/managed MarTech for e-commerce performance.<br/>
|
||
• Drove Agile practices.<br/>
|
||
• Utilized data analytics to optimize e-commerce growth.<br/>
|
||
• Managed product data feeds.
|
||
</div>
|
||
</div>
|
||
|
||
{/* HostPioneers */}
|
||
<div className="relative pl-8 border-l-2 border-gray-200 pb-2">
|
||
<div className="experience-dot experience-dot-sub"></div>
|
||
<div className="flex justify-between items-baseline mb-1">
|
||
<h3 className="text-lg font-bold text-gray-800 leading-none">Founder & CEO</h3>
|
||
<span className="text-xs font-bold text-gray-400">2012-2021</span>
|
||
</div>
|
||
<p className="text-sm font-bold text-blue-600 mb-3">HostPioneers.com | Denmark, Copenhagen</p>
|
||
<div className="text-[11px] text-gray-600 space-y-1.5 leading-snug">
|
||
• Led e-commerce platform development/optimization.<br/>
|
||
• Implemented MarTech to drive engagement/revenue.<br/>
|
||
• Developed/executed e-commerce marketing strategies.<br/>
|
||
• Managed all aspects of the online business.<br/>
|
||
• Executed e-commerce marketing (SEO, email, social).<br/>
|
||
• Oversaw customer journey.
|
||
</div>
|
||
</div>
|
||
|
||
{/* Red Cross */}
|
||
<div className="relative pl-8 border-l-2 border-gray-200 pb-2">
|
||
<div className="experience-dot experience-dot-sub"></div>
|
||
<div className="flex justify-between items-baseline mb-1">
|
||
<h3 className="text-lg font-bold text-gray-800 leading-none">Social Media Manager (Volunteer)</h3>
|
||
<span className="text-xs font-bold text-gray-400">2013-2016</span>
|
||
</div>
|
||
<p className="text-sm font-bold text-blue-600 mb-3">Danish Red Cross - Newtimes.dk</p>
|
||
<div className="text-[11px] text-gray-600 space-y-1.5 leading-snug">
|
||
• EU-funded project to raise awareness of asylum seekers and policymakers.<br/>
|
||
• Developed and managed the website, enhancing SEO and user engagement.<br/>
|
||
• Wrote articles and managed social media to increase brand visibility.
|
||
</div>
|
||
</div>
|
||
|
||
{/* Cayenne */}
|
||
<div className="relative pl-8 border-l-2 border-gray-200 pb-2">
|
||
<div className="experience-dot experience-dot-sub"></div>
|
||
<div className="flex justify-between items-baseline mb-1">
|
||
<h3 className="text-lg font-bold text-gray-800 leading-none">C.I.O Deputy</h3>
|
||
<span className="text-xs font-bold text-gray-400">2007-2012</span>
|
||
</div>
|
||
<p className="text-sm font-bold text-blue-600 mb-3">Cayenne Technologies | Egypt, Cairo</p>
|
||
<div className="text-[11px] text-gray-600 space-y-1.5 leading-snug">
|
||
• Web Business Manager & Deputy Chief Information Officer.<br/>
|
||
• Managed projects in the web technology department.<br/>
|
||
• Developed and presented web projects to clients and stakeholders.<br/>
|
||
• Installed and supported web servers and applications.<br/>
|
||
• Improved website traffic and SEO scores for clients.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* JavaScript */}
|
||
<script dangerouslySetInnerHTML={{ __html: `
|
||
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);
|
||
}
|
||
};
|
||
|
||
getEl('photoInput')?.addEventListener('change', (e) => handlePhotoUpload(e.target));
|
||
getEl('photoFrame')?.addEventListener('click', () => getEl('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);
|
||
};
|
||
|
||
getEl('btnNew')?.addEventListener('click', createNewProfile);
|
||
getEl('btnSave')?.addEventListener('click', saveCurrentProfile);
|
||
getEl('btnDelete')?.addEventListener('click', deleteProfile);
|
||
getEl('btnPrint')?.addEventListener('click', () => window.print());
|
||
getEl('resumeSelect')?.addEventListener('change', (e) => loadProfile(e.target.value));
|
||
|
||
document.addEventListener('DOMContentLoaded', init);
|
||
`}} />
|
||
</div>
|
||
);
|
||
}
|