Avg. Resolution Time (Hours)
${avgResolutionTimeElem.textContent}
First Contact Resolution Rate
${fcrRateElem.textContent}
Avg. CSAT Score
${avgCSATScoreElem.textContent}
`;
pdfContentWrapper.appendChild(summarySection);
// Add distribution charts
const chartsSection = document.createElement('div');
chartsSection.classList.add('grid', 'grid-cols-2', 'gap-6', 'mb-6');
chartsSection.innerHTML = `
Avg. Resolution Time by Channel (Hours)
`;
pdfContentWrapper.appendChild(chartsSection);
// Populate PDF charts (re-use logic but target PDF elements)
const ticketsByChannel = supportRecords.reduce((acc, record) => { acc[record.channel] = (acc[record.channel] || 0) + 1; return acc; }, {});
renderBarChart(chartsSection.querySelector('#pdfTicketsByChannelChart'), ticketsByChannel, 'count');
const resolutionTimeByChannelSum = {}; const resolutionTimeByChannelCount = {};
supportRecords.forEach(record => { if (record.resolutionStatus === 'Resolved') { resolutionTimeByChannelSum[record.channel] = (resolutionTimeByChannelSum[record.channel] || 0) + record.resolutionTime; resolutionTimeByChannelCount[record.channel] = (resolutionTimeByChannelCount[record.channel] || 0) + 1; } });
const avgResolutionTimeByChannel = {};
for (const channel in resolutionTimeByChannelSum) { if (resolutionTimeByChannelCount[channel] > 0) { avgResolutionTimeByChannel[channel] = resolutionTimeByChannelSum[channel] / resolutionTimeByChannelCount[channel]; } else { avgResolutionTimeByChannel[channel] = 0; } }
renderBarChart(chartsSection.querySelector('#pdfAvgResolutionTimeByChannelChart'), avgResolutionTimeByChannel, 'hours');
const fcrByChannelCount = {}; const totalTicketsByChannel = {};
supportRecords.forEach(record => { totalTicketsByChannel[record.channel] = (totalTicketsByChannel[record.channel] || 0) + 1; if (record.fcr === 'Yes') { fcrByChannelCount[record.channel] = (fcrByChannelCount[record.channel] || 0) + 1; } });
const fcrRateByChannel = {};
for (const channel in totalTicketsByChannel) { if (totalTicketsByChannel[channel] > 0) { fcrRateByChannel[channel] = (fcrByChannelCount[channel] || 0) / totalTicketsByChannel[channel] * 100; } else { fcrRateByChannel[channel] = 0; } }
renderBarChart(chartsSection.querySelector('#pdfFcrRateByChannelChart'), fcrRateByChannel, 'percentage');
const csatByChannelSum = {}; const csatByChannelCount = {};
supportRecords.forEach(record => { csatByChannelSum[record.channel] = (csatByChannelSum[record.channel] || 0) + record.csatScore; csatByChannelCount[record.channel] = (csatByChannelCount[record.channel] || 0) + 1; });
const avgCSATByChannel = {};
for (const channel in csatByChannelSum) { if (csatByChannelCount[channel] > 0) { avgCSATByChannel[channel] = csatByChannelSum[channel] / csatByChannelCount[channel]; } else { avgCSATByChannel[channel] = 0; } }
renderBarChart(chartsSection.querySelector('#pdfCsatByChannelChart'), avgCSATByChannel, 'csat_score');
// Add detailed support records list table
const supportListSection = document.createElement('div');
supportListSection.innerHTML = `
Detailed Support Records
| ID |
Customer Name |
Date |
Channel |
Issue Type |
Resolution Status |
Resolution Time (Hrs) |
FCR? |
CSAT Score |
Notes |
${dashboardSupportTableBody.innerHTML}
`;
pdfContentWrapper.appendChild(supportListSection);
// Options for html2pdf
const options = {
margin: 10,
filename: 'Customer_Support_Dashboard.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2, logging: true, dpi: 192, letterRendering: true },
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
};
// Generate PDF from the temporary content wrapper
html2pdf().from(pdfContentWrapper).set(options).save();
// Clean up the temporary div (optional, as it's not appended to the DOM)
pdfContentWrapper.remove();
}
/**
* Loads initial sample data for the dashboard.
* Relevant to USA context.
*/
function loadSampleData() {
supportRecords = [
{ id: 'TKT001', customerName: 'Alice Brown', recordDate: '2024-07-01', channel: 'Phone', issueType: 'Billing Inquiry', resolutionStatus: 'Resolved', resolutionTime: 0.5, fcr: 'Yes', csatScore: 5, notes: 'Customer satisfied with quick resolution.' },
{ id: 'TKT002', customerName: 'Bob White', recordDate: '2024-07-01', channel: 'Email', issueType: 'Technical Issue', resolutionStatus: 'Resolved', resolutionTime: 4.2, fcr: 'No', csatScore: 4, notes: 'Required backend team assistance.' },
{ id: 'TKT003', customerName: 'Charlie Green', recordDate: '2024-07-02', channel: 'Chat', issueType: 'Feature Request', resolutionStatus: 'Open', resolutionTime: 1.0, fcr: 'No', csatScore: 3, notes: 'Forwarded to product team.' },
{ id: 'TKT004', customerName: 'Diana Prince', recordDate: '2024-07-02', channel: 'Phone', issueType: 'Account Access', resolutionStatus: 'Resolved', resolutionTime: 0.3, fcr: 'Yes', csatScore: 5, notes: 'Password reset successful.' },
{ id: 'TKT005', customerName: 'Ethan Hunt', recordDate: '2024-07-03', channel: 'Social Media', issueType: 'Product Complaint', resolutionStatus: 'Escalated', resolutionTime: 2.0, fcr: 'No', csatScore: 2, notes: 'Negative public comment, escalated to PR.' },
{ id: 'TKT006', customerName: 'Fiona Davis', recordDate: '2024-07-03', channel: 'Email', issueType: 'Refund Request', resolutionStatus: 'Resolved', resolutionTime: 1.5, fcr: 'Yes', csatScore: 4, notes: 'Refund processed as per policy.' },
{ id: 'TKT007', customerName: 'George Wilson', recordDate: '2024-07-04', channel: 'Phone', issueType: 'Service Interruption', resolutionStatus: 'Resolved', resolutionTime: 0.8, fcr: 'Yes', csatScore: 5, notes: 'Service restored, customer happy.' },
{ id: 'TKT008', customerName: 'Hannah Miller', recordDate: '2024-07-04', channel: 'Chat', issueType: 'Login Issue', resolutionStatus: 'Resolved', resolutionTime: 0.2, fcr: 'Yes', csatScore: 5, notes: 'Quick fix provided.' },
{ id: 'TKT009', customerName: 'Ivan Rodriguez', recordDate: '2024-07-05', channel: 'Email', issueType: 'Bug Report', resolutionStatus: 'Open', resolutionTime: 3.0, fcr: 'No', csatScore: 3, notes: 'Detailed bug report, sent to dev team.' }
];
}