Public Relations (PR) Campaign Plan Outline

PR Campaign Plan Outline

Public Relations Campaign Plan Outline

A. Campaign Basics & Objectives

B. Core Strategy & Narrative

C. Execution: Activities & Timeline

Activity Target/Channel Date Status Action
No activities planned.

D. Evaluation & Budget

Budget Tracking (USD - $)

Key Performance Indicators (KPIs)

Final Report Preview

Click the 'Next' button to refresh the preview content.

Client: ${data.brandClient || 'N/A'} | Report Date: ${new Date().toLocaleDateString()}

Status: ${data.overallStatus}

Target Audience: ${data.targetAudience.substring(0, 70)}...

Primary Channel: ${data.primaryChannel}

Budget: ${totalBudget} | Spend: ${actualSpend}

Remaining: ${remaining}

Primary KPIs: ${data.kpis.join(', ').substring(0, 70)}...

Core Message

${data.coreMessage || 'N/A'}

Execution Snapshot (${data.executionPlan.filter(i => i.status === 'Complete').length}/${data.executionPlan.length} Complete)

    ${data.executionPlan.slice(0, 3).map(item => `
  • [${item.date}] ${item.activity} (${item.status})
  • `).join('')} ${data.executionPlan.length > 3 ? `
  • ... and ${data.executionPlan.length - 3} more activities.
  • ` : ''}
`; previewContent.innerHTML = html; } // --- Data Aggregation --- function collectAllData() { const data = { // Tab 0 campaignName: campaignNameInput.value.trim(), brandClient: brandClientInput.value.trim(), startDate: startDateInput.value, targetAudience: targetAudienceTextarea.value.trim(), primaryObjectives: primaryObjectivesTextarea.value.trim(), // Tab 1 coreMessage: coreMessageTextarea.value.trim(), keyThemes: keyThemesInput.value.split(',').map(s => s.trim()).filter(s => s), tone: toneSelect.value, primaryChannel: channelSelect.value, // Tab 2 (already in state: executionPlan) executionPlan: executionPlan, // Tab 3 totalBudget: parseFloat(totalBudgetInput.value) || 0, actualSpend: parseFloat(actualSpendInput.value) || 0, kpis: kpisTextarea.value.split(',').map(s => s.trim()).filter(s => s) }; // Set status for PDF only data.overallStatus = container.querySelector('#prcpo-tab-0 #prcpo-overall-status').value; return data; } // --- PDF Generation (Spec II.C) --- function downloadPDF() { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert('Error: jsPDF library not loaded.'); return; } const data = collectAllData(); const { jsPDF } = window.jspdf; const doc = new jsPDF(); const margin = 40; const pageWidth = doc.internal.pageSize.getWidth(); let currentY = margin; // --- Helper function to add space and break pages --- function checkY(needed) { if (currentY + needed > doc.internal.pageSize.getHeight() - margin) { doc.addPage(); currentY = margin; } } // --- Section 1: Header --- doc.setFontSize(22); doc.setFont('helvetica', 'bold'); doc.setTextColor(124, 58, 237); // violet-600 doc.text(data.campaignName || 'PR CAMPAIGN PLAN', pageWidth / 2, currentY, { align: 'center' }); currentY += 15; doc.setFontSize(12); doc.setFont('helvetica', 'normal'); doc.setTextColor(51, 65, 85); doc.text(`Client: ${data.brandClient || 'N/A'} | Report Date: ${new Date().toLocaleDateString()}`, pageWidth / 2, currentY, { align: 'center' }); currentY += 25; // --- Section 2: Overview --- doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text("1. Overview & Goals", margin, currentY); currentY += 15; const overviewData = [ ["Campaign Start Date:", data.startDate || 'N/A', "Overall Status:", data.overallStatus], ["Tone / Voice:", data.tone, "Primary Channel:", data.primaryChannel], ["Target Audience:", data.targetAudience], ["Primary Objectives:", data.primaryObjectives] ]; doc.autoTable({ startY: currentY, body: overviewData, theme: 'striped', styles: { fontSize: 9, cellPadding: 3 }, columnStyles: { 0: { fontStyle: 'bold', fillColor: [243, 232, 255] }, 2: { fontStyle: 'bold', fillColor: [243, 232, 255] } } }); currentY = doc.autoTable.previous.finalY + 15; // --- Section 3: Strategy --- checkY(40); doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text("2. Strategy & Messaging", margin, currentY); currentY += 15; doc.setFontSize(10); doc.setFont('helvetica', 'bold'); doc.text("Core Message:", margin, currentY); currentY += 12; doc.setFont('helvetica', 'normal'); let messageLines = doc.splitTextToSize(data.coreMessage || 'N/A', pageWidth - margin * 2); doc.text(messageLines, margin, currentY); currentY += messageLines.length * 12 + 8; doc.setFont('helvetica', 'bold'); doc.text("Key Themes:", margin, currentY); currentY += 12; doc.setFont('helvetica', 'normal'); doc.text(data.keyThemes.join(' • ') || 'N/A', margin, currentY); currentY += 15; // --- Section 4: Execution Plan --- checkY(40); doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text("3. Execution Plan & Timeline", margin, currentY); currentY += 15; if (data.executionPlan.length > 0) { const executionTableData = data.executionPlan.map(item => [ item.activity, item.target || 'N/A', item.date, item.status ]); doc.autoTable({ startY: currentY, head: [['Activity', 'Target/Channel', 'Date Due', 'Status']], body: executionTableData, theme: 'striped', headStyles: { fillColor: [124, 58, 237] }, // violet-600 styles: { fontSize: 8 } }); currentY = doc.autoTable.previous.finalY + 15; } else { doc.setFontSize(10); doc.setFont('helvetica', 'italic'); doc.text("No execution activities are currently planned.", margin, currentY); currentY += 15; } // --- Section 5: Budget & Evaluation --- checkY(80); doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text("4. Evaluation & Budget", margin, currentY); currentY += 15; const financeData = [ ["Budget Metrics", "Value"], ["Total Allocated Budget:", formatCurrency(data.totalBudget)], ["Actual Spend to Date:", formatCurrency(data.actualSpend)], ["Remaining Budget:", formatCurrency(data.totalBudget - data.actualSpend)], ]; doc.autoTable({ startY: currentY, body: financeData, theme: 'plain', styles: { fontSize: 10, cellPadding: 3, textColor: [33, 41, 53] }, columnStyles: { 0: { fontStyle: 'bold', cellWidth: 150 } } }); currentY = doc.autoTable.previous.finalY + 15; doc.setFontSize(10); doc.setFont('helvetica', 'bold'); doc.text("Key Performance Indicators (KPIs):", margin, currentY); currentY += 12; doc.setFont('helvetica', 'normal'); let kpiLines = doc.splitTextToSize(data.kpis.join('; ') || 'N/A', pageWidth - margin * 2); doc.text(kpiLines, margin, currentY); currentY += kpiLines.length * 12 + 10; doc.save('pr-campaign-plan.pdf'); } // --- Initial Load and Event Listeners --- addActivityBtn.addEventListener('click', addActivity); pdfBtn.addEventListener('click', downloadPDF); // Set default date startDateInput.value = new Date().toISOString().split('T')[0]; // Initial render renderExecutionPlan(); prcpoShowTab(0); });
Scroll to Top