search
f.name)); if (this.uploadedFiles.length + files.length > 5) { alert('You can only upload up to 5 branding files.'); return; } files.forEach(file => { const ext = file.name.split('.').pop().toLowerCase(); if (!['pdf', 'ai', 'eps', 'jpg', 'jpeg', 'png'].includes(ext)) { alert('Only PDF, AI, EPS, JPG, and PNG files are accepted.'); return; } if (file.size > 10 * 1024 * 1024) { alert('File size exceeds the 10MB limit.'); return; } this.uploadFile(file); }); }, updateFileState(filename, data) { const fileObj = this.uploadedFiles.find(f => f.name === filename); if (fileObj) { Object.assign(fileObj, data); this.uploadedFiles = [...this.uploadedFiles]; // Force Alpine reactivity } }, uploadFile(file) { this.uploadedFiles.push({ name: file.name, progress: 0, hashed_name: null, error: null, status: 'uploading' }); this.isUploading = true; this.uploadedFiles = [...this.uploadedFiles]; // Force immediate display of progress bar console.log('uploadFile: Preparing payload for:', file.name); const formData = new FormData(); formData.append('file', file); const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content') || ''; console.log('uploadFile: CSRF token lookup result:', csrfToken ? 'Token Found' : 'Token Missing!'); const xhr = new XMLHttpRequest(); xhr.open('POST', '/upload-quote-file'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); if (csrfToken) { xhr.setRequestHeader('X-CSRF-TOKEN', csrfToken); } xhr.upload.addEventListener('progress', e => { if (e.lengthComputable) { const percentage = Math.round((e.loaded / e.total) * 100); console.log('uploadFile progress (' + file.name + '): ' + percentage + '%'); this.updateFileState(file.name, { progress: percentage }); } }); xhr.addEventListener('load', () => { console.log('uploadFile load complete (' + file.name + '). Status code:', xhr.status); if (xhr.status >= 200 && xhr.status < 300) { try { const response = JSON.parse(xhr.responseText); console.log('uploadFile response (' + file.name + '):', response); if (response.success) { this.updateFileState(file.name, { hashed_name: response.hashed_name, status: 'success', progress: 100 }); } else { this.updateFileState(file.name, { error: response.message || 'Upload failed.', status: 'error' }); } } catch(err) { console.error('JSON parse exception during load handler:', err); this.updateFileState(file.name, { error: 'Invalid server response.', status: 'error' }); } } else { let msg = 'Upload failed.'; try { const err = JSON.parse(xhr.responseText); msg = err.message || msg; } catch(e) {} this.updateFileState(file.name, { error: msg, status: 'error' }); } this.checkUploadStatus(); }); xhr.addEventListener('error', () => { console.error('uploadFile net error (' + file.name + ')'); this.updateFileState(file.name, { error: 'Network error occurred.', status: 'error' }); this.checkUploadStatus(); }); xhr.send(formData); console.log('uploadFile: Sent payload for:', file.name); }, checkUploadStatus() { this.isUploading = this.uploadedFiles.some(f => f.status === 'uploading'); }, removeUploadedFile(index) { this.uploadedFiles.splice(index, 1); this.checkUploadStatus(); }, getBrandingFilesPayload() { return this.uploadedFiles .filter(f => f.status === 'success') .map(f => ({ original_name: f.name, hashed_name: f.hashed_name })); }, getAddIsDisabled(id) { const cartElement = document.querySelector('[x-data=\'shoppingCart\']'); const cart = Alpine.$data(cartElement); return cart.isInCart(id, this.getColourTitle()); }, init() { // Clean up any leading '?&' from the search query string and parse parameters let search = window.location.search; search = search.replace(/^\?&/, '?'); const params = new URLSearchParams(search); // Automatically set the Quantity const quantityParam = params.get('quantity') || params.get('qty'); if (quantityParam) { const qty = parseInt(quantityParam, 10); if (!isNaN(qty) && qty > 0) { this._quantity = qty; } } // Automatically select the Color const colourParam = params.get('colour') || params.get('color'); if (colourParam) { this.$nextTick(() => { const decodedColour = decodeURIComponent(colourParam).trim().toLowerCase(); const buttons = Array.from(document.querySelectorAll('.product-details button[title]')); const match = buttons.find(b => b.getAttribute('title').trim().toLowerCase() === decodedColour); if (match) match.click(); // Triggers the Alpine click handler to select color and update corresponding image }); } } }">

AS Colour NZ

Script Sticker

Colour:

Quantity

Branding Logo or Images

Accepted file types: PDF, AI, EPS, JPG, PNG | Max file size: 10MB | Max files: 1

Product Description expand_more

AS Colour script logo sticker Clear gloss vinyl, kisscut 18cm wide x 4.3cm high

Sizes

One Size

You might also like...