Vue.component('construction-consent-signature-pad', { props: { ownerId: {type: Number, required: true}, ownerName: {type: String, required: true} }, data() { return { window: window, signaturePad: null, consent: null, signatureDate: new Date().toLocaleDateString(), notes: '', penWidth: 2, penColor: '#000000', screenOrientation: 'landscape' } }, //language=Vue template: `

Einwilligung für {{ ownerName }}

Datum: {{ signatureDate }}

`, methods: { async submit() { try { if (this.signaturePad.isEmpty()) { this.window.notify('error', 'Bitte eine Unterschrift hinzufügen'); return; } const data = this.signaturePad.toDataURL(); const response = await axios.post(window.TT_CONFIG['BASE_PATH'] + '/ConstructionConsent/sign', { owner_id: this.ownerId, signature: data, signature_name: this.notes, signature_date: this.signatureDate }); if (response.data.success) { this.window.notify('success', response.data.message || 'Unterschrift erfolgreich gespeichert'); this.$emit('close', true); // Pass true to indicate successful signing } else { this.window.notify('error', response.data.errors ? Object.values(response.data.errors).join('
') : response.data.message || 'Ein Fehler ist aufgetreten'); } } catch (error) { console.error('Error submitting signature:', error); this.window.notify('error', 'Ein Fehler ist beim Speichern der Unterschrift aufgetreten'); } }, updatePenSettings() { this.signaturePad.penColor = this.penColor; this.signaturePad.penWidth = this.penWidth; }, toggleOrientation() { this.screenOrientation = this.screenOrientation === 'landscape' ? 'portrait' : 'landscape'; this.$nextTick(() => { this.resizeCanvas(); }); }, resizeCanvas() { const canvas = document.getElementById('consent-signature-pad'); const container = canvas.parentElement; if (this.screenOrientation === 'landscape') { canvas.width = container.offsetWidth - 20; canvas.height = 300; } else { canvas.width = Math.min(container.offsetWidth - 20, 500); canvas.height = 500; } // Important: maintain drawing after resize const data = this.signaturePad.toData(); this.signaturePad.clear(); if (data) { this.signaturePad.fromData(data); } } }, mounted() { this.$nextTick(() => { const canvas = document.getElementById('consent-signature-pad'); this.signaturePad = new SignaturePad(canvas, { penColor: this.penColor, penWidth: this.penWidth, velocityFilterWeight: 0.5 // Better for tablet input }); // Initial canvas sizing this.resizeCanvas(); // Resize on window change window.addEventListener('resize', this.resizeCanvas); // Handle tablet touch events better canvas.addEventListener('touchstart', function(event) { if (event.cancelable) { event.preventDefault(); } }, {passive: false}); }); }, beforeDestroy() { window.removeEventListener('resize', this.resizeCanvas); } }); // Main Component for Construction Consent Owner Signing Vue.component('construction-consent-sign-tablet', { data() { return { window: window, searchName: '', searchFilter: { consent_status: '', owner_result: '' }, results: [], loading: false, showSignaturePad: false, selectedConsent: null, filterOptions: { consent_status: [ {text: 'Alle Status', value: ''}, {text: 'Offen', value: 'open'}, {text: 'In Bearbeitung', value: 'in_progress'}, {text: 'Abgeschlossen', value: 'completed'} ], owner_result: [ {text: 'Alle Ergebnisse', value: ''}, {text: 'Nicht signiert', value: ''}, {text: 'Zugestimmt', value: 'accepted'}, {text: 'Abgelehnt', value: 'rejected'} ] }, tableConfig: { key: 'ConstructionConsentTable', tableHeader: 'Bauvorhaben Eigentümer', defaultPageSize: 10, headers: [ {text: 'Bauvorhaben', key: 'consent_name', sortable: false, filter: false, class: 'text-nowrap', priority: 9}, {text: 'Projekt', key: 'project_name', sortable: false,filter: false, class: 'text-nowrap', priority: 7}, {text: 'Eigentümer', key: 'owner_name', sortable: false,filter: false, class: 'text-nowrap', priority: 6}, {text: 'Adresse', key: 'owner_address', sortable: false,filter: false, class: '', priority: 5}, {text: 'Eigentümer Status', key: 'owner_status', sortable: false,filter: false, class: 'text-nowrap', priority: 3}, {text: 'Eigentümer Ergebnis', key: 'owner_result', sortable: false,filter: false, class: 'text-nowrap', priority: 2}, {text: 'Aktionen', key: 'actions', sortable: false,filter: false, class: 'text-nowrap text-center', priority: 1} ], } } }, //language=Vue template: ` `, methods: { async searchOwners() { this.loading = true; try { const response = await axios.post( window.TT_CONFIG['BASE_PATH'] + '/ConstructionConsent/searchTablet', { name: this.searchName, filter: this.searchFilter } ); if (response.data.success) { this.results = response.data.results; } else { this.window.notify('error', response.data.message || 'Fehler bei der Suche'); this.results = []; } } catch (error) { console.error('Error searching owners:', error); this.window.notify('error', 'Ein Fehler ist bei der Suche aufgetreten'); this.results = []; } finally { this.loading = false; } }, openSignaturePad(consent) { this.selectedConsent = consent; this.showSignaturePad = true; }, handleSignatureClose(success) { this.showSignaturePad = false; if (success) { // Refresh the data after successful signing this.searchOwners(); } }, getStatusBadgeClass(status) { switch (status) { case 'open': return 'badge-primary'; case 'in_progress': return 'badge-warning'; case 'completed': return 'badge-success'; default: return 'badge-secondary'; } }, getStatusText(status) { switch (status) { case 'open': return 'Offen'; case 'in_progress': return 'In Bearbeitung'; case 'completed': return 'Abgeschlossen'; default: return status; } }, getOwnerStatusBadgeClass(status) { switch (status) { case 'pending': return 'badge-warning'; case 'contacted': return 'badge-info'; case 'signed': return 'badge-success'; case 'returned': return 'badge-success'; default: return 'badge-secondary'; } }, getOwnerStatusText(status) { switch (status) { case 'pending': return 'Ausstehend'; case 'contacted': return 'Kontaktiert'; case 'signed': return 'Unterschrieben'; case 'returned': return 'Zurückgegeben'; default: return status; } }, getOwnerResultBadgeClass(result) { if (!result) return 'badge-primary'; switch (result) { case 'accepted': return 'badge-success'; case 'rejected': return 'badge-danger'; case 'denied': return 'badge-danger'; default: return 'badge-secondary'; } }, getOwnerResultText(result) { if (!result) return 'Nicht signiert'; switch (result) { case 'accepted': return 'Zugestimmt'; case 'rejected': return 'Abgelehnt'; default: return result; } } }, mounted() { // Initialize with empty search to show all results this.searchOwners(); } });