Completa tu PACK

Reparte las unidades entre tallas y sube tu diseño. El precio incluye impresión frontal. Si prefieres, puedes enviarlo más tarde (dejaremos el pedido Pendiente de arte).

Tallas Adulto
Asignadas 0/0
Diseño (frente incluido)
Formatos: JPG/PNG/PDF/AI/SVG · Máx. 20 MB · Calidad recomendada: mínimo 1200 px en el lado más corto.
`; grid.appendChild(el); }); updateState(); } function updateState(){ const total=totals(); const ok = total===cantidad; const exceeded = total>cantidad; progress.className='progress '+(ok? 'ok':'bad'); progTxt.textContent = `Asignadas ${total}/${cantidad}`; // data[s]>0).map(s=>`${s}:${data[s]}`).join(' · ')) || '—'; document.querySelectorAll('.inc').forEach(b=>b.disabled = total>=cantidad); if(exceeded){ showError(`Has asignado ${total}/${cantidad}. Reduce ${total-cantidad} prendas.`); if(!overWarned){ alert(`Has superado la cantidad acordada: ${total}/${cantidad}. Reduce ${total-cantidad} prendas.`); overWarned=true; } } else { clearError(); overWarned=false; } validate(); } grid.addEventListener('click', e=>{ const b=e.target.closest('button.btn'); if(!b) return; const sz=b.dataset.size; const act=b.dataset.act; if(act==='inc'){ if(totals()0){ data[sz]--; } updateState(); }); grid.addEventListener('input', e=>{ const input=e.target.closest('input.num'); if(!input) return; const sz=input.dataset.size; const v=Math.max(0, parseInt(input.value,10)||0); const otherTotal = totals() - data[sz]; const remaining = Math.max(0, cantidad - otherTotal); data[sz] = Math.min(v, remaining); if(v>remaining){ input.value = data[sz]; } updateState(); }); document.getElementById('t-auto').addEventListener('click', ()=>{ const perc={XS:0,S:.20,M:.35,L:.30,XL:.10,XXL:.05}; let remain=cantidad; sizes.forEach(s=>{ data[s]=Math.floor(cantidad*(perc[s]||0)); remain-=data[s]; }); const order=['M','L','S','XL','XXL','XS']; let i=0; while(remain>0){ const k=order[i%order.length]; data[k]++; remain--; i++; } updateState(); }); document.getElementById('t-clear').addEventListener('click', ()=>{ sizes.forEach(s=>data[s]=0); updateState(); }); function validate(){ const ready = (totals()===cantidad) && (document.getElementById('t-later').checked || document.getElementById('t-front').files.length>0); const btn=document.getElementById('t-continue'); btn.toggleAttribute('disabled', !ready); btn.setAttribute('aria-disabled', String(!ready)); btn.textContent = ready ? 'Continuar a pago' : 'Completa tallas y archivo'; } document.getElementById('t-front').addEventListener('change', ()=>{ // preview + validate const input=document.getElementById('t-front'); const out=document.getElementById('t-prev-front'); out.textContent=''; const f=input.files && input.files[0]; if(!f){ validate(); return; } const max=20*1024*1024; if(f.size>max){ out.textContent='Archivo demasiado grande (>20MB)'; input.value=''; validate(); return; } const name=f.name.toLowerCase(); if(name.endsWith('.jpg')||name.endsWith('.jpeg')||name.endsWith('.png')||name.endsWith('.svg')){ const reader=new FileReader(); reader.onload=e=>{ const img=new Image(); img.onload=()=>{ out.innerHTML = `
${f.name} (${Math.round(f.size/1024)} KB) — ${img.width}×${img.height}px
`; out.appendChild(img); }; img.src=e.target.result; }; reader.readAsDataURL(f); } else { out.textContent = `${f.name} (${Math.round(f.size/1024)} KB)`; } validate(); }); document.getElementById('t-later').addEventListener('change', validate); // --- Subida AJAX del archivo (si corresponde) --- async function uploadArtworkIfNeeded() { const later = document.getElementById('t-later').checked; const fi = document.getElementById('t-front'); if (later || !fi.files || !fi.files[0]) return null; const fd = new FormData(); fd.append('action', 'cp_pack_upload'); fd.append('nonce', (window.cpPackNonce || '')); fd.append('file', fi.files[0]); const resp = await fetch(window.cpAjax || '/wp-admin/admin-ajax.php', { method: 'POST', body: fd }); const json = await resp.json(); if (!json || !json.success) throw new Error(json && json.data ? json.data : 'Error al subir el archivo.'); return json.data; // {id,url} } // CTA – ir al CARRITO con pack_meta (incluye art_id/art_url si hay) document.getElementById('t-continue').addEventListener('click', async ()=>{ const btn=document.getElementById('t-continue'); if(btn.hasAttribute('disabled')) return; try{ btn.textContent='Procesando…'; btn.disabled=true; let art = await uploadArtworkIfNeeded(); // null si no se sube const meta={ gramaje, color, cantidad, tallas: data, enviar_mas_tarde: document.getElementById('t-later').checked, notas: document.getElementById('t-notes').value, art_id: art ? art.id : null, art_url: art ? art.url : '' }; const payload = btoa(unescape(encodeURIComponent(JSON.stringify(meta)))); const base = (window.cpCartURL || '/carrito/'); const sep = base.includes('?') ? '&' : '?'; window.location.assign(base + sep + 'pack_meta=' + encodeURIComponent(payload)); } catch(err){ alert(err.message || 'No se pudo subir el archivo.'); btn.textContent='Continuar a pago'; btn.disabled=false; } }); renderSizes(); })();

What can I find on Camisetaspersonalizadas.com?

Camisetaspersonalizadas.com offers comprehensive information coverage with regular updates, detailed analysis, and valuable content to keep you informed.

How often is the content updated?

We regularly update our information content to ensure you have access to the latest and most accurate information available in the industry.

Why choose Camisetaspersonalizadas.com for information?

Camisetaspersonalizadas.com is committed to providing reliable, well-researched information content from experienced contributors and trusted sources.