Merge branch 'Preorder/update-map' into 'master'
enhanced preorder map See merge request fronk/thetool!1774
This commit is contained in:
@@ -6,10 +6,11 @@
|
||||
<style>
|
||||
body { font-family: "Open Sans", sans-serif, Verdana; font-size: 10px; color: #333; }
|
||||
.fault-entry {
|
||||
border: 1px solid #ddd;
|
||||
/* Enhanced border for better printing */
|
||||
border: 1.5pt solid #aaa;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 15px;
|
||||
padding: 12px;
|
||||
padding: 10px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.fault-entry h2 {
|
||||
@@ -17,16 +18,66 @@
|
||||
color: #005384;
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #f7c423;
|
||||
/* Enhanced border for better printing */
|
||||
border-bottom: 1.5pt solid #f7c423;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.info-table { width: 100%; border-collapse: collapse; font-size: 10px; }
|
||||
.info-table { width: 100%; border-collapse: collapse; font-size: 10px; margin-bottom: 10px; }
|
||||
.info-table td { padding: 4px; vertical-align: top; }
|
||||
.info-table td.label { font-weight: bold; width: 120px; color: #444; }
|
||||
.faults-section { margin-top: 10px; border-top: 1px dashed #ccc; padding-top: 10px; }
|
||||
.faults-section h3 { font-size: 12px; color: #c0392b; margin-top: 0; margin-bottom: 5px; }
|
||||
.faults-section ul { margin: 0; padding-left: 20px; list-style-type: square; }
|
||||
.faults-section .other-text { background-color: #fef9e7; padding: 8px; border-left: 3px solid #f7c423; margin-top: 8px; font-style: italic; }
|
||||
|
||||
/* Container for the two-column fault layout */
|
||||
.faults-layout-table { width: 100%; border-spacing: 10px 0; border-collapse: separate; table-layout: fixed; }
|
||||
.faults-layout-table td { vertical-align: top; width: 50%; }
|
||||
|
||||
/* Red box for reported fault reasons */
|
||||
.fault-reasons-box {
|
||||
background-color: #fdedec;
|
||||
/* Enhanced border for better printing */
|
||||
border: 1.5pt solid #d63031;
|
||||
border-left: 3pt solid #c0392b;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
height: 100%; /* Ensures boxes have similar height */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.fault-reasons-box h3 {
|
||||
font-size: 12px;
|
||||
color: #c0392b;
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.fault-reasons-box ul {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
list-style-type: none; /* Remove default bullets */
|
||||
}
|
||||
/* Custom "beautiful" bullet points */
|
||||
.fault-reasons-box li {
|
||||
margin-bottom: 4px;
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
}
|
||||
.fault-reasons-box li:before {
|
||||
content: '»'; /* Using a character for better PDF compatibility */
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0px;
|
||||
color: #c0392b;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Yellow box for other annotations */
|
||||
.fault-other-box {
|
||||
background-color: #fef9e7;
|
||||
padding: 10px;
|
||||
/* Enhanced border for better printing */
|
||||
border: 1.5pt solid #e5b200;
|
||||
border-left: 3pt solid #f7c423;
|
||||
border-radius: 4px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.no-faults { text-align: center; font-size: 14px; color: #777; padding: 40px; border: 2px dashed #ccc; border-radius: 8px; }
|
||||
a { color: #005384; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
@@ -47,8 +98,8 @@
|
||||
<h2><?= $fullAddress ?></h2>
|
||||
<table class="info-table">
|
||||
<tr>
|
||||
<td class="label">AddressDB ID:</td>
|
||||
<td><?= $addr['hausnummer_id'] ?> (<a href="<?= $entry['addressDbLink'] ?>" target="_blank">Ansehen</a>)</td>
|
||||
<td class="label">TheTool ID:</td>
|
||||
<td><?= $addr['hausnummer_id'] ?> (<a href="<?= $entry['addressDbLink'] ?>" target="_blank">TheTool Link</a>)</td>
|
||||
<td class="label">RIMO Type:</td>
|
||||
<td><?= htmlspecialchars($addr['rimo_type'] ?: 'N/A') ?></td>
|
||||
</tr>
|
||||
@@ -62,30 +113,43 @@
|
||||
<td class="label">Wohneinheiten:</td>
|
||||
<td><?= $addr['wohneinheit_count'] ?></td>
|
||||
<td class="label">Koordinaten:</td>
|
||||
<td><?= $addr['gps_lat'] ?>, <?= $addr['gps_long'] ?> (<a href="<?= $entry['googleMapsLink'] ?>" target="_blank">Karte</a>)</td>
|
||||
<td><?= number_format((float)$addr['gps_lat'], 8) ?>, <?= number_format((float)$addr['gps_long'], 8) ?> (<a href="<?= $entry['googleMapsLink'] ?>" target="_blank">Karte</a>)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="faults-section">
|
||||
<h3>Gemeldete Fehler</h3>
|
||||
<?php if (empty($entry['faults']['reasons']) && empty(trim($entry['faults']['other']))): ?>
|
||||
<p>Keine spezifischen Fehlerdetails angegeben.</p>
|
||||
<?php else: ?>
|
||||
<?php if (!empty($entry['faults']['reasons'])): ?>
|
||||
<ul>
|
||||
<?php foreach ($entry['faults']['reasons'] as $reason): ?>
|
||||
<li><?= htmlspecialchars($reason) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty(trim($entry['faults']['other']))): ?>
|
||||
<div class="other-text">
|
||||
<strong>Sonstige Anmerkungen:</strong><br>
|
||||
<?= nl2br($entry['faults']['other']) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
$hasReasons = !empty($entry['faults']['reasons']);
|
||||
$hasOther = !empty(trim($entry['faults']['other']));
|
||||
?>
|
||||
|
||||
<?php if ($hasReasons || $hasOther): ?>
|
||||
<table class="faults-layout-table">
|
||||
<tr>
|
||||
<td>
|
||||
<?php if ($hasReasons): ?>
|
||||
<div class="fault-reasons-box">
|
||||
<h3>Gemeldete Fehler</h3>
|
||||
<ul>
|
||||
<?php foreach ($entry['faults']['reasons'] as $reason): ?>
|
||||
<li><?= htmlspecialchars($reason) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($hasOther): ?>
|
||||
<div class="fault-other-box">
|
||||
<strong>Sonstige Anmerkungen:</strong><br>
|
||||
<?= nl2br(htmlspecialchars($entry['faults']['other'])) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<p>Keine spezifischen Fehlerdetails angegeben.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -94,9 +94,9 @@
|
||||
}
|
||||
|
||||
.tooltip-content-wrapper.marker-label-saturated {
|
||||
background-color: rgba(212, 237, 218, 0.9);
|
||||
border-color: #81c784;
|
||||
color: #155724;
|
||||
background-color: #28a745; /* A solid, vibrant green */
|
||||
border-color: #218838; /* A slightly darker border for definition */
|
||||
color: white; /* White text for maximum contrast */
|
||||
}
|
||||
|
||||
div.leaflet-marker-icon.custom-div-icon {
|
||||
|
||||
@@ -89,9 +89,12 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
},
|
||||
watch: {
|
||||
selectedCampaign(newCampaignId) {
|
||||
const localStorageKey = 'rimoMapSelectedCampaign';
|
||||
if (newCampaignId) {
|
||||
localStorage.setItem(localStorageKey, newCampaignId);
|
||||
this.fetchAllMapData();
|
||||
} else {
|
||||
localStorage.removeItem(localStorageKey);
|
||||
this.mapMarkers = [];
|
||||
this.fcpMarkers = [];
|
||||
this.faults = {};
|
||||
@@ -103,9 +106,20 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
this.allCampaigns = window.TT_CONFIG?.ALL_CAMPAIGNS || [];
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const campaignIdParam = urlParams.get('preordercampaign_id');
|
||||
const localStorageKey = 'rimoMapSelectedCampaign';
|
||||
|
||||
if (this.allCampaigns.length === 1) this.selectedCampaign = this.allCampaigns[0].id;
|
||||
if (this.allCampaigns.length > 1 && campaignIdParam && this.allCampaigns.some(c => String(c.id) === campaignIdParam)) this.selectedCampaign = campaignIdParam;
|
||||
if (campaignIdParam && this.allCampaigns.some(c => String(c.id) === campaignIdParam)) {
|
||||
// URL parameter has priority and will be saved by the watcher
|
||||
this.selectedCampaign = campaignIdParam;
|
||||
} else {
|
||||
const savedCampaignId = localStorage.getItem(localStorageKey);
|
||||
if (savedCampaignId && this.allCampaigns.some(c => String(c.id) === savedCampaignId)) {
|
||||
this.selectedCampaign = savedCampaignId;
|
||||
} else if (this.allCampaigns.length === 1) {
|
||||
// Fallback for first time or if saved campaign is invalid
|
||||
this.selectedCampaign = this.allCampaigns[0].id;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (window.TT_CONFIG?.ALL_USERS) {
|
||||
@@ -402,20 +416,48 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
}
|
||||
}
|
||||
},
|
||||
async saveFaults() {
|
||||
if (!this.editingFault) return;
|
||||
const { hausnummerId, data } = this.editingFault;
|
||||
async saveFaults(hausnummerIdToUpdate) {
|
||||
const hausnummerId = hausnummerIdToUpdate || this.editingFault?.hausnummerId;
|
||||
if (!hausnummerId) {
|
||||
if (this.editingFault) this.editingFault = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.$set(this.faults, hausnummerId, data);
|
||||
if (this.editingFault && this.editingFault.hausnummerId === hausnummerId) {
|
||||
this.$set(this.faults, hausnummerId, this.editingFault.data);
|
||||
}
|
||||
|
||||
const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/Preorder/RimoTypeMapSaveFaults`, {
|
||||
campaignId: this.selectedCampaign,
|
||||
faults: this.faults
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
window.notify('success', 'Fehlerbericht gespeichert.');
|
||||
this.$refs.ttMap?.map.closePopup();
|
||||
this.mapMarkers = this.processData(this.rawRimoData);
|
||||
|
||||
const mapComponent = this.$refs.ttMap;
|
||||
if (mapComponent && mapComponent.markerLayer) {
|
||||
mapComponent.markerLayer.eachLayer(marker => {
|
||||
if (marker.tt_hausnummerId == hausnummerId) {
|
||||
const rimoItem = this.rawRimoData.find(item => item.hausnummer_id == hausnummerId);
|
||||
if (rimoItem) {
|
||||
const rimoType = this.getNormalizedRimoType(rimoItem.rimo_type);
|
||||
const fault = this.faults[hausnummerId];
|
||||
const hasFault = fault && !fault.done;
|
||||
const markerIconDef = this.getMarkerIcon(rimoType);
|
||||
|
||||
const newIcon = L.divIcon({
|
||||
className: `custom-div-icon marker-${rimoType} ${hasFault ? 'marker-has-fault' : ''}`,
|
||||
html: `<div class="rimo-marker ${markerIconDef.class}"><i class="${markerIconDef.icon} rimo-icon"></i></div>`,
|
||||
iconSize: [30, 30],
|
||||
iconAnchor: [15, 30],
|
||||
});
|
||||
marker.setIcon(newIcon);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
window.notify('error', 'Fehlerbericht konnte nicht gespeichert werden.');
|
||||
}
|
||||
@@ -431,7 +473,7 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
done_at: new Date().toISOString()
|
||||
});
|
||||
|
||||
await this.saveFaults();
|
||||
await this.saveFaults(hausnummerId);
|
||||
},
|
||||
zoomToFaultMarker(hausnummerId) {
|
||||
const map = this.$refs.ttMap?.map;
|
||||
@@ -494,7 +536,7 @@ Vue.component('PreorderRimoTypeMap', {
|
||||
style="min-width: 300px;"
|
||||
></tt-select>
|
||||
</div>
|
||||
<div class="map-filter-container" v-if="selectedCampaign">
|
||||
<div class="map-filter-container" style="margin-top: 8px" v-if="selectedCampaign">
|
||||
<h6 class="mr-2 font-weight-bold align-self-center">Filter:</h6>
|
||||
<button v-for="filter in filterOptions"
|
||||
:key="filter.value"
|
||||
|
||||
Reference in New Issue
Block a user