// Configure pdf.js worker pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; const canvas = document.getElementById('signatureCanvas'); const ctx = canvas.getContext('2d'); let isDrawing = false; let hasSignature = false; let ws = null; let currentPdf = null; let pdfDoc = null; let currentPageNum = 1; let totalPages = 1; connectWebSocket(); function connectWebSocket() { // Use current host (works for localhost, IP addresses, and reverse proxy) const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsHost = window.location.hostname; // If using HTTPS (reverse proxy), use same port as page (usually 443, no port needed) // If using HTTP directly, use port 8080 const wsPort = window.location.protocol === 'https:' ? '' : ':8080'; const wsUrl = `${wsProtocol}//${wsHost}${wsPort}`; console.log('Verbinde WebSocket zu:', wsUrl); ws = new WebSocket(wsUrl); ws.onopen = () => { console.log('WebSocket verbunden'); document.getElementById('loadingSection').style.display = 'none'; document.getElementById('waitingSection').style.display = 'block'; // Register as signature station ws.send(JSON.stringify({ type: 'register_signature' })); }; ws.onmessage = async (event) => { const data = JSON.parse(event.data); if (data.type === 'already_connected') { console.log('⚠️ Bereits eine andere Signatur-Station verbunden'); // Show warning message const warning = document.getElementById('alreadyConnectedWarning'); if (warning) { warning.style.display = 'block'; } } else if (data.type === 'pdf') { console.log('PDF empfangen'); currentPdf = new Uint8Array(data.pdf); // Show PDF notification document.getElementById('waitingSection').style.display = 'none'; document.getElementById('signatureSection').style.display = 'block'; document.getElementById('pdfDisplay').classList.add('show'); // Render ALL pages of PDF await renderPdfPreview(currentPdf); // Clear previous signature if any clearSignature(); } else if (data.type === 'page_change') { currentPageNum = data.pageNum; totalPages = data.totalPages; // Scroll to the specific page const pageCanvas = document.getElementById(`page-canvas-${data.pageNum}`); if (pageCanvas) { pageCanvas.scrollIntoView({ behavior: 'smooth', block: 'start' }); } } else if (data.type === 'signature_placed') { console.log('✅ Unterschrift wurde platziert! Reset in 5 Sekunden...'); console.log('Empfangene Daten:', JSON.stringify(data)); // Show immediate feedback const successMsg = document.getElementById('successMessage'); successMsg.classList.add('show'); // Reset after 5 seconds setTimeout(() => { console.log('Auto-Reset wird durchgeführt...'); // Clear signature clearSignature(); // Hide success message document.getElementById('successMessage').classList.remove('show'); // Hide PDF and signature section, show waiting document.getElementById('signatureSection').style.display = 'none'; document.getElementById('pdfDisplay').classList.remove('show'); document.getElementById('waitingSection').style.display = 'block'; // Reset PDF data currentPdf = null; pdfDoc = null; currentPageNum = 1; totalPages = 1; console.log('Bereit für nächste Unterschrift'); }, 5000); } else if (data.type === 'discard') { console.log('🔄 Verwerfen-Nachricht empfangen, setze zurück...'); resetSignatureStation(); } }; ws.onerror = (error) => { console.error('WebSocket Fehler:', error); document.getElementById('loadingSection').innerHTML = '
❌ Verbindung zum Server fehlgeschlagen.
'; }; ws.onclose = () => { console.log('WebSocket getrennt'); setTimeout(connectWebSocket, 1000); }; } async function renderPdfPreview(pdfBytes, pageNum = null) { try { // Create fresh copy to prevent detachment const safeCopy = new Uint8Array(pdfBytes.buffer.slice(0)); console.log('renderPdfPreview aufgerufen mit', pdfBytes.length, 'bytes'); const loadingTask = pdfjsLib.getDocument({ data: safeCopy }); pdfDoc = await loadingTask.promise; totalPages = pdfDoc.numPages; // Update page info const pageText = currentLanguage === 'de' ? 'Seite' : 'Page'; const pagesText = currentLanguage === 'de' ? 'Seiten' : 'Pages'; document.getElementById('pageInfoSignature').textContent = totalPages === 1 ? `${pageText} 1 ${currentLanguage === 'de' ? 'von' : 'of'} 1` : `${totalPages} ${pagesText}`; // Get container const container = document.getElementById('pdfPagesContainer'); container.innerHTML = ''; // Clear existing content // Render all pages for (let pageNum = 1; pageNum <= totalPages; pageNum++) { // Add page separator if not first page if (pageNum > 1) { const separator = document.createElement('div'); separator.className = 'page-separator'; const pageText = currentLanguage === 'de' ? 'Seite' : 'Page'; separator.textContent = `${pageText} ${pageNum}`; container.appendChild(separator); } else { // First page indicator const separator = document.createElement('div'); separator.className = 'page-separator'; const pageText = currentLanguage === 'de' ? 'Seite' : 'Page'; separator.textContent = `${pageText} 1`; container.appendChild(separator); } // Create canvas for this page const canvas = document.createElement('canvas'); canvas.className = 'pdf-preview-canvas'; canvas.id = `page-canvas-${pageNum}`; container.appendChild(canvas); // Render page const page = await pdfDoc.getPage(pageNum); const ctx = canvas.getContext('2d'); const viewport = page.getViewport({ scale: 1.2 }); canvas.width = viewport.width; canvas.height = viewport.height; const renderContext = { canvasContext: ctx, viewport: viewport }; await page.render(renderContext).promise; } console.log('Alle', totalPages, 'Seiten erfolgreich gerendert'); } catch (error) { console.error('Fehler beim Rendern der PDF Vorschau:', error); } } // Canvas setup ctx.strokeStyle = '#000'; ctx.lineWidth = 2; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; function startDrawing(e) { isDrawing = true; const pos = getPosition(e); ctx.beginPath(); ctx.moveTo(pos.x, pos.y); } function draw(e) { if (!isDrawing) return; e.preventDefault(); const pos = getPosition(e); ctx.lineTo(pos.x, pos.y); ctx.stroke(); hasSignature = true; document.getElementById('submitButton').disabled = false; } function stopDrawing() { isDrawing = false; } function getPosition(e) { const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; if (e.touches && e.touches.length > 0) { return { x: (e.touches[0].clientX - rect.left) * scaleX, y: (e.touches[0].clientY - rect.top) * scaleY }; } return { x: (e.clientX - rect.left) * scaleX, y: (e.clientY - rect.top) * scaleY }; } // Mouse events canvas.addEventListener('mousedown', startDrawing); canvas.addEventListener('mousemove', draw); canvas.addEventListener('mouseup', stopDrawing); canvas.addEventListener('mouseout', stopDrawing); // Touch events canvas.addEventListener('touchstart', startDrawing); canvas.addEventListener('touchmove', draw); canvas.addEventListener('touchend', stopDrawing); // Clear button document.getElementById('clearButton').addEventListener('click', () => { clearSignature(); }); function clearSignature() { ctx.clearRect(0, 0, canvas.width, canvas.height); hasSignature = false; document.getElementById('submitButton').disabled = true; document.getElementById('successMessage').classList.remove('show'); document.getElementById('errorMessage').classList.remove('show'); } function resetSignatureStation() { console.log('=== SIGNATUR-STATION ZURÜCKSETZEN ==='); // Clear signature canvas clearSignature(); // Hide success and error messages document.getElementById('successMessage').classList.remove('show'); document.getElementById('errorMessage').classList.remove('show'); // Hide PDF and signature section, show waiting document.getElementById('signatureSection').style.display = 'none'; document.getElementById('pdfDisplay').classList.remove('show'); document.getElementById('waitingSection').style.display = 'block'; // Clear PDF pages container const container = document.getElementById('pdfPagesContainer'); if (container) { container.innerHTML = ''; } // Reset PDF data currentPdf = null; pdfDoc = null; currentPageNum = 1; totalPages = 1; console.log('Signatur-Station zurückgesetzt - bereit für neue PDF'); } // Submit button document.getElementById('submitButton').addEventListener('click', async () => { if (!hasSignature || !ws || ws.readyState !== WebSocket.OPEN) return; try { // Get signature as data URL const signatureDataUrl = canvas.toDataURL('image/png'); // Send to server (no session ID needed) ws.send(JSON.stringify({ type: 'signature', signature: signatureDataUrl })); // Show success message document.getElementById('successMessage').classList.add('show'); document.getElementById('submitButton').disabled = true; console.log('Unterschrift gesendet, warte auf Platzierungs-Bestätigung...'); } catch (error) { console.error('Fehler beim Senden:', error); document.getElementById('errorMessage').classList.add('show'); } });