enhanced preorder map
This commit is contained in:
@@ -21,6 +21,7 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
showFaultsModal: false,
|
||||
logoControlAdded: false,
|
||||
userIdToNameMap: new Map(),
|
||||
editingFault: null, // Temporary state for the fault being edited
|
||||
faultReasons: [
|
||||
{ value: 'building_type', text: 'Gebäudetyp ist falsch' },
|
||||
{ value: 'home_count', text: 'Anzahl der Wohneinheiten ist falsch' },
|
||||
@@ -112,12 +113,12 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
}
|
||||
const storedShowFcps = localStorage.getItem('rimoMapShowFcps');
|
||||
this.showFcps = storedShowFcps !== null ? JSON.parse(storedShowFcps) : true;
|
||||
window.updateMapFault = this.handleFaultUpdate.bind(this);
|
||||
window.saveMapFaults = this.saveFaults.bind(this);
|
||||
window.updateEditingFault = this.updateTempFault.bind(this);
|
||||
window.saveEditingFault = this.saveFaults.bind(this);
|
||||
},
|
||||
beforeDestroy() {
|
||||
delete window.updateMapFault;
|
||||
delete window.saveMapFaults;
|
||||
delete window.updateEditingFault;
|
||||
delete window.saveEditingFault;
|
||||
},
|
||||
methods: {
|
||||
addLogoToMap() {
|
||||
@@ -263,7 +264,7 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
const rimoType = this.getNormalizedRimoType(group.rimo_type);
|
||||
const markerIcon = this.getMarkerIcon(rimoType);
|
||||
const fault = this.faults[group.hausnummer_id];
|
||||
const hasFault = fault && !fault.done;
|
||||
const hasFault = fault && !fault.done && (fault.reasons.length > 0 || (fault.other && fault.other.trim() !== ''));
|
||||
|
||||
let tooltipInnerClass = '';
|
||||
if (rimoType !== 'greenfield' && group.wohneinheit_count > 0 && group.wohneinheit_count === group.preorder_count)
|
||||
@@ -330,11 +331,11 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
const formInputs = this.faultReasons.map(reason => {
|
||||
const isChecked = faultData.reasons.includes(reason.value);
|
||||
const otherInput = (reason.value === 'other') ?
|
||||
`<textarea class="fault-other-textarea ${isChecked ? '' : 'hidden'}" oninput="window.updateMapFault(${itemGroup.hausnummer_id}, 'other_text', this.value, false)">${faultData.other || ''}</textarea>` :
|
||||
`<textarea class="fault-other-textarea ${isChecked ? '' : 'hidden'}" oninput="window.updateEditingFault('other_text', this.value)">${faultData.other || ''}</textarea>` :
|
||||
'';
|
||||
|
||||
return `<label>
|
||||
<input type="checkbox" onchange="window.updateMapFault(${itemGroup.hausnummer_id}, '${reason.value}', this.checked, false)" ${isChecked ? 'checked' : ''}>
|
||||
<input type="checkbox" onchange="window.updateEditingFault('${reason.value}', this.checked)" ${isChecked ? 'checked' : ''}>
|
||||
${reason.text}
|
||||
</label>
|
||||
${otherInput}`;
|
||||
@@ -342,15 +343,20 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
|
||||
return `<h6>Fehler melden/bearbeiten:</h6>
|
||||
${formInputs}
|
||||
<button class="btn btn-primary btn-sm mt-2" onclick="window.saveMapFaults()">Fehler Speichern</button>`;
|
||||
<button class="btn btn-primary btn-sm mt-2" onclick="window.saveEditingFault()">Fehler Speichern</button>`;
|
||||
},
|
||||
generateBuildingPopupHtml(itemGroup) {
|
||||
const faultData = this.faults[itemGroup.hausnummer_id] || { reasons: [], other: '' };
|
||||
const currentFault = this.faults[itemGroup.hausnummer_id] || { reasons: [], other: '', done: false };
|
||||
this.editingFault = {
|
||||
hausnummerId: itemGroup.hausnummer_id,
|
||||
data: JSON.parse(JSON.stringify(currentFault))
|
||||
};
|
||||
|
||||
const detailsHtml = this._generateBuildingDetailsHtml(itemGroup);
|
||||
const faultFormHtml = this._generateBuildingFaultFormHtml(itemGroup, faultData);
|
||||
const faultDisplayHtml = faultData.done ?
|
||||
`<div class="alert alert-success"><i class="fas fa-check-circle"></i> Dieser Fehler wurde von <strong>${this.userIdToNameMap.get(String(faultData.done_by)) || `User #${faultData.done_by}`}</strong> am ${new Date(faultData.done_at).toLocaleDateString()} als erledigt markiert.</div>` :
|
||||
this._generateBuildingFaultDisplayHtml(faultData);
|
||||
const faultFormHtml = this._generateBuildingFaultFormHtml(itemGroup, this.editingFault.data);
|
||||
const faultDisplayHtml = this.editingFault.data.done ?
|
||||
`<div class="alert alert-success"><i class="fas fa-check-circle"></i> Dieser Fehler wurde von <strong>${this.userIdToNameMap.get(String(this.editingFault.data.done_by)) || `User #${this.editingFault.data.done_by}`}</strong> am ${new Date(this.editingFault.data.done_at).toLocaleDateString()} als erledigt markiert.</div>` :
|
||||
this._generateBuildingFaultDisplayHtml(this.editingFault.data);
|
||||
|
||||
return `<div class="building-popup-content">
|
||||
${detailsHtml}
|
||||
@@ -359,36 +365,49 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
<div class="fault-reporting-form">${faultFormHtml}</div>
|
||||
</div>`;
|
||||
},
|
||||
handleFaultUpdate(hausnummerId, reason, value, from_mark_as_done = false) {
|
||||
if (!this.faults[hausnummerId])
|
||||
this.$set(this.faults, hausnummerId, { reasons: [], other: '', done: false });
|
||||
else if (this.faults[hausnummerId].done && !from_mark_as_done)
|
||||
this.$set(this.faults, hausnummerId, { reasons: [], other: '', done: false });
|
||||
updateTempFault(reason, value) {
|
||||
if (!this.editingFault) return;
|
||||
|
||||
if (this.editingFault.data.done) {
|
||||
this.editingFault.data.done = false;
|
||||
this.editingFault.data.done_by = null;
|
||||
this.editingFault.data.done_at = null;
|
||||
}
|
||||
|
||||
const fault = this.faults[hausnummerId];
|
||||
const fault = this.editingFault.data;
|
||||
|
||||
if (reason === 'other_text') {
|
||||
fault.other = value;
|
||||
} else if (reason) {
|
||||
} else { // It's a checkbox change
|
||||
const index = fault.reasons.indexOf(reason);
|
||||
if (value && index === -1) fault.reasons.push(reason);
|
||||
else if (!value && index > -1) fault.reasons.splice(index, 1);
|
||||
|
||||
const popup = this.$refs.ttMap?.map?._popup;
|
||||
if (popup?.isOpen()) {
|
||||
const otherTextarea = popup.getElement().querySelector('.fault-other-textarea');
|
||||
if (otherTextarea) otherTextarea.classList.toggle('hidden', !fault.reasons.includes('other'));
|
||||
if (value && index === -1) { // checked
|
||||
fault.reasons.push(reason);
|
||||
} else if (!value && index > -1) { // unchecked
|
||||
fault.reasons.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const markerInstance = this.$refs.ttMap.markerLayer.getLayers().find(m => m.tt_hausnummerId == hausnummerId);
|
||||
if (markerInstance?.getElement) {
|
||||
const hasOpenFault = fault && !fault.done && (fault.reasons.length > 0 || fault.other);
|
||||
markerInstance.getElement().classList.toggle('marker-has-fault', hasOpenFault);
|
||||
if (reason === 'other') {
|
||||
const popup = this.$refs.ttMap?.map?._popup;
|
||||
if (popup?.isOpen()) {
|
||||
const otherTextarea = popup.getElement().querySelector('.fault-other-textarea');
|
||||
if (otherTextarea) {
|
||||
const hasOther = fault.reasons.includes('other');
|
||||
otherTextarea.classList.toggle('hidden', !hasOther);
|
||||
if (!hasOther) {
|
||||
otherTextarea.value = '';
|
||||
fault.other = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async saveFaults() {
|
||||
if (!this.editingFault) return;
|
||||
const { hausnummerId, data } = this.editingFault;
|
||||
|
||||
this.$set(this.faults, hausnummerId, data);
|
||||
|
||||
const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Preorder/RimoTypeMapSaveFaults`, {
|
||||
campaignId: this.selectedCampaign,
|
||||
faults: this.faults
|
||||
@@ -396,9 +415,11 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
if (response.data.success) {
|
||||
window.notify('success', 'Fehlerbericht gespeichert.');
|
||||
this.$refs.ttMap?.map.closePopup();
|
||||
this.mapMarkers = this.processData(this.rawRimoData);
|
||||
} else {
|
||||
window.notify('error', 'Fehlerbericht konnte nicht gespeichert werden.');
|
||||
}
|
||||
this.editingFault = null;
|
||||
},
|
||||
async markFaultAsDone(hausnummerId) {
|
||||
if (!hausnummerId || !this.faults[hausnummerId]) return;
|
||||
@@ -411,7 +432,6 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
});
|
||||
|
||||
await this.saveFaults();
|
||||
this.handleFaultUpdate(hausnummerId, null, null, true);
|
||||
},
|
||||
zoomToFaultMarker(hausnummerId) {
|
||||
const map = this.$refs.ttMap?.map;
|
||||
@@ -475,28 +495,28 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
></tt-select>
|
||||
</div>
|
||||
<div class="map-filter-container" v-if="selectedCampaign">
|
||||
<h6 class="mr-2 font-weight-bold align-self-center">Filter:</h6>
|
||||
<button v-for="filter in filterOptions"
|
||||
:key="filter.value"
|
||||
@click="toggleFilter(filter.value)"
|
||||
class="btn btn-sm"
|
||||
:style="getFilterButtonStyle(filter.value)"
|
||||
:title="filter.text">
|
||||
<i :class="filter.icon"></i>
|
||||
</button>
|
||||
<div class="filter-separator"></div>
|
||||
<button @click="showOnlyFaults = !showOnlyFaults"
|
||||
class="btn btn-sm"
|
||||
:class="showOnlyFaults ? 'btn-danger' : 'btn-outline-danger'"
|
||||
title="Nur Gebäude mit Fehlern anzeigen">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</button>
|
||||
<button @click="toggleShowFcps"
|
||||
class="btn btn-sm"
|
||||
:class="showFcps ? 'btn-info' : 'btn-outline-info'"
|
||||
title="FCPs anzeigen/ausblenden">
|
||||
<i class="fas fa-broadcast-tower"></i>
|
||||
</button>
|
||||
<h6 class="mr-2 font-weight-bold align-self-center">Filter:</h6>
|
||||
<button v-for="filter in filterOptions"
|
||||
:key="filter.value"
|
||||
@click="toggleFilter(filter.value)"
|
||||
class="btn btn-sm"
|
||||
:style="getFilterButtonStyle(filter.value)"
|
||||
:title="filter.text">
|
||||
<i :class="filter.icon"></i>
|
||||
</button>
|
||||
<div class="filter-separator"></div>
|
||||
<button @click="showOnlyFaults = !showOnlyFaults"
|
||||
class="btn btn-sm"
|
||||
:class="showOnlyFaults ? 'btn-danger' : 'btn-outline-danger'"
|
||||
title="Nur Gebäude mit Fehlern anzeigen">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</button>
|
||||
<button @click="toggleShowFcps"
|
||||
class="btn btn-sm"
|
||||
:class="showFcps ? 'btn-info' : 'btn-outline-info'"
|
||||
title="FCPs anzeigen/ausblenden">
|
||||
<i class="fas fa-broadcast-tower"></i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:legend>
|
||||
|
||||
Reference in New Issue
Block a user