diff --git a/public/app.js b/public/app.js index 767bf6a..87e9412 100644 --- a/public/app.js +++ b/public/app.js @@ -7570,10 +7570,19 @@ document.addEventListener('DOMContentLoaded', () => { const canvasFontSize = document.getElementById('canvasFontSize'); const canvasTextColor = document.getElementById('canvasTextColor'); const canvasBgColorInput = document.getElementById('canvasBgColor'); + const canvasRotation = document.getElementById('canvasRotation'); + const canvasOpacity = document.getElementById('canvasOpacity'); const btnCanvasZIndexUp = document.getElementById('btnCanvasZIndexUp'); const btnCanvasZIndexDown = document.getElementById('btnCanvasZIndexDown'); const btnCanvasDelete = document.getElementById('btnCanvasDelete'); + // Novos controles do Painel de Assets Lateral + const canvasAssetSearch = document.getElementById('canvasAssetSearch'); + const canvasAssetsContainer = document.getElementById('canvasAssetsContainer'); + const btnTabAssetPostits = document.getElementById('btnTabAssetPostits'); + const btnTabAssetStickers = document.getElementById('btnTabAssetStickers'); + const btnTabAssetFormas = document.getElementById('btnTabAssetFormas'); + let canvasModeActive = false; let selectedCanvasItem = null; let isDraggingCanvas = false; @@ -7581,6 +7590,7 @@ document.addEventListener('DOMContentLoaded', () => { let dragStartX, dragStartY; let dragStartLeft, dragStartTop; let dragStartWidth, dragStartHeight; + let activeAssetTab = 'postit'; function enterCanvasMode() { canvasModeActive = true; @@ -7590,6 +7600,15 @@ document.addEventListener('DOMContentLoaded', () => { btnCanvasModeToggle.style.color = 'white'; } if (canvasControlPanel) canvasControlPanel.style.display = 'flex'; + + // Alternar painéis laterais + const configPanel = document.getElementById('cartazLeftConfigPanel'); + const canvasPanel = document.getElementById('cartazLeftCanvasPanel'); + if (configPanel) configPanel.style.display = 'none'; + if (canvasPanel) canvasPanel.style.display = 'flex'; + + // Iniciar na aba correspondente de assets + selectAssetTab(activeAssetTab); cartazPrintableArea.style.position = 'relative'; const rectParent = cartazPrintableArea.getBoundingClientRect(); @@ -7639,7 +7658,7 @@ document.addEventListener('DOMContentLoaded', () => { }); cartazPreviewContent.style.display = 'none'; - showToast('Modo Design Canvas ativado! Arraste, redimensione e clique duas vezes para editar o texto.', 'info'); + showToast('Modo Design Canvas ativado! Adicione elementos e ajuste o mural livremente.', 'info'); } function exitCanvasMode() { @@ -7650,6 +7669,12 @@ document.addEventListener('DOMContentLoaded', () => { btnCanvasModeToggle.style.color = 'var(--text-secondary)'; } if (canvasControlPanel) canvasControlPanel.style.display = 'none'; + + // Alternar painéis de volta + const configPanel = document.getElementById('cartazLeftConfigPanel'); + const canvasPanel = document.getElementById('cartazLeftCanvasPanel'); + if (configPanel) configPanel.style.display = 'flex'; + if (canvasPanel) canvasPanel.style.display = 'none'; if (selectedCanvasItem) { selectedCanvasItem.classList.remove('active-item'); @@ -7660,8 +7685,47 @@ document.addEventListener('DOMContentLoaded', () => { items.forEach(item => { item.removeAttribute('contenteditable'); }); - - showToast('Layout do Canvas salvo com sucesso!', 'success'); + + // Limpar o HTML para persistência (remover seleções/handles) + const tempContainer = document.createElement('div'); + tempContainer.innerHTML = cartazPrintableArea.innerHTML; + tempContainer.querySelectorAll('.canvas-resize-handle').forEach(h => h.remove()); + tempContainer.querySelectorAll('.canvas-item').forEach(el => { + el.classList.remove('active-item'); + el.removeAttribute('contenteditable'); + if (el.style.border && el.style.border.includes('dashed')) { + el.style.border = 'none'; + } + }); + const cleanHtml = tempContainer.innerHTML; + + // Persistir alterações de canvas no banco + if (activeCartazData && activeCartazData.id) { + fetch(`/api/cartazes/${activeCartazData.id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: JSON.stringify({ + conteudo: cleanHtml, + corFundo: cartazBgColor.value, + corTexto: cartazTextColor.value + }) + }).then(res => { + if (res.ok) { + showToast('Layout do Canvas salvo no servidor!', 'success'); + loadCartazesHistory(); + } else { + showToast('Erro ao salvar layout no servidor.', 'error'); + } + }).catch(e => { + console.error(e); + showToast('Erro de conexão ao salvar canvas.', 'error'); + }); + } else { + showToast('Layout salvo temporariamente. Crie o cartaz para salvar definitivamente.', 'warning'); + } } function setupCanvasItemEvents(item) { @@ -7916,6 +7980,12 @@ document.addEventListener('DOMContentLoaded', () => { const bg = rgbToHex(window.getComputedStyle(selectedCanvasItem).backgroundColor); if (canvasBgColorInput) canvasBgColorInput.value = bg; + + const rot = selectedCanvasItem.getAttribute('data-rotation') || '0'; + if (canvasRotation) canvasRotation.value = rot; + + const op = window.getComputedStyle(selectedCanvasItem).opacity || '1'; + if (canvasOpacity) canvasOpacity.value = Math.round(parseFloat(op) * 100); } if (canvasFontFamily) { @@ -7938,6 +8008,23 @@ document.addEventListener('DOMContentLoaded', () => { if (selectedCanvasItem) selectedCanvasItem.style.backgroundColor = canvasBgColorInput.value; }); } + if (canvasRotation) { + canvasRotation.addEventListener('input', () => { + if (selectedCanvasItem) { + const val = canvasRotation.value; + selectedCanvasItem.style.transform = `rotate(${val}deg)`; + selectedCanvasItem.setAttribute('data-rotation', val); + } + }); + } + if (canvasOpacity) { + canvasOpacity.addEventListener('input', () => { + if (selectedCanvasItem) { + const val = canvasOpacity.value; + selectedCanvasItem.style.opacity = parseFloat(val) / 100; + } + }); + } if (btnCanvasZIndexUp) { btnCanvasZIndexUp.addEventListener('click', () => { if (selectedCanvasItem) { @@ -8039,4 +8126,161 @@ document.addEventListener('DOMContentLoaded', () => { } }); } + + function selectAssetTab(tab) { + activeAssetTab = tab; + [btnTabAssetPostits, btnTabAssetStickers, btnTabAssetFormas].forEach(btn => { + if (!btn) return; + const tabIdName = `btnTabAsset${tab.charAt(0).toUpperCase() + tab.slice(1)}s`; + if (btn.id === tabIdName) { + btn.classList.add('active'); + btn.style.background = 'rgba(59, 130, 246, 0.1)'; + btn.style.color = 'var(--text-primary)'; + btn.style.fontWeight = 'bold'; + } else { + btn.classList.remove('active'); + btn.style.background = 'transparent'; + btn.style.color = 'var(--text-secondary)'; + btn.style.fontWeight = 'normal'; + } + }); + loadCanvasAssets(tab, canvasAssetSearch ? canvasAssetSearch.value : ''); + } + + if (btnTabAssetPostits) btnTabAssetPostits.addEventListener('click', () => selectAssetTab('postit')); + if (btnTabAssetStickers) btnTabAssetStickers.addEventListener('click', () => selectAssetTab('sticker')); + if (btnTabAssetFormas) btnTabAssetFormas.addEventListener('click', () => selectAssetTab('forma')); + + if (canvasAssetSearch) { + canvasAssetSearch.addEventListener('input', (e) => { + loadCanvasAssets(activeAssetTab, e.target.value); + }); + } + + async function loadCanvasAssets(tipo, busca = '') { + if (!canvasAssetsContainer) return; + canvasAssetsContainer.innerHTML = '