`;
// Render for UI previews
document.getElementById('live-preview-dashboard').innerHTML = contentHtml;
document.getElementById('final-preview').innerHTML = contentHtml;
// Render for PDF
document.getElementById('pdf-render-area').innerHTML = contentHtml.replace(/class="/g, 'style="'); // Basic class to style conversion
};
// --- Template Selection ---
templateCards.forEach(card => {
card.addEventListener('click', () => {
templateCards.forEach(c => c.classList.remove('selected'));
card.classList.add('selected');
proposalData.selectedTemplate = card.dataset.template;
// In a real app, this would change the CSS/layout. Here we just store it.
renderAllPreviews();
});
});
// --- AI Content Generation ---
aiButtons.forEach(button => {
button.addEventListener('click', async () => {
const targetId = button.dataset.target;
const promptTemplate = button.dataset.prompt;
const targetTextarea = document.getElementById(targetId);
if (!targetTextarea) return;
const prompt = promptTemplate
.replace('[Project Name]', proposalData.projectName || 'this project')
.replace('[My Company Name]', proposalData.myCompanyName || 'our company')
.replace('[Your Industry]', proposalData.yourIndustry || 'our industry');
button.textContent = 'Generating...';
button.disabled = true;
try {
let chatHistory = [{ role: "user", parts: [{ text: prompt }] }];
const payload = { contents: chatHistory };
const apiKey = "";
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`;
const response = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!response.ok) throw new Error(`API Error: ${response.status}`);
const result = await response.json();
const text = result.candidates[0].content.parts[0].text;
targetTextarea.value = text.trim();
// Manually trigger input event to update data and previews
targetTextarea.dispatchEvent(new Event('input', { bubbles: true }));
} catch (error) {
console.error('AI Generation Error:', error);
targetTextarea.value = 'Error generating content. Please try again.';
} finally {
button.textContent = 'Generate with AI';
button.disabled = false;
}
});
});
// --- PDF Download ---
downloadPdfBtn.addEventListener('click', () => {
const { jsPDF } = window.jspdf;
const pdfElement = document.getElementById('pdf-render-area');
html2canvas(pdfElement, { scale: 2, useCORS: true }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
const imgHeight = canvas.height * pdfWidth / canvas.width;
let heightLeft = imgHeight;
let position = 0;
pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
pdf.addPage();
pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
heightLeft -= pageHeight;
}
pdf.save(`${proposalData.projectName || 'Proposal'}.pdf`);
});
});
// --- Initial Load ---
bindData();
updateUI();
});