Local Session Error
The CV Studio encountered a render error. This is usually caused by corrupted saved data from a previous session.
{this.state.error?.message}
);
}
return this.props.children;
}
}
const GateModal = ({ reason, onClose }) => {
return (
{reason === 'login' && (
<>
Login Required
Please log in to edit, upload, or generate AI content.
Login via Portal
>
)}
{reason === 'role' && (
<>
Premium Access
This tool is available for Premium Subscription only.
Subscribe Now
>
)}
{reason === 'timer' && (
<>
Usage Limit
You have used your session for now.
Wait: {window.BIMUSERS_CONFIG.timeRemaining} min
Upgrade for Unlimited Access
>
)}
);
};
const UsageHistoryPanel = ({ history }) => (
Drag to Pan
Zoom
setTheme(p => ({...p, photoScale: parseFloat(e.target.value)}))}
className="w-full h-1.5 bg-slate-200 rounded-lg appearance-none cursor-pointer accent-blue-600 mb-2" title="Zoom In/Out" />
{['circle', 'rounded', 'square'].map(shape => (
))}
);
};
const EditorContent = () => (
{/* File Upload Section */}
{isUploading ? : }
Auto-Import from Resume
Upload existing PDF/Image to auto-fill details.
{uploadError &&
{uploadError}
}
{/* Personal Info */}
{expandedSection === 'personal' && (
)}
{/* Experience Section */}
{expandedSection === 'xp' && (
{(resumeData.experience || []).map((exp, idx) => (
handleArrayChange('experience', idx, 'role', e.target.value)} />
handleArrayChange('experience', idx, 'company', e.target.value)} />
handleArrayChange('experience', idx, 'duration', e.target.value)} />
))}
)}
{/* Projects Section */}
{expandedSection === 'projects' && (
{(resumeData.projects || []).map((proj, idx) => (
))}
)}
{/* Skills Section */}
{expandedSection === 'skills' && (
)}
{/* Languages Section */}
{expandedSection === 'languages' && (
{(resumeData.languages || []).map((lang, idx) => (
handleArrayChange('languages', idx, 'name', e.target.value)} />
))}
)}
{/* Education Section */}
{expandedSection === 'edu' && (
Degrees
{(resumeData.education || []).map((edu, idx) => (
handleArrayChange('education', idx, 'degree', e.target.value)} />
handleArrayChange('education', idx, 'school', e.target.value)} />
handleArrayChange('education', idx, 'year', e.target.value)} />
))}
Certificates
{(resumeData.certifications || []).map((cert, idx) => (
handleArrayChange('certifications', idx, 'name', e.target.value)} />
handleArrayChange('certifications', idx, 'issuer', e.target.value)} />
handleArrayChange('certifications', idx, 'year', e.target.value)} />
))}
)}
);
// NEW: Dynamic Resizing Wrapper for Side-by-Side Preview
const PreviewWrapper = ({ fullView = false }) => {
const wrapperRef = useRef(null);
const [scale, setScale] = useState(1);
const [height, setHeight] = useState('auto');
useEffect(() => {
const updateLayout = () => {
if (wrapperRef.current && wrapperRef.current.parentElement) {
const parentWidth = wrapperRef.current.parentElement.clientWidth;
const targetWidth = 794; // approx A4 width in px (210mm)
let newScale = 1;
if (!fullView) {
// In side-by-side mode, strictly scale down to fit container width
if (parentWidth < targetWidth + 40) {
newScale = (parentWidth - 40) / targetWidth;
}
} else {
// In Full View (Preview Tab), expand on large screens or fit normally
if (parentWidth > 1200) {
newScale = 1.2;
} else if (parentWidth < targetWidth + 40) {
newScale = (parentWidth - 40) / targetWidth;
}
}
setScale(newScale);
// Adjust container height to match scaled document to prevent awkward scroll dead-zones
const contentNode = document.getElementById('cv-preview-content');
if (contentNode) {
const actualHeight = contentNode.offsetHeight;
setHeight(`${actualHeight * newScale}px`);
}
}
};
const observer = new ResizeObserver(updateLayout);
if (wrapperRef.current) {
observer.observe(wrapperRef.current.parentElement);
const contentNode = document.getElementById('cv-preview-content');
if (contentNode) observer.observe(contentNode);
}
setTimeout(updateLayout, 100);
return () => observer.disconnect();
}, [activeTab, resumeData, theme, fullView]);
return (
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email && {resumeData.email}}
{resumeData.phone && • {resumeData.phone}}
{resumeData.linkedin && • {resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}}
{resumeData.portfolio && • {resumeData.portfolio.replace(/(^\w+:|^)\/\//, '')}}
{resumeData.summary && (
Professional Summary
{resumeData.summary}
)}
Professional Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.role}
{exp.duration}
{exp.company}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Key Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name} | {proj.role}
{renderDetails(proj.details)}
))}
)}
Core Competencies & Skills
{resumeData.skills}
Education
{(resumeData.education || []).map(edu => (
{edu.degree}
{edu.school}, {edu.year}
))}
{((resumeData.certifications || []).length > 0 || (resumeData.languages || []).length > 0) && (
{(resumeData.certifications || []).length > 0 && (
Certifications
{(resumeData.certifications || []).map(cert => (
-
{cert.name}, {cert.issuer} ({cert.year})
))}
)}
{(resumeData.languages || []).length > 0 && (
Languages
{(resumeData.languages || []).map(lang => (
-
{lang.name}: {lang.level}
))}
)}
)}
);
}
// 3: EXECUTIVE MINIMAL
if (theme.layout === 'executive') {
return (
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email &&
Email{resumeData.email}
}
{resumeData.phone &&
Phone{resumeData.phone}
}
{resumeData.linkedin &&
LinkedIn{resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}
}
{resumeData.portfolio &&
Portfolio{resumeData.portfolio.replace(/(^\w+:|^)\/\//, '')}
}
Core Skills
{(resumeData.skills || '').split(',').map((s,i) => {
const trimmed = s.trim(); if (!trimmed) return null;
return • {trimmed};
})}
{resumeData.languages && resumeData.languages.length > 0 && (
Languages
{(resumeData.languages || []).map((l,i) => (
{l.name}
{l.level}
))}
)}
{resumeData.education && resumeData.education.length > 0 && (
Education
{(resumeData.education || []).map((edu,i) => (
{edu.degree}{edu.school}{edu.year}
))}
)}
{resumeData.summary && (
Profile
{resumeData.summary}
)}
Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.role}
{exp.company}
{exp.duration}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Key Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name}
{proj.role}
{renderDetails(proj.details)}
))}
)}
{resumeData.certifications && resumeData.certifications.length > 0 && (
Certifications
{(resumeData.certifications || []).map((cert, idx) => (
{cert.name} — {cert.issuer} ({cert.year})
))}
)}
);
}
// 4: MINIMALIST
if (theme.layout === 'minimalist') {
return (
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email && {resumeData.email}}
{resumeData.phone && {resumeData.phone}}
{resumeData.linkedin && {resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}}
{resumeData.summary && (
)}
Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.role}
{exp.duration}
{exp.company}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name}
{proj.role}
{renderDetails(proj.details)}
))}
)}
Expertise
{(resumeData.skills || '').split(',').map((s,i) => {
const trimmed = s.trim(); if (!trimmed) return null;
return ({trimmed});
})}
Education
{(resumeData.education || []).map(edu => (
{edu.degree}
{edu.school} | {edu.year}
))}
);
}
// 5: CREATIVE (Bold Header Banner)
if (theme.layout === 'creative') {
return (
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email &&
{resumeData.email}
}
{resumeData.phone &&
{resumeData.phone}
}
{resumeData.linkedin &&
{resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}
}
{resumeData.portfolio &&
{resumeData.portfolio.replace(/(^\w+:|^)\/\//, '')}
}
{resumeData.summary && (
)}
Technical Skills
{(resumeData.skills || '').split(',').map((s,i) => {
const trimmed = s.trim(); if (!trimmed) return null;
return (
• {trimmed}
);
})}
Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.company} — {exp.role}
{exp.duration}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name} | {proj.role}
{renderDetails(proj.details)}
))}
)}
Education
{(resumeData.education || []).map(edu => (
{edu.degree}
{edu.school}, {edu.year}
))}
{((resumeData.certifications || []).length > 0 || (resumeData.languages || []).length > 0) && (
{(resumeData.certifications || []).length > 0 && (
Certifications
{(resumeData.certifications || []).map(cert => (
-
{cert.name}, {cert.issuer} ({cert.year})
))}
)}
)}
);
}
// 7: TIMELINE
if (theme.layout === 'timeline') {
return (
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email &&
{resumeData.email}
}
{resumeData.phone &&
{resumeData.phone}
}
{resumeData.linkedin &&
{resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}
}
{resumeData.portfolio &&
{resumeData.portfolio.replace(/(^\w+:|^)\/\//, '')}
}
{resumeData.summary && (
Profile
{resumeData.summary}
)}
Skills
{(resumeData.skills || '').split(',').map((s,i) => {
const trimmed = s.trim(); if (!trimmed) return null;
return (
✓ {trimmed}
);
})}
{resumeData.languages && resumeData.languages.length > 0 && (
Languages
{(resumeData.languages || []).map(lang => (
{lang.name}
{lang.level}
))}
)}
{resumeData.certifications && resumeData.certifications.length > 0 && (
Certifications
{(resumeData.certifications || []).map(cert => (
{cert.name}
{cert.issuer}
{cert.year}
))}
)}
Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.duration}
{exp.role}
{exp.company}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Key Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name}
{proj.role}
{renderDetails(proj.details)}
))}
)}
{resumeData.education && resumeData.education.length > 0 && (
Education
{(resumeData.education || []).map((edu, idx) => (
{edu.year}
{edu.degree}
{edu.school}
))}
)}
);
}
// 8: ELEGANT (New)
if (theme.layout === 'elegant') {
return (
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email && {resumeData.email}}
{resumeData.phone && | {resumeData.phone}}
{resumeData.linkedin && | {resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}}
{resumeData.portfolio && | {resumeData.portfolio.replace(/(^\w+:|^)\/\//, '')}}
{resumeData.summary && (
Profile
{resumeData.summary}
)}
Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.role}
{exp.duration}
{exp.company}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Selected Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name}
{proj.role}
{renderDetails(proj.details)}
))}
)}
Education
{(resumeData.education || []).map(edu => (
{edu.degree}
{edu.school} • {edu.year}
))}
Expertise
{resumeData.skills}
);
}
// 9: COMPACT (New)
if (theme.layout === 'compact') {
return (
{/* Left Column (Narrow) */}
{resumeData.fullName || "Your Name"}
{resumeData.title || "Professional Title"}
{resumeData.email &&
{resumeData.email}
}
{resumeData.phone &&
{resumeData.phone}
}
{resumeData.linkedin &&
{resumeData.linkedin.replace(/(^\w+:|^)\/\//, '')}
}
{resumeData.portfolio &&
{resumeData.portfolio.replace(/(^\w+:|^)\/\//, '')}
}
Skills
{(resumeData.skills || '').split(',').map((s,i) => {
const trimmed = s.trim(); if (!trimmed) return null;
return {trimmed};
})}
{resumeData.education && resumeData.education.length > 0 && (
Education
{(resumeData.education || []).map((edu,i) => (
{edu.degree}{edu.school}{edu.year}
))}
)}
{resumeData.certifications && resumeData.certifications.length > 0 && (
Certs
{(resumeData.certifications || []).map((cert,i) => (
{cert.name}
{cert.year}
))}
)}
{resumeData.languages && resumeData.languages.length > 0 && (
Languages
{(resumeData.languages || []).map((l,i) => (
{l.name}{l.level}
))}
)}
{/* Right Column (Wide) */}
{resumeData.summary && (
Summary
{resumeData.summary}
)}
Experience
{(resumeData.experience || []).map((exp, idx) => (
{exp.role}
{exp.duration}
{exp.company}
{renderDetails(exp.details)}
))}
{resumeData.projects && resumeData.projects.length > 0 && (
Key Projects
{(resumeData.projects || []).map((proj, idx) => (
{proj.name} | {proj.role}
{renderDetails(proj.details)}
))}
)}
);
}
return null;
};
const ToolsContent = () => (