Personality
Positive Traits: ${characterData['char-traits'] || 'N/A'}
Flaws: ${characterData['char-flaws'] || 'N/A'}
Motivations: ${characterData['char-motivations'] || 'N/A'}
Backstory
${characterData['char-backstory'] || 'N/A'}
`;
pdfButtonContainer.style.display = 'block';
showTab(tabs.length - 1);
};
const downloadPDF = () => {
try {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const fields = {
name: document.getElementById('char-name')?.value || 'Unnamed Character',
nickname: document.getElementById('char-nickname')?.value || 'N/A',
age: document.getElementById('char-age')?.value || 'N/A',
gender: document.getElementById('char-gender')?.value || 'N/A',
occupation: document.getElementById('char-occupation')?.value || 'N/A',
concept: document.getElementById('char-concept')?.value || 'N/A',
height: document.getElementById('char-height')?.value || 'N/A',
hair: document.getElementById('char-hair')?.value || 'N/A',
features: document.getElementById('char-features')?.value || 'N/A',
style: document.getElementById('char-style')?.value || 'N/A',
traits: document.getElementById('char-traits')?.value || 'N/A',
flaws: document.getElementById('char-flaws')?.value || 'N/A',
motivations: document.getElementById('char-motivations')?.value || 'N/A',
backstory: document.getElementById('char-backstory')?.value || 'N/A'
};
const pageHeight = doc.internal.pageSize.getHeight();
const pageWidth = doc.internal.pageSize.getWidth();
const margin = 15;
let cursorY = margin;
// --- PDF Header ---
doc.setFont('helvetica', 'bold');
doc.setFontSize(24);
doc.setTextColor(45, 22, 82); // Dark Purple
doc.text(fields.name, pageWidth / 2, cursorY, { align: 'center' });
cursorY += 8;
doc.setFont('helvetica', 'normal');
doc.setFontSize(12);
doc.setTextColor(128, 128, 128);
doc.text(`Character Profile Sheet`, pageWidth / 2, cursorY, { align: 'center' });
cursorY += 12;
doc.setDrawColor(221, 221, 221);
doc.line(margin, cursorY, pageWidth - margin, cursorY);
cursorY += 10;
// --- Helper function for sections ---
const addSection = (title, content, isLongText = false) => {
if (cursorY > pageHeight - 30) {
doc.addPage();
cursorY = margin;
}
doc.setFontSize(14);
doc.setFont('helvetica', 'bold');
doc.setTextColor(88, 28, 135); // Purple
doc.text(title, margin, cursorY);
cursorY += 6;
doc.setFont('helvetica', 'normal');
doc.setFontSize(10);
doc.setTextColor(55, 65, 81);
if(isLongText){
const textLines = doc.splitTextToSize(content, pageWidth - margin * 2);
doc.text(textLines, margin, cursorY);
cursorY += (textLines.length * 4.5) + 8;
} else {
doc.autoTable({
startY: cursorY,
body: content,
theme: 'plain',
styles: { fontSize: 10, cellPadding: 2, textColor: [55, 65, 81] },
columnStyles: { 0: { fontStyle: 'bold', cellWidth: 50, textColor: [17, 24, 39] } }
});
cursorY = doc.previousAutoTable.finalY + 8;
}
};
// --- Build PDF Sections ---
const identityData = [
['Nickname:', fields.nickname], ['Age:', fields.age], ['Gender:', fields.gender], ['Occupation:', fields.occupation]
];
addSection("Core Identity", identityData);
addSection("Core Concept", fields.concept, true);
const appearanceData = [
['Height & Build:', fields.height], ['Hair & Eyes:', fields.hair], ['Features:', fields.features], ['Clothing Style:', fields.style]
];
addSection("Appearance", appearanceData);
addSection("Positive Traits", fields.traits, true);
addSection("Flaws & Vices", fields.flaws, true);
addSection("Motivations & Goals", fields.motivations, true);
addSection("Backstory", fields.backstory, true);
// --- Footer ---
const pageCount = doc.internal.getNumberOfPages();
for (let i = 1; i <= pageCount; i++) {
doc.setPage(i);
doc.setFontSize(9);
doc.setTextColor(150);
const footerText = `Page ${i} of ${pageCount} | ${fields.name} | Generated on: ${new Date().toLocaleDateString()}`;
doc.text(footerText, pageWidth / 2, pageHeight - 10, { align: 'center' });
}
doc.save(`${fields.name.replace(/\s+/g, '_')}-Profile.pdf`);
} catch (error) {
console.error("Failed to generate PDF:", error);
const pdfButtonContainer = document.getElementById('pdf-button-container');
if (pdfButtonContainer && !pdfButtonContainer.querySelector('.error-msg')) {
const errorMsg = document.createElement('p');
errorMsg.textContent = 'Sorry, an error occurred while creating the PDF.';
errorMsg.className = 'text-red-500 text-sm mt-2 error-msg';
pdfButtonContainer.appendChild(errorMsg);
}
}
};
// Event Listeners
prevButton.addEventListener('click', () => navigate(-1));
nextButton.addEventListener('click', () => navigate(1));
generateButton.addEventListener('click', generateProfile);
downloadPdfButton.addEventListener('click', downloadPDF);
// Initial setup
showTab(0);
});