// WorkorderMphBase.js - Shared components for WorkorderMph module // Traffic light component (reused from WorkorderBase) Vue.component('traffic-light-mph', { props: ['deadline', 'status'], computed: { lightInfo() { const deadlineDate = moment.unix(this.deadline); const daysLeft = deadlineDate.diff(moment(), 'days'); if (['completed', 'new', 'cancelled'].includes(this.status)) return { color: '#cccccc', title: 'Status irrelevant für Dringlichkeit' }; if (!deadlineDate.isValid()) return { color: '#cccccc', title: 'Keine Deadline gesetzt' }; if (deadlineDate.isBefore(moment())) return { color: '#dc3545', title: 'Deadline überschritten' }; if (daysLeft <= 7) return { color: '#dc3545', title: 'Dringend: Weniger als 1 Woche' }; if (daysLeft <= 21) return { color: '#ffc107', title: 'Mittel: Weniger als 3 Wochen' }; return { color: '#28a745', title: 'Im Plan: Mehr als 3 Wochen' }; } }, template: `` }); // Wohneinheit Status Manager Component Vue.component('wohneinheit-status-manager', { props: { workorderMphId: { type: Number, required: true }, isAdmin: { type: Boolean, default: false } }, template: `
Wohneinheiten Status
Keine Wohneinheiten gefunden.
{{ we.bezeichner }}
OAID: {{ we.oaid }}
{{ we.contact }}
Keine Kontaktinfo
`, data: () => ({ loading: true, wohneinheiten: [], statusOptions: [] }), methods: { async fetchWohneinheiten() { this.loading = true; try { const basePath = this.isAdmin ? '/WorkorderMphAdmin' : '/WorkorderMphCompany'; const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}${basePath}/getWohneinheiten`, { params: { workorderMphId: this.workorderMphId } }); this.wohneinheiten = data.wohneinheiten.map(we => ({ ...we, changed: false, saving: false })); this.statusOptions = data.statusOptions || []; } catch (e) { window.notify('error', 'Wohneinheiten konnten nicht geladen werden.'); console.error(e); } finally { this.loading = false; } }, markAsChanged(we) { we.changed = true; }, async saveWohneinheit(we) { if (!we.note || !we.note.trim()) { return window.notify('error', 'Bitte eine Notiz eingeben.'); } we.saving = true; try { const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/updateWohneinheit`, { workorderMphId: this.workorderMphId, wohneinheitId: we.wohneinheitId, status: we.status, note: we.note }); if (data.success) { window.notify('success', data.message); we.changed = false; this.$emit('wohneinheit-updated'); } else { window.notify('error', data.message || 'Speichern fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { we.saving = false; } }, getStatusText(statusValue) { const option = this.statusOptions.find(opt => opt.value === statusValue); return option ? option.text : ''; } }, async mounted() { await this.fetchWohneinheiten(); } }); // Checkbox Documentation Component Vue.component('checkbox-documentation', { props: { workorderMphId: { type: Number, required: true }, isAdmin: { type: Boolean, default: false } }, template: `
Dokumentation Checkboxen
`, data: () => ({ loading: true, saving: false, checkboxes: { easement: false, btb: false, fttxLocationSupplied: false, conduitToHuepLaid: false, huepMounted: false, dropCableAvailable: false, spliceCompleted: false } }), methods: { async fetchCheckboxes() { this.loading = true; try { const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/getWorkorderById`, { params: { id: this.workorderMphId } }); this.checkboxes = { easement: !!data.easement, btb: !!data.btb, fttxLocationSupplied: !!data.fttxLocationSupplied, conduitToHuepLaid: !!data.conduitToHuepLaid, huepMounted: !!data.huepMounted, dropCableAvailable: !!data.dropCableAvailable, spliceCompleted: !!data.spliceCompleted }; } catch (e) { window.notify('error', 'Checkboxen konnten nicht geladen werden.'); console.error(e); } finally { this.loading = false; } }, async saveCheckboxes() { this.saving = true; try { const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/updateCheckboxes`, { workorderMphId: this.workorderMphId, ...this.checkboxes }); if (data.success) { window.notify('success', data.message); this.$emit('checkboxes-updated'); } else { window.notify('error', data.message || 'Speichern fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.saving = false; } } }, async mounted() { await this.fetchCheckboxes(); } }); // WorkorderMph Details Manager Vue.component('workorder-mph-details-manager', { props: { workorderMphId: { type: String, required: true }, isAdmin: { type: Boolean, default: false } }, data: () => ({ loading: true, docs: [], journals: [], newJournalMessage: '', addingJournalEntry: false, uploading: false, completing: false, showCompleteModal: false, showAcceptModal: false, uploadData: { files: [], documentType: '', description: '' }, wohneinheitenWithNotes: true, requiredDocs: [ { key: 'huep_photo', label: 'HÜP/HAK Foto', icon: 'fas fa-camera', example: 'Foto der installierten HÜP/HAK' }, { key: 'bep_md_photo', label: 'BEP MD Foto', icon: 'fas fa-camera', example: 'Foto der BEP (MD) Installation' }, { key: 'ont_photo', label: 'ONT Foto', icon: 'fas fa-camera', example: 'Foto der ONT Installation' }, { key: 'cable_routing', label: 'Kabelverlegung', icon: 'fas fa-route', example: 'Fotos der Kabelverlegung im Treppenhaus' }, { key: 'fttx_location', label: 'FTTx Location', icon: 'fas fa-map-marker-alt', example: 'Foto/Dokument der FTTx Location' }, { key: 'signature', label: 'Unterschrift', icon: 'fas fa-signature', example: 'Unterschriebenes Übergabeprotokoll' }, { key: 'other', label: 'Sonstige Dokumentation', icon: 'fas fa-file', example: 'Weitere relevante Dokumente' } ] }), template: `
Auftrag abschließen

Dokumentieren Sie alle Wohneinheiten und laden Sie die erforderlichen Dokumente hoch.


Bitte fügen Sie für jede Wohneinheit eine Notiz hinzu und laden Sie Dokumente hoch.
Auftrag bereits abgeschlossen oder storniert.
Prüfung & Freigabe

Prüfen Sie die hochgeladenen Dokumente:

{{ doc.label }}
Stellen Sie sicher, dass alle relevanten Dokumente vorhanden sind.
Journal
  • {{ formatDate(log.create) }} ({{ log.createByName }}):
    {{ log.text }}
Keine Journaleinträge.
Neues Dokument hochladen
{{ getDocExample(uploadData.documentType) }}
Erlaubt: Bilder (JPG, PNG) und PDF
Möchten Sie diesen Auftrag wirklich abschließen und zur Prüfung einreichen? Soll die Dokumentation für diesen Arbeitsauftrag wirklich akzeptiert und der Auftrag abgeschlossen werden?
`, computed: { isReadOnly() { return ['completed', 'cancelled'].includes(this.workorder?.status); }, canComplete() { return this.wohneinheitenWithNotes && this.docs.length > 0; } }, methods: { formatDate(timestamp) { return timestamp ? window.moment.unix(timestamp).format('DD.MM.YYYY HH:mm') : '–'; }, hasDocType(docType) { return this.docs.some(doc => doc.documentType === docType); }, getDocExample(docType) { const doc = this.requiredDocs.find(d => d.key === docType); return doc ? doc.example : ''; }, async fetchData() { this.loading = true; try { const basePath = this.isAdmin ? '/WorkorderMphAdmin' : '/WorkorderMphCompany'; const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}${basePath}/getDocumentation`, { params: { workorderMphId: this.workorderMphId } }); this.docs = data.docs || []; this.journals = data.journals || []; } catch (e) { window.notify('error', 'Details konnten nicht geladen werden.'); this.docs = []; this.journals = []; } finally { this.loading = false; } }, async addJournalEntry() { if (!this.newJournalMessage.trim()) return window.notify('error', 'Bitte eine Nachricht eingeben.'); this.addingJournalEntry = true; try { const basePath = this.isAdmin ? '/WorkorderMphAdmin' : '/WorkorderMphCompany'; const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}${basePath}/addJournal`, { workorderMphId: this.workorderMphId, text: this.newJournalMessage }); if (data.success) { window.notify('success', data.message); this.journals = data.journals || []; this.newJournalMessage = ''; } else { window.notify('error', data.message || 'Eintrag fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.addingJournalEntry = false; } }, handleFileUpload(event) { this.uploadData.files = event.target.files; }, async uploadFiles() { if (!this.uploadData.files?.length) return window.notify('error', 'Bitte eine oder mehrere Dateien auswählen.'); this.uploading = true; const formData = new FormData(); formData.append('workorderMphId', this.workorderMphId); formData.append('documentType', this.uploadData.documentType); formData.append('description', this.uploadData.description); for (const file of this.uploadData.files) { formData.append('file', file); } try { const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/uploadDocumentation`, formData); if (data.success) { window.notify('success', data.message); this.$refs.fileInput.value = ''; this.uploadData = { files: [], documentType: 'photo', description: '' }; await this.fetchData(); } else { window.notify('error', data.error || 'Upload fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist beim Upload aufgetreten.'); } finally { this.uploading = false; } }, async deleteDocumentation(file) { try { const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/deleteDocumentation`, { documentationId: file.id }); if (data.success) { window.notify('success', data.message); await this.fetchData(); } else { window.notify('error', data.message || 'Löschen fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Netzwerkfehler beim Löschen.'); } }, async completeWorkorder() { this.completing = true; try { const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphCompany/completeWorkorder`, { workorderId: this.workorderMphId }); if (data.success) { window.notify('success', data.message); this.$emit('workorder-completed'); this.showCompleteModal = false; } else { window.notify('error', data.message || 'Abschluss fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.completing = false; } }, async acceptDocumentation() { try { const { data } = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderMphAdmin/acceptDocumentation`, { workorderId: this.workorderMphId }); if (data.success) { window.notify('success', data.message); this.$emit('documentation-accepted'); this.showAcceptModal = false; } else { window.notify('error', data.message || 'Akzeptieren fehlgeschlagen.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } } }, async mounted() { await this.fetchData(); } });