Files
gps-frontend/resources/views/menu_v1/reports/_trip_detail.blade.php
Pringgosutono 0fe1cac8bf timefix
2025-09-18 13:41:30 +07:00

329 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<style>
#map {
height: 100%;
margin: 0;
}
.my-leaflet-map-container img {
max-height: none;
}
.dtl-text{
font-size: 11px;
}
.head-text{
font-size: 12px !important;
}
/* .leaflet-overlay-pane svg {
transform: none !important;
} */
.leaflet-routing-container {
display: none !important;
}
#viewPdf {
display: flex;
justify-content: center;
width: 794px;
/* height: auto; */
max-width: 100%; /* Ensures it is responsive */
}
/* .modal-dialog{
width: 794px;
} */
</style>
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mdlDetailTripLabel">{{$nopol1}} Trip Detail</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row head-text" id="viewPdf">
<div class="col-12">
<h4>{{$nopol1}}</h4>
</div>
<div class="col-4">
<p class="text-bold mb-0">Start</p>
<p class="mb-0 time">{{ $start['time'] }}</p>
<p class="mb-0">Vehicle Mileage: {{number_format($start['mileage'], 2)}} km</p>
<p>{{$start['fulladdress']}}</p>
</div>
<div class="col-4">
<p class="text-bold mb-0">Finish</p>
<p class="mb-0 time">{{ $finish['time'] }}</p>
<p class="mb-0">Vehicle Mileage: {{number_format($finish['mileage'], 2)}} km</p>
<p>{{$finish['fulladdress']}}</p>
</div>
<div class="col-2">
<p class="text-bold mb-0">Distance</p>
<p class="mb-0">{{number_format($distance, 2)}} km</p>
</div>
<div class="col-2">
<p class="text-bold mb-0">Duration</p>
<p class="mb-0">{{$duration}}</p>
</div>
<div class="col-12">
<div id="leafMap" style="height: 400px;"></div>
</div>
<div class="col-12">
<!-- <li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Time: 25 Aug 2025 07:31:08</p>
<p class="text-muted mb-0 dtl-text">-8.55387 - 125.542409</p>
<p class="text-muted mb-0 dtl-text">Avenida Luro Mata, Praia dos Coqueiros, Bebunuk, Dom Aleixo, Dili, Timor-Leste;2066973</p>
<p class="mb-0 dtl-text">Current speed: 7km/h</p>
</li> -->
@foreach ($list as $item)
<!-- <li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Time: {{date('d-m-Y H:i:s', $item->crt_d)}}</p>
<p class="text-muted mb-0 dtl-text">Vehicle Mileage: {{number_format($item->vhc_milleage, 2)}} km</p>
<p class="text-muted mb-0 dtl-text">{{number_format($item->latitude, 6)}} - {{number_format($item->longitude, 6)}}</p>
<p class="text-muted mb-0 dtl-text">{{urldecode($item->fulladdress)}}</p>
<p class="text-muted mb-0 dtl-text">Current speed: {{number_format($item->speed, 2)}} km/h</p>
</li> -->
<li class="list-group-item p-1 px-2">
<div class="row">
<div class="col-4">
<p class="text-bold mb-0 dtl-text">Time: <span class="time">{{ $item->crt_d }}</span></p>
<p class="text-muted mb-0 dtl-text">Vehicle Mileage: {{number_format($item->vhc_milleage, 2)}} km</p>
<p class="text-muted mb-0 dtl-text">Current speed: {{$item->speed}} km/h</p>
</div>
<div class="col-8">
<p class="text-muted mb-0 dtl-text">{{number_format($item->latitude, 6)}}, {{number_format($item->longitude, 6)}}</p>
<p class="text-muted mb-0 dtl-text">{{urldecode($item->fulladdress)}}</p>
</div>
</div>
</li>
@endforeach
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-danger ms-auto" id="btnDownloadReport">Download Report</button>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('.time').each(function () {
const unix = parseInt($(this).text().trim());
$(this).text(moment.unix(unix).format('DD MMM YYYY HH:mm:ss'));
});
let coords
setTimeout(async() => {
map.invalidateSize(); // force Leaflet to recalc
map.fitBounds(polyline.getBounds());
// map.fitBounds(await coords.map(c => L.latLng(c[0], c[1])));
}, 200);
const linesData = (@json($list));
// 1) Initialize map
const map = L.map("leafMap").setView([-8.90507, 125.9945732], 10)
// 2) Add tile layer
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20,
crossOrigin: true
}).addTo(map);
// // // 3) Coordinates (Lat, Lng) for polyline
const points = linesData
.filter(p => p.latitude && p.longitude)
.map((point) => [point.latitude, point.longitude])
// 4) Add polyline
const polyline = L.polyline(points,{
color: 'red',
weight: 3,
opacity: 0.7,
smoothFactor: 1
})
// .addTo(map);
// const lines = L.Routing.control({
// waypoints: points,
// // router: L.Routing.osrmv1(),
// router: L.Routing.osrmv1({
// serviceUrl: "https://brilianapps.britimorleste.tl:5001/route/v1",
// }),
// show: false,
// itinerary: null, // 👈 completely removes the panel
// addWaypoints: false, // ❌ prevent adding points by clicking
// draggableWaypoints: false, // ❌ prevent dragging markers
// routeWhileDragging: false, // optional: dont reroute while dragging
// createMarker: () => null,
// routingOptions: {
// radiuses: [100, 100] // tolerance in meters per waypoint
// },
// lineOptions:{
// styles: [{ color: "#C0392B", weight: 4, opacity: 0.7 }],
// },
// }).addTo(map)
function fetchOsrm(points) {
// balik koordinat: [lat, lon] -> [lon, lat]
const coords = points
// hints: N-1 semicolon
const hints = ";".repeat(points.length - 1);
const body = {
coordinates: coords,
overview: "false",
alternatives: "false",
steps: "true",
hints: hints
};
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://brilianapps.britimorleste.tl/osrm-backend/post-route/v1/driving/',
headers: {
'Content-Type': 'application/json'
},
data: body
};
return axios.request(config)
.then((response) => {
// console.log(JSON.stringify(response.data));
return response.data; // supaya bisa dipakai di luar
})
.catch((error) => {
console.error("Error:", err.message);
return null;
});
}
function decodeOSRMGeometry(encoded) {
const coordinates = [];
let index = 0,
lat = 0,
lng = 0;
while (index < encoded.length) {
let result = 1,
shift = 0,
b;
do {
b = encoded.charCodeAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lat += (result & 1 ? ~(result >> 1) : result >> 1);
result = 1;
shift = 0;
do {
b = encoded.charCodeAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lng += (result & 1 ? ~(result >> 1) : result >> 1);
coordinates.push([lat / 1e5, lng / 1e5]);
}
return coordinates;
}
fetchOsrm(points).then(osrm => {
if (!osrm) return console.log("OSRM gagal");
coords = osrm.routes[0].legs.flatMap(leg =>
leg.steps.flatMap(step =>
decodeOSRMGeometry(step.geometry)
)
);
L.polyline(coords, {
color: "#2980B9",
weight: 3,
opacity: 0.8
}).addTo(map);
// map.fitBounds(coords.map(c => L.latLng(c[0], c[1])));
});
// start and finish point
const startIcon = L.icon({
iconUrl: "{{ asset('images/start.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
})
L.marker(points[0], {icon: startIcon}).addTo(map)
const finishIcon = L.icon({
iconUrl: "{{ asset('images/finish.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
})
L.marker(points[points.length - 1], {icon: finishIcon}).addTo(map)
// // 5) Auto-fit map to polyline bounds
// map.fitBounds(polyline.getBounds())
// download pdf
window._downloadReportBound ||= (
$(document).on('click', '#btnDownloadReport', function () {
$('#viewPdf').printThis({
debug: false, // show the iframe for debugging
importCSS: true, // copy linked styles
importStyle: true, // copy inline styles
});
// const viewPdf = document.getElementById("viewPdf");
// // find overlay svg (the one holding polylines)
// const overlaySvg = document.querySelector('.leaflet-overlay-pane svg');
// let originalTransform = '';
// if (overlaySvg) {
// originalTransform = overlaySvg.style.transform;
// overlaySvg.style.transform = 'none';
// }
// html2canvas(viewPdf, {
// scale: 2,
// useCORS: true,
// logging: true
// }).then(canvas => {
// const imgData = canvas.toDataURL('image/png');
// const { jsPDF } = window.jspdf;
// const pdf = new jsPDF('p', 'mm', 'a4');
// const pageWidth = pdf.internal.pageSize.getWidth();
// const pageHeight = pdf.internal.pageSize.getHeight();
// const imgWidth = pageWidth - 20; // margin
// const imgHeight = canvas.height * imgWidth / canvas.width;
// let position = 10;
// // 👉 Handle multipage content
// let heightLeft = imgHeight;
// while (heightLeft > 0) {
// pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
// heightLeft -= pageHeight;
// if (heightLeft > 0) {
// pdf.addPage();
// position = 0;
// }
// }
// pdf.save(`{{$nopol1}} Trip Report {{$start['time']}}.pdf`);
// });
}),
true
);
});
</script>