update feature
This commit is contained in:
34
app/Http/Controllers/ReportsController.php
Normal file
34
app/Http/Controllers/ReportsController.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Validator;
|
||||
use Auth;
|
||||
use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\Devices;
|
||||
use App\Models\VehiclesDetail;
|
||||
use App\Models\Users;
|
||||
|
||||
class ReportsController extends Controller
|
||||
{
|
||||
public function view_report_vehicle_trips(Request $req)
|
||||
{
|
||||
$data = [
|
||||
// 'lanes' => ConfRates::getLanesActive(),
|
||||
// 'provs' => Region::listProv(),
|
||||
// 'vendors' => Users::getUsersActiveByRole(Users::ROLE_VENDOR),
|
||||
// 'truck_types' => ConfTruckTypes::listTruckTypes(ConfTruckTypes::IS_ACTIVE),
|
||||
];
|
||||
|
||||
return view('menu_v1.reports.vehicle_trips', $data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -143,8 +143,8 @@ class TrackController extends Controller
|
||||
$filter["start_date"] = $req->start_date;
|
||||
$filter["end_date"] = $req->end_date;
|
||||
|
||||
$filter["start_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->start_date));
|
||||
$filter["end_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->end_date));
|
||||
// $filter["start_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->start_date));
|
||||
// $filter["end_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->end_date));
|
||||
|
||||
$filter["limit"] = 100000;
|
||||
} else {
|
||||
|
||||
@ -436,85 +436,88 @@ class Tracks extends Model
|
||||
$query .= " GROUP BY v.id ORDER BY tr.crt_d DESC LIMIT 500";
|
||||
|
||||
$list = DB::select($query, $params);
|
||||
|
||||
// dd($list);
|
||||
// Post-processing per row
|
||||
foreach ($list as $_list) {
|
||||
$_list->vhc_sum_milleage =
|
||||
optional(
|
||||
DB::select(
|
||||
"SELECT SUM(pre_milleage) as vhc_sum_milleage FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE vhc_id = ?",
|
||||
[$_list->vid]
|
||||
)
|
||||
)[0]->vhc_sum_milleage ?? "";
|
||||
// foreach ($list as $_list) {
|
||||
// $_list->vhc_sum_milleage =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT SUM(pre_milleage) as vhc_sum_milleage FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE vhc_id = ?",
|
||||
// [$_list->vid]
|
||||
// )
|
||||
// )[0]->vhc_sum_milleage ?? "";
|
||||
|
||||
$_list->lst_idle_at =
|
||||
optional(
|
||||
DB::select(
|
||||
"SELECT crt_s FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE stts_engine = ? AND vhc_id = ? AND crt_s >= (
|
||||
SELECT crt_s FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE stts_engine IN (?, ?) AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
) ORDER BY id ASC LIMIT 1",
|
||||
[
|
||||
self::STTS_EN_IDLING,
|
||||
$_list->vid,
|
||||
self::STTS_EN_STOPING,
|
||||
self::STTS_EN_MOVING,
|
||||
$_list->vid,
|
||||
$_list->lst_loc_crt_s,
|
||||
]
|
||||
)
|
||||
)[0]->crt_s ?? "";
|
||||
// $_list->lst_idle_at =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine = ? AND vhc_id = ? AND crt_s >= (
|
||||
// SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine IN (?, ?) AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1",
|
||||
// [
|
||||
// self::STTS_EN_IDLING,
|
||||
// $_list->vid,
|
||||
// self::STTS_EN_STOPING,
|
||||
// self::STTS_EN_MOVING,
|
||||
// $_list->vid,
|
||||
// $_list->lst_loc_crt_s,
|
||||
// ]
|
||||
// )
|
||||
// )[0]->crt_s ?? "";
|
||||
|
||||
$_list->lst_stop_at =
|
||||
optional(
|
||||
DB::select(
|
||||
"SELECT crt_s FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE stts_engine = ? AND vhc_id = ? AND crt_s >= (
|
||||
SELECT crt_s FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE stts_engine IN (?, ?) AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
) ORDER BY id ASC LIMIT 1",
|
||||
[
|
||||
self::STTS_EN_STOPING,
|
||||
$_list->vid,
|
||||
self::STTS_EN_IDLING,
|
||||
self::STTS_EN_MOVING,
|
||||
$_list->vid,
|
||||
$_list->lst_loc_crt_s,
|
||||
]
|
||||
)
|
||||
)[0]->crt_s ?? "";
|
||||
// $_list->lst_stop_at =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine = ? AND vhc_id = ? AND crt_s >= (
|
||||
// SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine IN (?, ?) AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1",
|
||||
// [
|
||||
// self::STTS_EN_STOPING,
|
||||
// $_list->vid,
|
||||
// self::STTS_EN_IDLING,
|
||||
// self::STTS_EN_MOVING,
|
||||
// $_list->vid,
|
||||
// $_list->lst_loc_crt_s,
|
||||
// ]
|
||||
// )
|
||||
// )[0]->crt_s ?? "";
|
||||
|
||||
$_list->lst_heartbeat =
|
||||
optional(
|
||||
DB::select(
|
||||
"SELECT COUNT(id) as lst_heartbeat FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE vhc_id = ? AND action = 'heartbeat' AND crt BETWEEN ? AND ? LIMIT 1",
|
||||
[$_list->vid, $now - 600, $now]
|
||||
)
|
||||
)[0]->lst_heartbeat ?? "";
|
||||
}
|
||||
// $_list->lst_heartbeat =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT COUNT(id) as lst_heartbeat FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE vhc_id = ? AND action = 'heartbeat' AND crt BETWEEN ? AND ? LIMIT 1",
|
||||
// [$_list->vid, $now - 600, $now]
|
||||
// )
|
||||
// )[0]->lst_heartbeat ?? "";
|
||||
// }
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function lastMoveTracks($vid, $filter = [])
|
||||
{
|
||||
// dd($vid, $filter);
|
||||
$now = time();
|
||||
$params = [];
|
||||
$query = "SELECT";
|
||||
$query .= " v.id as vid,v.device_id,v.nopol1,v.nopol2,v.nopol3";
|
||||
$query .= " ,tr.id as master_id,tr.latitude,tr.longitude,tr.speed,tr.orientation";
|
||||
// ,(tr.crt + ( 7 * 3600 )) AS lst_loc_crt
|
||||
// ,(tr.crt_d + ( 7 * 3600 )) AS lst_loc_crt_d
|
||||
$query .= "
|
||||
,(tr.crt + ( 7 * 3600 )) AS lst_loc_crt
|
||||
,(tr.crt_d + ( 7 * 3600 )) AS lst_loc_crt_d
|
||||
,tr.crt AS lst_loc_crt
|
||||
,tr.crt_d AS lst_loc_crt_d
|
||||
,tr.crt_s AS lst_loc_crt_s";
|
||||
$query .= " ,tr.ignition,tr.stts_engine";
|
||||
$query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1";
|
||||
@ -563,61 +566,88 @@ class Tracks extends Model
|
||||
$query .= " ;";
|
||||
$rawTracks = DB::select($query, $params);
|
||||
$rawTracks = collect($rawTracks);
|
||||
// dd($rawTracks->toJson(JSON_PRETTY_PRINT));
|
||||
// dd($rawTracks);
|
||||
|
||||
$filtered = collect();
|
||||
$zeroBlock = collect();
|
||||
$tempBlock = collect();
|
||||
// // filter
|
||||
// $filtered = collect();
|
||||
// $zeroBlock = collect();
|
||||
// $tempBlock = collect();
|
||||
|
||||
$lastIndex = $rawTracks->count() - 1;
|
||||
// $lastIndex = $rawTracks->count() - 1;
|
||||
|
||||
foreach ($rawTracks as $i => $track) {
|
||||
$isZero = $track->speed == 0;
|
||||
// foreach ($rawTracks as $i => $track) {
|
||||
// $isZero = $track->speed == 0;
|
||||
|
||||
if ($i === $lastIndex) {
|
||||
if ($isZero) {
|
||||
$zeroBlock->push($track);
|
||||
// if ($i === $lastIndex) {
|
||||
// if ($isZero) {
|
||||
// $zeroBlock->push($track);
|
||||
// } else {
|
||||
// if ($zeroBlock->isNotEmpty()) {
|
||||
// $tempBlock = $zeroBlock;
|
||||
// $tempBlock->push($track);
|
||||
|
||||
// $zerosOnly = $tempBlock->filter(fn($t) => $t->speed == 0);
|
||||
|
||||
// if ($zerosOnly->count() === 1) {
|
||||
// $filtered->push($zerosOnly->first());
|
||||
// } elseif ($zerosOnly->count() > 1) {
|
||||
// $filtered->push($zerosOnly->first());
|
||||
// $filtered->push($zerosOnly->last());
|
||||
// }
|
||||
// } else {
|
||||
// $filtered->push($track);
|
||||
// }
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
// //
|
||||
// if ($isZero) {
|
||||
// $zeroBlock->push($track);
|
||||
// } else {
|
||||
// if ($zeroBlock->isNotEmpty()) {
|
||||
// $filtered->push($zeroBlock->first());
|
||||
// $zeroBlock = collect();
|
||||
// }
|
||||
// $filtered->push($track);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if ($zeroBlock->isNotEmpty() && $rawTracks->last()->speed == 0) {
|
||||
// if ($zeroBlock->count() === 1) {
|
||||
// $filtered->push($zeroBlock->first());
|
||||
// } else {
|
||||
// $filtered->push($zeroBlock->first());
|
||||
// $filtered->push($zeroBlock->last());
|
||||
// }
|
||||
// }
|
||||
|
||||
// grouping by trip
|
||||
$groupTrip = [];
|
||||
$temp = [];
|
||||
|
||||
// loop from top to bottom
|
||||
foreach ($rawTracks as $item) {
|
||||
if ($item->ignition == 4) {
|
||||
// collect data when ignition is 4
|
||||
$temp[] = $item;
|
||||
} else {
|
||||
if ($zeroBlock->isNotEmpty()) {
|
||||
$tempBlock = $zeroBlock;
|
||||
$tempBlock->push($track);
|
||||
// if ignition != 4, save group if exists then reset
|
||||
if (!empty($temp)) {
|
||||
$groupTrip[] = $temp;
|
||||
$temp = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
// add last collected group if any
|
||||
if (!empty($temp)) {
|
||||
$groupTrip[] = $temp;
|
||||
}
|
||||
// dd($groupTrip);
|
||||
|
||||
$zerosOnly = $tempBlock->filter(fn($t) => $t->speed == 0);
|
||||
|
||||
if ($zerosOnly->count() === 1) {
|
||||
$filtered->push($zerosOnly->first());
|
||||
} elseif ($zerosOnly->count() > 1) {
|
||||
$filtered->push($zerosOnly->first());
|
||||
$filtered->push($zerosOnly->last());
|
||||
}
|
||||
} else {
|
||||
$filtered->push($track);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isZero) {
|
||||
$zeroBlock->push($track);
|
||||
} else {
|
||||
if ($zeroBlock->isNotEmpty()) {
|
||||
$filtered->push($zeroBlock->first());
|
||||
$zeroBlock = collect();
|
||||
}
|
||||
$filtered->push($track);
|
||||
}
|
||||
}
|
||||
|
||||
if ($zeroBlock->isNotEmpty() && $rawTracks->last()->speed == 0) {
|
||||
if ($zeroBlock->count() === 1) {
|
||||
$filtered->push($zeroBlock->first());
|
||||
} else {
|
||||
$filtered->push($zeroBlock->first());
|
||||
$filtered->push($zeroBlock->last());
|
||||
}
|
||||
}
|
||||
|
||||
// return $filtered->take(500);
|
||||
return $filtered;
|
||||
return $groupTrip;
|
||||
}
|
||||
|
||||
public static function nearestInCircle($lat, $lng, $rad, $filter = [])
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
<link href="{{ asset('assets/vendor/DataTables/datatables.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/css/bootstrap-datepicker.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/css/meus.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css" integrity="sha512-f0tzWhCwVFS3WeYaofoLWkTP62ObhewQ1EZn65oSYDZUg1+CyywGKkWzm8BxaJj5HGKI72PnMH9jYyIFz+GH7g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<style>
|
||||
.landscape-photo {
|
||||
max-height: max(21vh, 210px);
|
||||
@ -75,6 +76,8 @@
|
||||
<script src="{{ asset('assets/js/moment.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/bootstrap-datepicker.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/helper.js') }}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js" integrity="sha512-AIOTidJAcHBH2G/oZv9viEGXRqDNmfdPVPYOYKGy3fti0xIplnlgMHUGfuNRzC6FkzIo0iIxgFnr9RikFxK+sw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
|
||||
<script>
|
||||
const AppState = {
|
||||
user_role: {
|
||||
|
||||
@ -21,6 +21,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.leaflet-routing-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#openLeftSideBar1Mobile {
|
||||
display: none;
|
||||
}
|
||||
@ -402,11 +406,11 @@
|
||||
<div>
|
||||
<div class="mb-2">
|
||||
<label class="text-muted">From</label>
|
||||
<input class="form-control" type="date" id="historyStartDate">
|
||||
<input class="form-control" id="historyStartDate">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="text-muted">To</label>
|
||||
<input class="form-control" type="date" id="historyEndDate">
|
||||
<input class="form-control" id="historyEndDate">
|
||||
</div>
|
||||
</div>
|
||||
<div id="infoMove-plots" class="infoMove-plots">
|
||||
@ -519,9 +523,11 @@
|
||||
<script src="{{ asset('assets/vendor/leaflet-1.7.1/leaflet-src.js') }}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js" integrity="sha512-ozq8xQKq6urvuU6jNgkfqAmT7jKN2XumbrX1JiB3TnF7tI48DPI4Gy1GXKD/V3EExgAs1V+pRO7vwtS1LHg0Gw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/leaflet-rotatedmarker@0.2.0/leaflet.rotatedMarker.min.js"></script>
|
||||
{{-- <script src="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.js"></script> --}}
|
||||
<script src="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.js"></script>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
const State = {
|
||||
isDrawPolygon: 0,
|
||||
timingRouteAnimation: 100,
|
||||
@ -737,6 +743,13 @@
|
||||
$('#rightSideBar1').addClass('d-none');
|
||||
$('#openRightSideBar1').removeClass('d-none');
|
||||
}
|
||||
|
||||
$('#historyStartDate, #historyEndDate').datetimepicker({
|
||||
format:'d-m-Y H:i',
|
||||
defaultTime:'00:00',
|
||||
closeOnDateSelect: true,
|
||||
// mask:true
|
||||
});
|
||||
},
|
||||
calcIdlingDur: function(lst_idle_unix, lst_speed) {
|
||||
let now = moment();
|
||||
@ -760,19 +773,19 @@
|
||||
};
|
||||
},
|
||||
calcPeriodeDate: function(startDate, endDate) {
|
||||
if (startDate.format('YYYY-MM-DD') === 'Invalid date') {
|
||||
if (startDate.format('YYYY-MM-DD HH:mm') === 'Invalid date') {
|
||||
Helper.toast('Warning', 'just now', 'Start date of the period is not valid');
|
||||
return {
|
||||
isValid: false
|
||||
};
|
||||
}
|
||||
if (endDate.format('YYYY-MM-DD') === 'Invalid date') {
|
||||
if (endDate.format('YYYY-MM-DD HH:mm') === 'Invalid date') {
|
||||
Helper.toast('Warning', 'just now', 'End date of the period is not valid');
|
||||
return {
|
||||
isValid: false
|
||||
};
|
||||
}
|
||||
endDate.add(23, 'hour').add(59, 'minutes').add(59, 'seconds');
|
||||
// endDate.add(23, 'hour').add(59, 'minutes').add(59, 'seconds');
|
||||
const duration = moment.duration(endDate.diff(startDate));
|
||||
const diffDays = duration.days();
|
||||
if (diffDays > 30) {
|
||||
@ -814,7 +827,7 @@
|
||||
// Leaflet.map = L.map('map').setView([-7.1451449, 109.9776078], 8); // centering javanese province
|
||||
// Leaflet.map = L.map('map').setView([-7.8241413, 112.9071746], 9); // centering east java province
|
||||
// Leaflet.map = L.map('map').setView([-6.2106272, 106.8477106], 9); // centering east java province
|
||||
Leaflet.map = L.map('map').setView([-8.90507, 125.9945732], 10); // centering east java province
|
||||
Leaflet.map = L.map('map').setView([-8.90507, 125.9945732], 10); // centering timor leste
|
||||
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
|
||||
attribution: 'Map data © <a href="https://www.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
// maxZoom: 20,
|
||||
@ -887,6 +900,11 @@
|
||||
if (locs.constructor === Array) {
|
||||
let circles = [];
|
||||
for (let i = 0; i < locs.length; i++) {
|
||||
// invisible circle
|
||||
if(locs[i].options?.markerOpacity == 0){
|
||||
locs[i].options.opacity = 0
|
||||
locs[i].options.fill = false
|
||||
}
|
||||
let circle = L.circle([locs[i].lat, locs[i].lng], locs[i]?.options);
|
||||
circle.bindPopup(locs[i]?.label || '');
|
||||
circle.bindTooltip(locs[i]?.label || '');
|
||||
@ -914,6 +932,31 @@
|
||||
if (cb) cb(polyline);
|
||||
return polyline;
|
||||
},
|
||||
addRoutes: function(locs = [], cb = null) {
|
||||
let latLngs = [];
|
||||
for (let i = 0; i < locs.length; i++) {
|
||||
latLngs.push([locs[i].lat, locs[i].lng]);
|
||||
}
|
||||
let routes = L.Routing.control({
|
||||
waypoints: latLngs.reverse(), // reverse to make first point as start
|
||||
// router: L.Routing.osrmv1(),
|
||||
router: L.Routing.osrmv1({
|
||||
serviceUrl: "https://brilianapps.britimorleste.tl/osrm-backend/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: don’t reroute while dragging
|
||||
createMarker: () => null,
|
||||
lineOptions:{
|
||||
styles: [{ color: locs[0]?.options?.color, weight: 5, opacity: 0.7 }],
|
||||
},
|
||||
}).addTo(Leaflet.map)
|
||||
|
||||
if (cb) cb(routes);
|
||||
return routes;
|
||||
},
|
||||
// start custom polylines
|
||||
addCustomPolylines: function(locs = [], cb = null) {
|
||||
const radius = 0.5 /* corner smooth radius, keep value in range 0 - 0.5 to avoid artifacts */
|
||||
@ -1077,6 +1120,7 @@
|
||||
if (cb) cb();
|
||||
}
|
||||
} else if (type == 'eventRemoveRouteStartEnd') {
|
||||
// console.log('clear route eventRemoveRouteStartEnd');
|
||||
if (State.eventRemoveRouteStartEnd) {
|
||||
window.dispatchEvent(State.eventRemoveRouteStartEnd);
|
||||
if (cb) cb();
|
||||
@ -1251,7 +1295,7 @@
|
||||
$('#infoMovement').addClass('d-none');
|
||||
} else if (type == State.stts_filterDetail.lastMove) { // last movement
|
||||
$('#infoVehicles').addClass('d-none');
|
||||
$('#infoDriver').addClass('d-none');
|
||||
// $('#infoDriver').addClass('d-none');
|
||||
$('#infoJob').addClass('d-none');
|
||||
$('#infoMovement').removeClass('d-none');
|
||||
$('#infoMovement').addClass('d-block');
|
||||
@ -1353,7 +1397,11 @@
|
||||
eventListMovement: function() {
|
||||
$('#infoMove-plots').on('click', '.plotMove-item', function(e) {
|
||||
let tr = JSON.parse(decodeURIComponent(window.atob($(e.target).closest('.plotMove-item').data('obj'))));
|
||||
// console.log("tr", tr);
|
||||
|
||||
let arrIdx = Helper.getIndexReversedSequence(tr.key_index - 1, Trucks.last_move.length - 1);
|
||||
// console.log("arrIdx", arrIdx);
|
||||
|
||||
PgBar.setCrntVal(arrIdx);
|
||||
Menu.createMarkerDetailPlotMovement(tr);
|
||||
})
|
||||
@ -1457,35 +1505,49 @@
|
||||
});
|
||||
},
|
||||
eventFilterHistoryDate: function() {
|
||||
$('#historyStartDate').on('change', function(e) {
|
||||
$('#historyStartDate, #historyEndDate').on('change', function(e) {
|
||||
const date0 = moment($('#historyStartDate').val(), "DD-MM-YYYY HH:mm")
|
||||
const date1 = moment($('#historyEndDate').val(), "DD-MM-YYYY HH:mm")
|
||||
const {
|
||||
isValid,
|
||||
data
|
||||
} = Wrapper.calcPeriodeDate(moment($('#historyStartDate').val()), moment($('#historyEndDate').val()))
|
||||
} = Wrapper.calcPeriodeDate(
|
||||
date0,
|
||||
date1
|
||||
)
|
||||
if (!isValid) return false;
|
||||
State.historyStartDate = data.startDate.unix();
|
||||
State.historyEndDate = data.endDate.unix();
|
||||
// console.log("isValid", isValid, data);
|
||||
|
||||
State.historyStartDate = date0.unix();
|
||||
State.historyEndDate = date1.unix();
|
||||
|
||||
Leaflet.clearLayer('eventRemoveRouteStartEnd');
|
||||
Trucks.bundleShowRouteTruck(false);
|
||||
});
|
||||
$('#historyEndDate').on('change', function(e) {
|
||||
const {
|
||||
isValid,
|
||||
data
|
||||
} = Wrapper.calcPeriodeDate(moment($('#historyStartDate').val()), moment($('#historyEndDate').val()))
|
||||
if (!isValid) return false;
|
||||
State.historyStartDate = data.startDate.unix();
|
||||
State.historyEndDate = data.endDate.unix();
|
||||
// $('#historyEndDate').on('change', function(e) {
|
||||
// const {
|
||||
// isValid,
|
||||
// data
|
||||
// } = Wrapper.calcPeriodeDate(moment($('#historyStartDate').val()), moment($('#historyEndDate').val()))
|
||||
// if (!isValid) return false;
|
||||
// State.historyStartDate = data.startDate.unix();
|
||||
// State.historyEndDate = data.endDate.unix();
|
||||
|
||||
Leaflet.clearLayer('eventRemoveRouteStartEnd');
|
||||
Trucks.bundleShowRouteTruck(false);
|
||||
});
|
||||
// Leaflet.clearLayer('eventRemoveRouteStartEnd');
|
||||
// Trucks.bundleShowRouteTruck(false);
|
||||
// });
|
||||
$('#historyStartDate').on('clearFilterHistoryDate', function(e) {
|
||||
State.historyStartDate = '';
|
||||
State.historyEndDate = '';
|
||||
$('#historyStartDate').val('');
|
||||
$('#historyEndDate').val('');
|
||||
// default date today
|
||||
State.historyStartDate = moment().startOf('day').unix();
|
||||
State.historyEndDate = moment().endOf('day').unix();
|
||||
$('#historyStartDate').val(moment().startOf('day').format('DD-MM-YYYY HH:mm'));
|
||||
$('#historyEndDate').val(moment().endOf('day').format('DD-MM-YYYY HH:mm'));
|
||||
|
||||
// // for testing purpose
|
||||
// State.historyStartDate = '1756054800';
|
||||
// State.historyEndDate = '1756141140';
|
||||
// $('#historyStartDate').val("25-08-2025 00:00");
|
||||
// $('#historyEndDate').val("25-08-2025 23:59");
|
||||
});
|
||||
},
|
||||
handlerFilterPopupVhcMarker: function(markers) {
|
||||
@ -2501,13 +2563,16 @@
|
||||
bundleShowRouteTruck: async function(cache = false) {
|
||||
Menu.clearListMovements();
|
||||
if (State.inShowVid != State.loadedLastMoveVid) $('#historyStartDate').trigger('clearFilterHistoryDate');
|
||||
Trucks.last_move = await Trucks.getLastMove(State.inShowVid, cache);
|
||||
|
||||
const getLastMove = await Trucks.getLastMove(State.inShowVid, cache);
|
||||
Trucks.last_move = getLastMove.flat()
|
||||
|
||||
if (Trucks.last_move.length < 1) {
|
||||
Helper.toast('Data Not Found', 'just now', 'There are no last data', 'bg-warning');
|
||||
Trucks.last_move = null;
|
||||
return false;
|
||||
}
|
||||
Trucks.showLastMoveToView(Trucks.last_move);
|
||||
Trucks.showLastMoveToView(getLastMove);
|
||||
},
|
||||
getLastMove: async function(vid, cache = false) {
|
||||
State.loadedLastMoveVid = vid;
|
||||
@ -2568,37 +2633,169 @@
|
||||
showLastMoveToView: function(truckRoutes) {
|
||||
// Leaflet.clearLayer('eventAboutTruck');
|
||||
Leaflet.hideLayer('eventHideAllTruck');
|
||||
Trucks.routeStartEnd(truckRoutes);
|
||||
// Trucks.routeStartEnd(truckRoutes);
|
||||
Trucks.routeStartEndGroupTrip(truckRoutes);
|
||||
},
|
||||
routeStartEnd: function(truckRoutes) {
|
||||
let key_length = truckRoutes.length;
|
||||
let polyTruckRoutes = truckRoutes.map((obj, key) => {
|
||||
obj.key_index = key + 1 // key_length - key;
|
||||
// lists per detail info movement
|
||||
Menu.showToListMovement(obj);
|
||||
// routeStartEnd: function(truckRoutes) {
|
||||
// let key_length = truckRoutes.length;
|
||||
// let polyTruckRoutes = truckRoutes.map((obj, key) => {
|
||||
|
||||
// obj.key_index = key + 1 // key_length - key;
|
||||
// // lists per detail info movement
|
||||
// Menu.showToListMovement(obj);
|
||||
// return {
|
||||
// lat: obj.latitude,
|
||||
// lng: obj.longitude,
|
||||
// options: {
|
||||
// // polyline
|
||||
// smoothFactor: 1.0,
|
||||
// noClip: true,
|
||||
// bubblingMouseEvents: false,
|
||||
// // circle
|
||||
// radius: 5,
|
||||
// // markerOpacity: 0
|
||||
// },
|
||||
// // circle
|
||||
// // label: `<b>${obj.key_index}</b><br>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}<br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof obj.speed != 'undefined') ? obj.speed : '0'}<br>${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// // label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// }
|
||||
// });
|
||||
|
||||
// let polyline = Leaflet.addPolylines(polyTruckRoutes);
|
||||
// Leaflet.map.fitBounds(polyline.getBounds());
|
||||
// // let ctrWaypoint = Leaflet.addWaypoints(polyTruckRoutes.slice(0, 100))
|
||||
|
||||
// Leaflet.addCircles(polyTruckRoutes, function(circle, i) {
|
||||
// window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
// circle.remove();
|
||||
// });
|
||||
// circle.on('click', function() {
|
||||
// PgBar.syncToPlotTravelHistory(i);
|
||||
// })
|
||||
// });
|
||||
|
||||
// let start = truckRoutes.at(-1);
|
||||
// let finish = truckRoutes.at(0);
|
||||
// // ${(start?.city_text || start?.state_tex || 'address't)} - ${(start?.postcode || 'postcode')}
|
||||
// // ${(finish?.city_text || finish?.state_text || 'address')} - ${(finish?.postcode || 'postcode')}
|
||||
// let startMarker = Leaflet.addMarkers({
|
||||
// lat: start.latitude,
|
||||
// lng: start.longitude,
|
||||
// label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
// // label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
// options: {
|
||||
// icon: Icon.titikAwal(),
|
||||
// // rotationAngle: 290
|
||||
// }
|
||||
// });
|
||||
// let finishMarker = Leaflet.addMarkers({
|
||||
// lat: finish.latitude,
|
||||
// lng: finish.longitude,
|
||||
// label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
// //label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
// options: {
|
||||
// icon: Icon.titikAkhir()
|
||||
// }
|
||||
// });
|
||||
|
||||
// // remove marker, circle, event listener and all about this marker
|
||||
// State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
// startMarker,
|
||||
// finishMarker,
|
||||
// polyline,
|
||||
// polyline,
|
||||
// });
|
||||
// window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
// startMarker.removeEventListener('click');
|
||||
// startMarker.removeEventListener('moveend');
|
||||
// startMarker.remove();
|
||||
// finishMarker.removeEventListener('click');
|
||||
// finishMarker.removeEventListener('moveend');
|
||||
// finishMarker.remove();
|
||||
// polyline.remove();
|
||||
// e.currentTarget.removeEventListener(e.type,
|
||||
// handler); // window.removeEventListener('remove', this.handler, true);
|
||||
// State.eventRemoveRouteStartEnd = null;
|
||||
// State.inShowLastMove = null;
|
||||
|
||||
// PgBar.tglMenuPlayback(false);
|
||||
// PgBar.reset();
|
||||
// });
|
||||
|
||||
// PgBar.setMinMax(0, truckRoutes.length - 1);
|
||||
// },
|
||||
routeStartEndGroupTrip: function(truckRoutes) {
|
||||
const colors = [
|
||||
"#2980B9", // Dark Blue
|
||||
"#C0392B", // Dark Red
|
||||
"#27AE60", // Dark Green
|
||||
"#D35400", // Dark Orange
|
||||
"#F39C12", // Dark Yellow/Gold
|
||||
]
|
||||
let i = 1
|
||||
let polyTruckRoutes = truckRoutes.map((groupTrip, key0) => {
|
||||
return groupTrip.map((obj, key) => {
|
||||
obj.key_index = i++
|
||||
// console.log("obj", obj.key_index);
|
||||
|
||||
Menu.showToListMovement(obj)
|
||||
|
||||
// add start end marker per group trip
|
||||
if(key == 0 || key == groupTrip.length - 1)
|
||||
Leaflet.addMarkers({
|
||||
lat: obj.latitude,
|
||||
lng: obj.longitude,
|
||||
label: `
|
||||
<b>Start Poin</b><br>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}<br>
|
||||
${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>
|
||||
Speed: ${(typeof obj.lst_speed != 'undefined') ? obj.lst_speed : '0'}<br>
|
||||
${Number(obj.latitude).toFixed(5)},${Number(obj.longitude).toFixed(6)}<br>
|
||||
${decodeURIComponent(obj.fulladdress || 'address')}
|
||||
`,
|
||||
// label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
options: {
|
||||
icon: (key == 0) ? Icon.titikAkhir() : (key == (groupTrip.length - 1)) ? Icon.titikAwal() : null,
|
||||
// rotationAngle: 290
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
lat: obj.latitude,
|
||||
lng: obj.longitude,
|
||||
options: {
|
||||
// polyline
|
||||
smoothFactor: 1.0,
|
||||
color : colors[key0 % colors.length],
|
||||
smoothFactor : 0,
|
||||
noClip : true,
|
||||
bubblingMouseEvents : false,
|
||||
// circle
|
||||
radius: 2,
|
||||
radius: 5,
|
||||
markerOpacity: 0
|
||||
},
|
||||
// circle
|
||||
// label: `<b>${obj.key_index}</b><br>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}<br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof obj.speed != 'undefined') ? obj.speed : '0'}<br>${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// startLast : (key == 0) ? 0 : (key == (groupTrip.length - 1)) ? 1 : null,
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
// console.log("truckRoutes update", polyTruckRoutes);
|
||||
|
||||
let polyline = Leaflet.addPolylines(polyTruckRoutes);
|
||||
Leaflet.map.fitBounds(polyline.getBounds());
|
||||
// let ctrWaypoint = Leaflet.addWaypoints(polyTruckRoutes.slice(0, 100))
|
||||
polyTruckRoutes.forEach((poly, idx) => {
|
||||
// console.log("poly", poly);
|
||||
let polyline = Leaflet.addRoutes(poly)
|
||||
// let polyline = Leaflet.addPolylines(poly)
|
||||
// if(idx == 0)
|
||||
// Leaflet.map.fitBounds(polyline.getBounds());
|
||||
|
||||
|
||||
// let circlesStartStop = [...poly.filter((p, i) => i == 0 || i == (poly.length - 1))]
|
||||
let circlesStartStop = []
|
||||
// console.log("circlesStartStop", circlesStartStop);
|
||||
|
||||
Leaflet.addCircles(poly, function(circle, i) {
|
||||
if(i == 0 || i == (polyTruckRoutes.length - 1))
|
||||
circlesStartStop.push(circle)
|
||||
|
||||
Leaflet.addCircles(polyTruckRoutes, function(circle, i) {
|
||||
window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
circle.remove();
|
||||
});
|
||||
@ -2607,45 +2804,37 @@
|
||||
})
|
||||
});
|
||||
|
||||
let start = truckRoutes.at(-1);
|
||||
let finish = truckRoutes.at(0);
|
||||
// ${(start?.city_text || start?.state_tex || 'address't)} - ${(start?.postcode || 'postcode')}
|
||||
// ${(finish?.city_text || finish?.state_text || 'address')} - ${(finish?.postcode || 'postcode')}
|
||||
let startMarker = Leaflet.addMarkers({
|
||||
lat: start.latitude,
|
||||
lng: start.longitude,
|
||||
label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
// label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
options: {
|
||||
icon: Icon.titikAwal(),
|
||||
// rotationAngle: 290
|
||||
}
|
||||
});
|
||||
let finishMarker = Leaflet.addMarkers({
|
||||
lat: finish.latitude,
|
||||
lng: finish.longitude,
|
||||
label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
//label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
options: {
|
||||
icon: Icon.titikAkhir()
|
||||
// // remove marker, circle, event listener and all about this marker
|
||||
State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
detail: {
|
||||
polyline,
|
||||
circlesStartStop
|
||||
}
|
||||
});
|
||||
|
||||
// remove marker, circle, event listener and all about this marker
|
||||
State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
startMarker,
|
||||
finishMarker,
|
||||
polyline,
|
||||
polyline,
|
||||
});
|
||||
window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
startMarker.removeEventListener('click');
|
||||
startMarker.removeEventListener('moveend');
|
||||
startMarker.remove();
|
||||
finishMarker.removeEventListener('click');
|
||||
finishMarker.removeEventListener('moveend');
|
||||
finishMarker.remove();
|
||||
window.addEventListener('eventRemoveRouteStartEnd', function (e) {
|
||||
// console.log("circlesStartStop", circlesStartStop);
|
||||
polyline.remove();
|
||||
circlesStartStop.forEach(c => c.remove())
|
||||
});
|
||||
// State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
// polyline,
|
||||
// circlesStartStop,
|
||||
// });
|
||||
// console.log("polyline", polyline);
|
||||
// console.log("circlesStartStop", circlesStartStop);
|
||||
// console.log("State.eventRemoveRouteStartEnd", State.eventRemoveRouteStartEnd);
|
||||
|
||||
})
|
||||
|
||||
window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
// startMarker.removeEventListener('click');
|
||||
// startMarker.removeEventListener('moveend');
|
||||
// startMarker.remove();
|
||||
// finishMarker.removeEventListener('click');
|
||||
// finishMarker.removeEventListener('moveend');
|
||||
// finishMarker.remove();
|
||||
// polyline.remove();
|
||||
e.currentTarget.removeEventListener(e.type,
|
||||
handler); // window.removeEventListener('remove', this.handler, true);
|
||||
State.eventRemoveRouteStartEnd = null;
|
||||
@ -2655,7 +2844,7 @@
|
||||
PgBar.reset();
|
||||
});
|
||||
|
||||
PgBar.setMinMax(0, truckRoutes.length - 1);
|
||||
PgBar.setMinMax(0, Trucks.last_move.length - 1);
|
||||
},
|
||||
routePerPoint: function() {
|
||||
Leaflet.addMarkers(truckRoutes.routes.map((obj) => {
|
||||
|
||||
614
resources/views/menu_v1/reports/vehicle_trips.blade.php
Normal file
614
resources/views/menu_v1/reports/vehicle_trips.blade.php
Normal file
@ -0,0 +1,614 @@
|
||||
@php
|
||||
$user_role = Auth::user()->role;
|
||||
@endphp
|
||||
|
||||
@extends('app.app')
|
||||
|
||||
@section('title')
|
||||
Vehicles
|
||||
@endsection
|
||||
|
||||
@section('customcss')
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row d-flex align-items-center">
|
||||
<div class="col-3">
|
||||
<p class="card-title text-bold mb-0">Vehicle Trips Report</p>
|
||||
</div>
|
||||
@if ($user_role == \App\Models\Users::ROLE_VENDOR || $user_role == \App\Models\Users::ROLE_ADMIN)
|
||||
@can('vehicle.create')
|
||||
<!-- <div class="col text-end">
|
||||
<button id="btnMdlNewVhc" class="btn btn-sm btn-danger">Add New Vehicle</button>
|
||||
</div> -->
|
||||
@endcan
|
||||
|
||||
{{-- <div class="col-auto text-end ps-0">
|
||||
<button class="btn btn-sm btn-danger">Upload</button>
|
||||
</div> --}}
|
||||
@endif
|
||||
<div class="col-auto text-end ps-0">
|
||||
<!-- <button class="btn btn-sm btn-danger">Download</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- filter -->
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">From</label>
|
||||
<input type="date" class="form-control"id="tgl0" value="2025-08-01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">To</label>
|
||||
<input type="date" class="form-control" id="tgl1" value="2025-08-28">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2 d-flex align-items-end">
|
||||
<!-- <button class="btn btn-sm btn-danger">Filter</button> -->
|
||||
<button class="btn btn-sm btn-danger">Download</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive p-2">
|
||||
<table id="tVehicleTrips" class="table table-hover dataTable ">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<!-- <th class="">#</th> -->
|
||||
<!-- <th class="text-center">Action</th> -->
|
||||
<th class="">Vehicle Name</th>
|
||||
<th class="">License Plate Number</th>
|
||||
<th class="">Number of Trips</th>
|
||||
<th class="">Total Milage (km)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>24-679</td>
|
||||
<td>24-679</td>
|
||||
<td>26</td>
|
||||
<td>442.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24-682</td>
|
||||
<td>24-682</td>
|
||||
<td>28</td>
|
||||
<td>312.7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24-877</td>
|
||||
<td>24-877</td>
|
||||
<td>15</td>
|
||||
<td>276.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A.16-347</td>
|
||||
<td>A.16-347</td>
|
||||
<td>37</td>
|
||||
<td>543.2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AL2025-B21</td>
|
||||
<td>AL2025-B21</td>
|
||||
<td>18</td>
|
||||
<td>295.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B.16-542</td>
|
||||
<td>B.16-542</td>
|
||||
<td>32</td>
|
||||
<td>478.2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B.24-264</td>
|
||||
<td>B.24-264</td>
|
||||
<td>24</td>
|
||||
<td>188.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B.24-274</td>
|
||||
<td>B.24-274</td>
|
||||
<td>33</td>
|
||||
<td>440.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ford Ranger</td>
|
||||
<td>26-199</td>
|
||||
<td>30</td>
|
||||
<td>631.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nissan AD</td>
|
||||
<td>B.10-517</td>
|
||||
<td>27</td>
|
||||
<td>375.9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Triton</td>
|
||||
<td>A.29-127</td>
|
||||
<td>26</td>
|
||||
<td>508.2</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- modal -->
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const State = {
|
||||
file_jimp_worker: "{{ asset('assets/js/worker/jimp.js') }}",
|
||||
storage_lara: "{{ asset('storage') }}/",
|
||||
dvc_type: {
|
||||
built_in: "{{ \App\Models\Devices::TYPE_BUILT_IN }}",
|
||||
portable: "{{ \App\Models\Devices::TYPE_PORTABLE }}",
|
||||
},
|
||||
};
|
||||
|
||||
const Wrapper = {
|
||||
activate: function() {
|
||||
Wrapper.event();
|
||||
DTable.activate();
|
||||
},
|
||||
event: function() {
|
||||
$('#add-device_id').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
$('#add-brand').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
$('#add-type').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
$('#add-model').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
$('#add-dcurrent').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
$('#add-dassign').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
$('#add-vendor_id').select2({
|
||||
dropdownParent: $('#mdlNewVhc'),
|
||||
});
|
||||
|
||||
$('#edt-device_id').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
$('#edt-brand').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
$('#edt-type').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
$('#edt-model').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
$('#edt-dcurrent').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
$('#edt-dassign').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
$('#edt-vendor_id').select2({
|
||||
dropdownParent: $('#mdlEdtVhc'),
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const DTable = {
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
$('#tVehicleTrips').DataTable();
|
||||
// if (Driver.Table.firstInitDataTable == 1) { loadTableSkeletonLoading() } else { Driver.Table.firstInitDataTable = 1; }
|
||||
// $('#tVehicles').DataTable({
|
||||
// processing: true,
|
||||
// serverSide: false,
|
||||
// bLengthChange: true,
|
||||
// deferRender: true,
|
||||
// destroy: true,
|
||||
// ajax: {
|
||||
// url: "{{ route('api_report_vehicle_trips_list') }}?cptid=" + AppState.current_company,
|
||||
// type: 'GET',
|
||||
// complete: function() {
|
||||
// // removeTableSkeletonLoading()
|
||||
// },
|
||||
// },
|
||||
// deferRender: true,
|
||||
// columns: [{
|
||||
// data: 'DT_RowIndex',
|
||||
// className: 'text-end',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// },
|
||||
// {
|
||||
// data: 'action',
|
||||
// className: 'text-center',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// let action = `
|
||||
// <a href="#" class="text-decoration-none me-1 btnEdtVhc">
|
||||
// <span class="icon ion-eye fz-16"></span>
|
||||
// </a>
|
||||
// `;
|
||||
// // <a href="#" class="text-decoration-none text-danger btnDelVhc">
|
||||
// // <span class="icon ion-trash-b fz-16"></span>
|
||||
// // </a>
|
||||
// return action;
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// data: 'name',
|
||||
// className: 'text-start text-nowrap',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// return `
|
||||
// <img src="${State.storage_lara}${row.fvhc_img}" class="img-fluid thumb-img-table" /><br>
|
||||
// ${row.nopol1} ${row.nopol2} ${row.nopol3}
|
||||
// `;
|
||||
// },
|
||||
// createdCell: function(td, cellData, rowData, row, col) {
|
||||
// $(td).attr('data-vid', rowData.vid);
|
||||
// $(td).attr('data-name', rowData.name);
|
||||
// $(td).attr('data-nopol1', rowData.nopol1);
|
||||
// $(td).attr('data-nopol2', rowData.nopol2);
|
||||
// $(td).attr('data-nopol3', rowData.nopol3);
|
||||
// },
|
||||
// },
|
||||
// // {
|
||||
// // data: 'stnk_img',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // // exp: ${row.stnk_exp?.split('-').reverse().join('-') || ''}
|
||||
// // return `
|
||||
// // <img src="${State.storage_lara}${data}" class="img-fluid thumb-img-table" /><br>
|
||||
// // ${row.nopol1} ${row.nopol2} ${row.nopol3}<br>
|
||||
// // exp: ${moment(row.stnk_exp).format('DD MMM YYYY') || '-'}
|
||||
// // `;
|
||||
// // },
|
||||
// // },
|
||||
// {
|
||||
// data: 'tax_exp',
|
||||
// className: 'text-end text-nowrap',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// // return (`${data?.split('-').reverse().join('-') || '-'}`);
|
||||
// return (`${moment(data).format('DD MMM YYYY') || '-'}`);
|
||||
// },
|
||||
// },
|
||||
// // {
|
||||
// // data: 'kir_exp',
|
||||
// // className: 'text-end text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${moment(data).format('DD MMM YYYY') || '-'}`);
|
||||
// // },
|
||||
// // },
|
||||
// {
|
||||
// data: 'crt',
|
||||
// className: 'text-end text-nowrap',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// return moment.unix(data).format('DD MMM YYYY');
|
||||
// },
|
||||
// },
|
||||
// @if ($user_role != \App\Models\Users::ROLE_VENDOR)
|
||||
// {
|
||||
// data: 'device_id',
|
||||
// className: 'text-end text-nowrap',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// return `<span class="d-none">${data}</span>` + Helper.splitEvery4Char(`${data}`);
|
||||
// },
|
||||
// },
|
||||
// @endif
|
||||
// // {
|
||||
// // data: 'dc_fullname',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (
|
||||
// // `${data}<br>` +
|
||||
// // `<a href="tel:0${row.dc_phone}">${Helper.splitEvery4Char('0'+row.dc_phone)}</a>` +
|
||||
// // ` || ` +
|
||||
// // `<a href="https://api.whatsapp.com/send/?phone=62${row.dc_phone}&text=Halo&app_absent=0" class="bg-light" target="_blank"><i class="text-success ion-social-whatsapp"></i></a>`
|
||||
// // );
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'da_fullname',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (
|
||||
// // `${data}<br>` +
|
||||
// // `<a href="tel:0${row.da_phone}">${Helper.splitEvery4Char('0'+row.da_phone)}</a>` +
|
||||
// // ` || ` +
|
||||
// // `<a href="https://api.whatsapp.com/send/?phone=62${row.da_phone}&text=Halo&app_absent=0" class="bg-light" target="_blank"><i class="text-success ion-social-whatsapp"></i></a>`
|
||||
// // );
|
||||
// // },
|
||||
// // },
|
||||
// {
|
||||
// data: 'type_name',
|
||||
// className: 'text-start text-nowrap',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// // return (`${row.brand_name}<br>-<br>${data}`);
|
||||
// return data;
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// data: 'vyear',
|
||||
// className: 'text-end',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// return (`${(data || '-')}`);
|
||||
// },
|
||||
// },
|
||||
// // {
|
||||
// // data: 'cc',
|
||||
// // className: 'text-start',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${(data || '0')} CC`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'vin',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${Helper.splitEvery4Char(data || '-')}`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'en',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${Helper.splitEvery4Char(data || '-')}`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'vcolor',
|
||||
// // className: 'text-start',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${(data || '-')}`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'fuel_type',
|
||||
// // className: 'text-start',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${(data || '-')}`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'tnkb_color',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${(data || '-')}`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'regis_year',
|
||||
// // className: 'text-end',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return (`${(data || '-')}`);
|
||||
// // },
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'speed_limit',
|
||||
// // className: 'text-end',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'fuel_capacity',
|
||||
// // className: 'text-end',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'fuel_drop_treshold',
|
||||
// // className: 'text-end',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'max_pressure',
|
||||
// // className: 'text-end',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'alert_zones',
|
||||
// // className: 'text-start',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'is_track_holiday_text',
|
||||
// // className: 'text-start',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// // {
|
||||
// // data: 'track_schedule',
|
||||
// // className: 'text-end',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// {
|
||||
// data: 'sum_milleage',
|
||||
// className: 'text-end',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// return Number(data).toFixed(2);
|
||||
// }
|
||||
// },
|
||||
// // {
|
||||
// // data: 'cameras',
|
||||
// // className: 'text-start',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // },
|
||||
// {
|
||||
// data: 'company_name',
|
||||
// className: 'text-start text-nowrap',
|
||||
// visible: true,
|
||||
// orderable: true,
|
||||
// searchable: true,
|
||||
// render: function(data, type, row, meta) {
|
||||
// return data || '-';
|
||||
// }
|
||||
// },
|
||||
// // {
|
||||
// // data: 'group_name',
|
||||
// // className: 'text-start text-nowrap',
|
||||
// // visible: true,
|
||||
// // orderable: true,
|
||||
// // searchable: true,
|
||||
// // render: function(data, type, row, meta) {
|
||||
// // return data || 'All Group';
|
||||
// // }
|
||||
// // },
|
||||
// ],
|
||||
// });
|
||||
},
|
||||
};
|
||||
|
||||
function safeVal(selector) {
|
||||
const val = $(selector).val();
|
||||
return (val === undefined || val === null || val === '') ? null : val;
|
||||
}
|
||||
|
||||
const Filter = {
|
||||
activate: function() {
|
||||
Filter.event();
|
||||
},
|
||||
event: function() {},
|
||||
triggerFilterCompany: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
}
|
||||
|
||||
async function convertImgHtmlToFile(imgHtml, imgWidth, imgHeight, mimeType, fileName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
let canvas = document.createElement("canvas")
|
||||
|
||||
// Draw image to canvas.
|
||||
canvas.width = imgWidth
|
||||
canvas.height = imgHeight
|
||||
let ctx = canvas.getContext('2d')
|
||||
ctx.drawImage(imgHtml, 0, 0)
|
||||
|
||||
// Convert canvas to ImageState.
|
||||
let imageData = ctx.getImageData(0, 0, imgWidth, imgHeight)
|
||||
// console.log(imageState.data.byteLength + ' bytes.')
|
||||
|
||||
// Convert canvas to Blob
|
||||
canvas.toBlob((blob) => {
|
||||
let newReader = new FileReader();
|
||||
newReader.addEventListener('loadend', () => {
|
||||
// Convert canvas to ArrayBuffer
|
||||
let arrayBuffer = newReader.result
|
||||
// console.log(arrayBuffer.byteLength + ' bytes.')
|
||||
|
||||
// Convert ArrayBuffer to Blob
|
||||
// let blob = new Blob([arrayBuffer], {type: mimeType})
|
||||
|
||||
// Dispay Blob content in an Image.
|
||||
// console.log(URL.createObjectURL(blob))
|
||||
|
||||
// Generate as file
|
||||
let newFile = new File([arrayBuffer], fileName, {
|
||||
type: mimeType,
|
||||
lastModified: new Date(),
|
||||
size: arrayBuffer.byteLength,
|
||||
})
|
||||
resolve(newFile)
|
||||
});
|
||||
newReader.readAsArrayBuffer(blob);
|
||||
}, mimeType);
|
||||
} catch (e) {
|
||||
reject(e.message)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Wrapper.activate();
|
||||
</script>
|
||||
@endsection
|
||||
@ -42,6 +42,18 @@
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@if (auth()->user()->can('config_truck_type.view') || auth()->user()->can('config_master_device.view') || auth()->user()->can('config_logs_gps.view'))
|
||||
<li class="nav-item dropdown {{ Request::segment(1) == 'reports' ? 'active' : '' }}">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="dropdownConfig" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Reports
|
||||
</a>
|
||||
<ul class="dropdown-menu" style="right: 0; left: auto;" aria-labelledby="dropdownConfig">
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(2) == 'vehicle-trips' ? 'active' : '' }}" href="{{ route('view_report_vehicle_trips') }}" title="">Vehicle Trips</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@if (auth()->user()->can('config_truck_type.view') || auth()->user()->can('config_master_device.view') || auth()->user()->can('config_logs_gps.view'))
|
||||
<li class="nav-item dropdown {{ Request::segment(1) == 'config' ? 'active' : '' }}">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="dropdownConfig" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
|
||||
@ -153,6 +153,11 @@ Route::middleware(["auth", "auth.user"])->group(function () {
|
||||
);
|
||||
Route::get("/config/logbook_keys", "LogbookKeysController@view_lgb_keys")->name("view_config_lgb_keys");
|
||||
|
||||
// reports
|
||||
Route::get("/reports/vehicle-trips", "ReportsController@view_report_vehicle_trips")->name("view_report_vehicle_trips");
|
||||
Route::get("/reports/vehicle-trips-list", "ReportsController@api_report_vehicle_trips_list")->name("api_report_vehicle_trips_list");
|
||||
|
||||
|
||||
Route::get("/user/vendor/transactions", "MenuController@view_user_vendor_transaction")->name(
|
||||
"view_user_vendor_transaction"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user