Shoe Design Creator

Shoe Design Creator

Design Your Shoe

Customize Your Design

Total Price

$0.00

Base Price

$

Manage Materials

$

Existing Materials

No materials added.

'; return; } sdc_data.materials.forEach(material => { const item = document.createElement('div'); item.className = 'sdc-list-item'; item.innerHTML = ` ${sdc_escapeHTML(material.name)} (+$${material.cost.toFixed(2)}) `; sdc_materialListEl.appendChild(item); }); } /** * Saves the new base price */ window.sdc_saveBasePrice = function() { if (!sdc_basePriceInput) return; const newPrice = parseFloat(sdc_basePriceInput.value); if (!isNaN(newPrice) && newPrice >= 0) { sdc_data.basePrice = newPrice; sdc_updatePrice(); alert('Base price updated.'); } else { alert('Please enter a valid price.'); sdc_basePriceInput.value = sdc_data.basePrice.toFixed(2); } } /** * Adds a new material from the form */ window.sdc_addMaterial = function(event) { event.preventDefault(); if (!sdc_newMaterialNameInput || !sdc_newMaterialCostInput) return; const name = sdc_newMaterialNameInput.value.trim(); const cost = parseFloat(sdc_newMaterialCostInput.value); if (name && !isNaN(cost) && cost >= 0) { if (sdc_data.materials.some(m => m.name.toLowerCase() === name.toLowerCase())) { alert('A material with this name already exists.'); return; } sdc_data.materials.push({ name, cost }); sdc_renderConfigLists(); sdc_renderDashboardControls(); // Reset form sdc_newMaterialNameInput.value = ''; sdc_newMaterialCostInput.value = '0.00'; } } /** * Deletes a material */ window.sdc_deleteMaterial = function(name) { if (sdc_data.materials.length <= 1) { alert('You must have at least one material.'); return; } if (confirm(`Are you sure you want to delete "${name}"?`)) { sdc_data.materials = sdc_data.materials.filter(m => m.name !== name); sdc_renderConfigLists(); sdc_renderDashboardControls(); sdc_handleDesignChange(); // Update price in case deleted material was selected } } // --- TAB & NAVIGATION FUNCTIONS --- window.sdc_switchTab = function(tabIndex) { sdc_currentTabIndex = tabIndex; sdc_tabContents.forEach((content, index) => { content.classList.toggle('sdc-active', index === tabIndex); }); sdc_tabs.forEach((tab, index) => { tab.classList.toggle('sdc-active', index === tabIndex); }); sdc_updateNavButtons(); } window.sdc_navigateTabs = function(direction) { if (direction === 'next' && sdc_currentTabIndex < sdc_numTabs - 1) { sdc_switchTab(sdc_currentTabIndex + 1); } else if (direction === 'prev' && sdc_currentTabIndex > 0) { sdc_switchTab(sdc_currentTabIndex - 1); } } function sdc_updateNavButtons() { sdc_prevBtn.style.visibility = (sdc_currentTabIndex === 0) ? 'hidden' : 'visible'; sdc_nextBtn.style.visibility = (sdc_currentTabIndex === sdc_numTabs - 1) ? 'hidden' : 'visible'; } // --- PDF GENERATION --- /** * Generates and downloads the design as a PDF */ window.sdc_generatePdf = function() { if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { alert('Error: PDF generation library (jsPDF) not loaded.'); return; } if (typeof window.jspdf.plugin.autotable === 'undefined') { alert('Error: PDF generation library (jsPDF-AutoTable) not loaded.'); return; } try { const { jsPDF } = jspdf; const doc = new jsPDF(); const svgEl = document.getElementById('sdc-shoe-svg'); const canvasEl = document.getElementById('sdc-pdf-canvas'); if (!svgEl || !canvasEl) { throw new Error('SVG or Canvas element not found.'); } // 1. Serialize and draw SVG to Canvas const svgData = new XMLSerializer().serializeToString(svgEl); const img = new Image(); const svgBase64 = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgData))); img.onload = function() { // Set canvas dimensions const svgRect = svgEl.getBoundingClientRect(); canvasEl.width = svgRect.width * 2; // Increase resolution for PDF canvasEl.height = svgRect.height * 2; const ctx = canvasEl.getContext('2d'); ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); // Draw image to canvas ctx.drawImage(img, 0, 0, canvasEl.width, canvasEl.height); // Get canvas image data const canvasImgData = canvasEl.toDataURL('image/png'); // 2. Build the PDF const margin = 15; const docWidth = doc.internal.pageSize.getWidth(); const imgWidth = docWidth - (margin * 2); const imgHeight = (canvasEl.height * imgWidth) / canvasEl.width; let cursorY = 20; // Title doc.setFont('helvetica', 'bold'); doc.setFontSize(20); doc.setTextColor(varGet('--sdc-primary-color', '#0073e6')); doc.text("My Custom Shoe Design", 105, cursorY, { align: 'center' }); cursorY += 15; // Shoe Image doc.addImage(canvasImgData, 'PNG', margin, cursorY, imgWidth, imgHeight); cursorY += imgHeight + 15; // 3. Add Design Summary Table const basePrice = parseFloat(sdc_data.basePrice) || 0; const material = sdc_data.materials.find(m => m.name === sdc_currentDesign.material); const materialCost = material ? parseFloat(material.cost) : 0; const totalPrice = basePrice + materialCost; const tableHead = [["Component", "Selection", "Cost"]]; const tableBody = [ ['Base Shoe', '-', `$${basePrice.toFixed(2)}`], ['Upper Material', sdc_currentDesign.material, `$${materialCost.toFixed(2)}`], ['Upper Color', sdc_currentDesign.upperColor, '-'], ['Sole Color', sdc_currentDesign.soleColor, '-'], ['Laces Color', sdc_currentDesign.lacesColor, '-'], ['Logo Color', sdc_currentDesign.logoColor, '-'] ]; doc.autoTable({ head: tableHead, body: tableBody, startY: cursorY, theme: 'striped', headStyles: { fillColor: varGet('--sdc-primary-color', '#0073e6'), textColor: varGet('--sdc-text-light', '#fff') }, alternateRowStyles: { fillColor: varGet('--sdc-light-primary', '#e6f1fc') }, // Total Row didDrawPage: (data) => { doc.setFont('helvetica', 'bold'); doc.setFontSize(14); doc.text('Total Price:', data.settings.margin.left, doc.autoTable.previous.finalY + 10); doc.text(`$${totalPrice.toFixed(2)}`, data.table.width - data.settings.margin.right, doc.autoTable.previous.finalY + 10, { align: 'right' }); } }); // 4. Save PDF doc.save('my_shoe_design.pdf'); }; img.src = svgBase64; } catch (e) { console.error("PDF Generation Error: ", e); alert("An error occurred while generating the PDF."); } } // --- UTILITY FUNCTIONS --- function varGet(varName, fallback = '#000') { try { return getComputedStyle(document.documentElement).getPropertyValue(varName).trim() || fallback; } catch (e) { return fallback; } } function sdc_escapeHTML(str) { if (!str) return ''; return str.replace(/[&<>"']/g, function(m) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m]; }); } // --- INITIALIZATION --- function sdc_initTool() { // Setup tabs sdc_switchTab(0); // Populate config tab sdc_renderConfigLists(); // Populate dashboard sdc_renderDashboardControls(); // Set initial state sdc_handleDesignChange(); // Attach event listeners for dashboard controls if (sdc_materialSelect) sdc_materialSelect.addEventListener('input', sdc_handleDesignChange); if (sdc_upperColorInput) sdc_upperColorInput.addEventListener('input', sdc_handleDesignChange); if (sdc_soleColorInput) sdc_soleColorInput.addEventListener('input', sdc_handleDesignChange); if (sdc_lacesColorInput) sdc_lacesColorInput.addEventListener('input', sdc_handleDesignChange); if (sdc_logoColorInput) sdc_logoColorInput.addEventListener('input', sdc_handleDesignChange); } sdc_initTool(); // Run the tool }); // End of DOMContentLoaded