diff --git a/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor b/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor
index e4390286..75e6acbe 100644
--- a/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor
+++ b/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor
@@ -566,9 +566,19 @@ const int MaxThumbnailWidth = 400;
}
[JSInvokable]
- public void OnSignatureButtonClick(int signatureId) {
- Console.WriteLine($"Signature #{signatureId} clicked");
- OpenSignaturePopup();
+ public async Task OnSignatureButtonClick(int signatureId) {
+ if (_capturedSignature == null) {
+ // No signature captured yet - should not happen as popup is shown on page load
+ return;
+ }
+
+ // Apply signature to PDF canvas
+ await JSRuntime.InvokeVoidAsync("pdfViewer.applySignature",
+ signatureId,
+ _capturedSignature.DataUrl,
+ _capturedSignature.FullName,
+ _capturedSignature.Position,
+ _capturedSignature.Place);
}
// Signature popup methods
diff --git a/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js b/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js
index 5c7fc556..e78ede29 100644
--- a/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js
+++ b/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js
@@ -594,7 +594,133 @@ window.pdfViewer = {
}
});
this.signatureButtons = [];
+ },
+
+ /**
+ * Applies a signature to a specific signature field, removing the button and rendering the signature.
+ * German standard: Signature image + Name, Position, Place, Date
+ * @param {number} signatureId - ID of the signature field
+ * @param {string} signatureDataUrl - Base64 PNG data URL of signature
+ * @param {string} fullName - Signer's full name
+ * @param {string} position - Signer's position (optional, can be empty)
+ * @param {string} place - Signing place
+ */
+ async applySignature(signatureId, signatureDataUrl, fullName, position, place) {
+ try {
+ // Find and remove the button
+ const buttonIndex = this.signatureButtons.findIndex(btn => {
+ return btn.getAttribute('data-signature-id') == signatureId;
+ });
+
+ if (buttonIndex === -1) {
+ console.warn(`Signature button #${signatureId} not found`);
+ return;
+ }
+
+ const button = this.signatureButtons[buttonIndex];
+ const signatureLayer = document.getElementById('pdf-signature-layer');
+
+ if (!signatureLayer) {
+ console.error('Signature layer not found');
+ return;
+ }
+
+ // Get button position before removing it
+ const left = button.style.left;
+ const top = button.style.top;
+
+ // Remove button
+ if (button.parentNode) {
+ button.parentNode.removeChild(button);
+ }
+ this.signatureButtons.splice(buttonIndex, 1);
+
+ // Create signature container
+ const signatureContainer = document.createElement('div');
+ signatureContainer.className = 'applied-signature';
+ signatureContainer.setAttribute('data-signature-id', signatureId);
+ signatureContainer.style.position = 'absolute';
+ signatureContainer.style.left = left;
+ signatureContainer.style.top = top;
+ signatureContainer.style.width = '230px';
+ signatureContainer.style.backgroundColor = '#f8f9fa';
+ signatureContainer.style.border = '1px solid #dee2e6';
+ signatureContainer.style.borderRadius = '6px';
+ signatureContainer.style.padding = '12px';
+ signatureContainer.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
+ signatureContainer.style.fontFamily = "'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
+
+ // Signature image
+ const signatureImg = document.createElement('img');
+ signatureImg.src = signatureDataUrl;
+ signatureImg.alt = 'Unterschrift';
+ signatureImg.style.width = '100%';
+ signatureImg.style.height = 'auto';
+ signatureImg.style.maxHeight = '70px';
+ signatureImg.style.display = 'block';
+ signatureImg.style.objectFit = 'contain';
+ signatureImg.style.marginBottom = '6px';
+
+ // Separator line (German standard)
+ const separator = document.createElement('div');
+ separator.style.width = '100%';
+ separator.style.height = '1px';
+ separator.style.backgroundColor = '#495057';
+ separator.style.marginBottom = '8px';
+
+ // Text information container
+ const infoContainer = document.createElement('div');
+ infoContainer.style.fontSize = '9px';
+ infoContainer.style.lineHeight = '1.4';
+ infoContainer.style.color = '#495057';
+ infoContainer.style.fontWeight = '400';
+
+ // Format date (German style: dd.MM.yyyy)
+ const today = new Date();
+ const dateStr = today.toLocaleDateString('de-DE', {
+ day: '2-digit',
+ month: '2-digit',
+ year: 'numeric'
+ });
+
+ // Build text lines (German standard format)
+ const lines = [];
+ lines.push(`${this.escapeHtml(fullName)}`);
+
+ if (position && position.trim() !== '') {
+ lines.push(`${this.escapeHtml(position)}`);
+ }
+
+ lines.push(`${this.escapeHtml(place)}, ${dateStr}`);
+
+ infoContainer.innerHTML = lines.join('
');
+
+ // Assemble container
+ signatureContainer.appendChild(signatureImg);
+ signatureContainer.appendChild(separator);
+ signatureContainer.appendChild(infoContainer);
+
+ // Add to signature layer
+ signatureLayer.appendChild(signatureContainer);
+
+ console.log(`Signature #${signatureId} applied successfully`);
+
+ } catch (error) {
+ console.error('Error applying signature:', error);
+ }
+ },
+
+ /**
+ * Escapes HTML to prevent XSS attacks
+ */
+ escapeHtml(text) {
+ const div = document.createElement('div');
+ div.textContent = text;
+ return div.innerHTML;
}
};
+
+
+