1. Construction & Fit Notes
${fdtg_escapeHTML(data.notes) || 'No specific construction notes provided.'}
2. Materials Specifications
| Item | Content / Supplier | Usage |
|---|---|---|
| No fabrics or trims listed. | ||
3. Color Palette & Codes
| Color Name | HEX Code | Pantone Code |
|---|---|---|
| No colors defined. | ||
${designSheetHTML}
`;
}
/**
* Generates and downloads a PDF of the design sheet
*/
async function fdtg_downloadPDF() {
if (!fdtg_data.styleName) {
alert("Please enter a Style Name before downloading.");
return;
}
if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') {
alert("Error: PDF libraries failed to load.");
return;
}
fdtg_renderPdfClone();
const { jsPDF } = window.jspdf;
try {
const contentDiv = fdtg_pdfRenderClone.querySelector('.pdf-content');
if (!contentDiv) return;
const canvas = await html2canvas(contentDiv, { scale: 1.5, useCORS: true });
const imgData = canvas.toDataURL('image/png');
const imgProps = { width: canvas.width, height: canvas.height };
const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const margin = 40;
const contentWidth = pdfWidth - (margin * 2);
const contentHeight = (contentWidth * imgProps.height) / imgProps.width;
let heightLeft = contentHeight;
let position = 0;
pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight);
heightLeft -= (pdfHeight - margin * 2);
while (heightLeft > 0) {
position -= (pdfHeight - margin * 2);
pdf.addPage();
pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight);
heightLeft -= (pdfHeight - margin * 2);
}
const safeName = (fdtg_data.styleName || 'design_sheet').replace(/[^a-z0-9]/gi, '_').toLowerCase();
pdf.save(`${safeName}_Technical_Sheet.pdf`);
} catch (error) {
console.error("PDF generation failed:", error);
alert("An error occurred while generating the PDF.");
}
}
// --- EVENT LISTENERS ---
// Tab link clicks
fdtg_tabLinks.forEach((link, index) => {
link.addEventListener('click', () => fdtg_switchTab(index));
});
// Next/Prev button clicks
if (fdtg_prevButton) {
fdtg_prevButton.addEventListener('click', () => {
if (fdtg_currentTab > 0) fdtg_switchTab(fdtg_currentTab - 1);
});
}
if (fdtg_nextButton) {
fdtg_nextButton.addEventListener('click', () => {
if (fdtg_currentTab === fdtg_tabLinks.length - 1) {
fdtg_updateDataFromConfig();
fdtg_switchTab(0);
} else {
if (fdtg_currentTab < fdtg_tabLinks.length - 1) fdtg_switchTab(fdtg_currentTab + 1);
}
});
}
// PDF download
if (fdtg_downloadPdfButton) {
fdtg_downloadPdfButton.addEventListener('click', fdtg_downloadPDF);
}
// --- Config Tab Listeners (Fabrics) ---
if (fdtg_addFabricButton) {
fdtg_addFabricButton.addEventListener('click', () => {
fdtg_fabricsContainer.appendChild(fdtg_createFabricInput());
});
}
// --- Config Tab Listeners (Colors) ---
if (fdtg_addColorButton) {
fdtg_addColorButton.addEventListener('click', () => {
fdtg_colorsContainer.appendChild(fdtg_createColorInput());
});
}
if (fdtg_configTab) {
// Handle removal (general removal for fabrics/colors)
fdtg_configTab.addEventListener('click', (e) => {
const removeFabricButton = e.target.closest('.fdtg-remove-fabric');
const removeColorButton = e.target.closest('.fdtg-remove-color');
if (removeFabricButton || removeColorButton) {
const selector = removeFabricButton ? '.p-3[data-id]' : '.flex[data-id]';
removeButton.closest(selector).remove();
}
});
}
// --- INITIALIZATION ---
fdtg_renderConfig();
fdtg_renderDashboard();
// Set initial tab state
fdtg_tabPanes.forEach((pane, index) => {
pane.classList.toggle('hidden', index !== 0);
pane.classList.toggle('fdtg-active', index === 0);
});
fdtg_tabLinks.forEach((link, index) => {
TAB_CLASSES.active.forEach(cls => link.classList.remove(cls));
TAB_CLASSES.inactive.forEach(cls => link.classList.remove(cls));
if (index === 0) {
TAB_CLASSES.active.forEach(cls => link.classList.add(cls));
} else {
TAB_CLASSES.inactive.forEach(cls => link.classList.add(cls));
}
});
});
