Files
gps-frontend/resources/views/menu_v1/dashboard.blade.php
Pringgosutono 0284d25af4 dashboard fix
2025-09-25 16:51:16 +07:00

3502 lines
175 KiB
PHP
Executable File

@extends('app.app')
@section('title')
Dashboard
@endsection
@section('customcss')
{{-- <link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.css" /> --}}
{{-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" integrity="sha512-gc3xjCmIy673V6MyOAZhIW93xhM9ei1I+gLbmFjUHIjocENRsLX/QUE1htk5q1XV2D/iie/VQ8DXI6Vu8bexvQ==" crossorigin="anonymous" referrerpolicy="no-referrer" /> --}}
<link rel="stylesheet" href="{{ asset('assets/css/r.css') }}" />
<style>
.infoMove-plots li:hover {
/* background: #ffd25c; */
background: rgba(229, 41, 32, .25);
}
.infoMove-plots li.hover {
/* background: #ffd25c; */
background: rgba(229, 41, 32, .25);
}
.leaflet-control-container .leaflet-left {
display: none;
}
.leaflet-routing-container {
display: none !important;
}
#openLeftSideBar1Mobile {
display: none;
}
.ptName {
display: none;
}
@media (max-width: 425px) {
#openLeftSideBar1 {
display: none !important;
}
#openLeftSideBar1Mobile {
display: block !important;
}
.ptName {
display: block;
}
}
</style>
@endsection
@section('content')
<div class="container-fluid bg-white">
<div class="row">
{{-- list zones --}}
<div class="col-sm-2 bg-white overflow-auto panel-right border-end d-none" id="leftSideBar1">
<div class="row d-flex align-items-center mb-3">
<div class="col text-start">
<a href="javascript:void(0);" class="text-decoration-none text-dark" id="closeLeftSideBar1">
<span class="icon ion-ios-arrow-left fz-18"></span>
</a>
</div>
<div class="col text-end">
<p class="mb-0 text-bold">Zone List (<span id="c_list_zone">2</span>)</p>
</div>
</div>
<div class="row d-flex align-items-center mb-3 ptName">
<div class="col text-dark text-bold"><span id="ptName">{{ $client_group->c_name }}</span></div>
</div>
<div class="row d-flex align-items-center mb-3">
<div class="col text-danger"><a id="clearZone" href="javascript:void(0);"><small>hide zone</small></a></div>
</div>
<div class="form-group mb-3">
<input id="filterZoneSearch" type="text" class="form-control form-control-sm" placeholder="Search Zone">
</div>
<ul id="listZone" class="list-group">
<li class="list-group-item vehicles-list-wrapper zone-item p-1 px-2">
<a href="#" class="text-dark">
<div class="row d-flex align-items-center">
<div class="col-3 d-flex justify-content-center">
<div class="align-items-center d-flex justify-content-center zone-icon" style="background: #B600FF">
<span class="ion-android-pin text-white"></span>
</div>
</div>
<div class="col ps-0">
<p class="text-bold mb-0">BRK001</p>
<p class="text-muted mb-0">Warehouse</p>
</div>
</div>
</a>
</li>
<li class="list-group-item vehicles-list-wrapper p-1 px-2">
<a href="#" class="text-dark">
<div class="row d-flex align-items-center">
<div class="col-3 d-flex justify-content-center">
<div class="align-items-center d-flex justify-content-center zone-icon" style="background: #B600FF">
<span class="ion-android-pin text-white"></span>
</div>
</div>
<div class="col ps-0">
<p class="text-bold mb-0">BRK002</p>
<p class="text-muted mb-0">Warehouse</p>
</div>
</div>
</a>
</li>
</ul>
</div>
{{-- zone detail --}}
<div class="col-sm-2 bg-white overflow-auto panel-right border-end d-none" id="leftSideBar2">
<div class="text-end">
<a href="javascript:void(0);" class="text-decoration-none text-danger" id="closeLeftSideBar2">
<span class="icon ion-android-close fz-18"></span>
</a>
</div>
<div class="card shadow-none border mb-3">
<div class="card-body p-2">
<div class="row d-flex align-items-center">
<div class="col-3 d-flex justify-content-center">
<div id="zd-boundary_hex_color" class="align-items-center d-flex justify-content-center zone-icon" style="background: #B600FF">
<span class="ion-android-pin text-white"></span>
</div>
</div>
<div class="col ps-0">
<p id="zd-name" class="text-bold mb-0">BRK001</p>
<p id="zd-type_name" class="text-muted mb-0">Warehouse</p>
</div>
</div>
</div>
</div>
<ul class="list-group">
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Client</p>
<p id="zd-client" class="text-muted mb-0">JNE</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Tipe</p>
<p id="zd-type_name1" class="text-muted mb-0">Warehouse</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Jenis Zona</p>
<p id="zd-workflow_type_name" class="text-muted mb-0">Pickup</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Alamat</p>
<p id="zd-fulladdress" class="text-muted mb-0">Jl. Letjen Mt. Haryono No.Kav. 20, RW.1, Cawang, Kec.
Kramat jati, Kota Jakarta Timur, Daerah Khusus Ibukota Jakarta</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Kode Pos</p>
<p id="zd-shiptocode" class="text-muted mb-0">13630</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Pembaharuan Terakhir</p>
<p class="text-muted mb-0">
<span id="zd-updt_at">22-Sep-2020 04:43:43</span>
<span id="zd-updt_by">RTadmin</span>
</p>
</li>
</ul>
</div>
<div class="col px-0">
<div id="map" style="{{ Auth::user()->role != 2 ? 'height: calc(100vh - 90.52px) !important' : '' }}">
{{-- client logo --}}
{{-- <div class="card floating-menu-left mb-0" id="openLeftSideBar1">
<div class="card-body">
<div class="cNameGroup row d-flex align-items-center justify-content-between mb-1">
<div class="col-auto">
<p id="c_name" class="mb-0 fz-14">{{ $client_group->c_name }}</p>
</div>
<div class="col-1 me-1">
<a href="javascript:void(0);" class="text-decoration-none text-dark fz-18">
<span class="icon ion-ios-arrow-right"></span>
</a>
</div>
</div>
<div class="cLogoGroup row">
<div class="col-11 text-center ms-2">
@if ($client_group)
<img id="c_logo" src="{{ asset('storage/' . $client_group->c_logo) ?? asset('images/swa-nusa-logo.png') }}" alt="Client logo" class="img-fluid thumb-img-landscape-med">
@else
<img id="c_logo" src="{{ asset('images/swa-nusa-logo.png') }}" alt="Client logo" class="img-fluid" style="height: 40px">
@endif
</div>
</div>
</div>
</div> --}}
<a href="javascript:void(0);" class="btn btn-sm bg-white text-decoration-none text-dark fz-18 floating-menu-left" id="openLeftSideBar1" style="width:38px;">
<span class="icon ion-ios-arrow-right"></span>
</a>
<a href="javascript:void(0);" class="btn btn-sm bg-white text-decoration-none text-dark fz-18 floating-menu-left" id="openLeftSideBar1Mobile" style="width:38px;">
<span class="icon ion-ios-arrow-right"></span>
</a>
<a href="javascript:void(0);" class="btn btn-sm bg-white text-decoration-none text-dark fz-18 floating-menu-right d-none" id="openRightSideBar1">
<span class="icon ion-ios-arrow-left"></span>
</a>
<div id="menuPlayback" class="floating-menu-bottom bg-light mb-0 disablePanning d-none">
<div class="row">
<div id="pgplay" class="col-auto ps-4 pe-0" style="margin-top: 0.15rem;">
<i id="icon-pg" class="ion ion-play icon-pg"></i>
</div>
<div class="col">
<div id="pgcontainer" class="slidecontainer">
<input type="range" min="0" max="1000" value="0" class="slider" id="pgbar">
</div>
{{-- <div id="pgcontainer" class="pgcontainer">
<div id="pgbar" class="pgbar"></div>
</div> --}}
</div>
</div>
</div>
</div>
</div>
{{-- vehicle detail --}}
<div class="col-sm-2 bg-white overflow-auto panel-right border-end d-none" style="{{ Auth::user()->role != 2 ? 'height: calc(100vh - 90.52px) !important' : '' }}" id="rightSideBar2">
<div class="text-end">
<a href="javascript:void(0);" class="text-decoration-none text-danger" id="closeRightSideBar2"><span class="icon ion-android-close fz-18"></span></a>
</div>
<div class="card shadow-none border">
<div class="card-body p-2">
<div class="align-items-center d-flex row">
<div class="col-4">
<img id="infoVehicles-thumb-sm" src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png" class="img-fluid thumb-img-small" alt="">
</div>
<div class="col ps-0">
<p id="infoVehicles-platno" class="text-bold mb-0">B 1201 SYX</p>
<p id="infoVehicles-addr-title" class="text-muted mb-0">Kebon Baru - Tebet</p>
</div>
</div>
</div>
</div>
<div class="form-group mb-3 w-100">
<select name="" class="form-control select2" style="width: 100%;" id="selectFiter">
<option value="1">Vehicle</option>
<option value="2">Driver</option>
<option value="3">Job</option>
<option value="4">Travel History</option>
</select>
</div>
<ul class="list-group" id="infoVehicles">
<li class="list-group-item p-1">
<img id="infoVehicles-thumb-md" src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png" class="img-fluid thumb-img-landscape" alt="">
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Timestamp</p>
<p id="infoVehicles-crt" class="text-muted mb-0">20-Jan-2022 23:16:18</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Current Location</p>
<p id="infoVehicles-addr" class="text-muted mb-0">Kebon Baru - Tebet</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Latitude, Longitude</p>
<p id="infoVehicles-lat_lng" class="text-muted mb-0">-6.27013, 106.731371</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Vehicle Mileage (km)</p>
<p id="infoVehicles-mileage" class="text-muted mb-0">45080.83</p>
</li>
{{-- <li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Batas kecepatan (kph)</p>
<p id="infoVehicles-speedLimit" class="text-muted mb-0">100</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Keccepatan Saat Ini (kph)</p>
<p id="infoVehicles-currentSpeed" class="text-muted mb-0">60</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Pengapian</p>
<p id="infoVehicles-ignition" class="text-muted mb-0">ON</p>
</li> --}}
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Engine Status</p>
<p id="infoVehicles-engineStatus" class="text-muted mb-0">Idling</p>
</li>
{{-- <li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Durasi Berhenti (<span id="infoVehicles-idlingUnit">min</span>)</p>
<p id="infoVehicles-idlingDuration" class="text-muted mb-0">2946</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Zona Peringatan</p>
<p id="infoVehicles-alertZones" class="text-muted mb-0 d-block">Pasar Induk Cibitung, RAPID Office,
Rumah Ranko KBB, toll
Jorr</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Lacak di Hari Libur</p>
<p id="infoVehicles-isTrackHoliday" class="text-muted mb-0">Enabled</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Jadwal Pelacakan</p>
<p id="infoVehicles-trackSch" class="text-muted mb-0">24/7</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Perusahaan</p>
<p id="infoVehicles-company" class="text-muted mb-0">Swa Nusa Multimedia</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Tanggal Bergabung</p>
<p id="infoVehicles-serviceStart" class="text-muted mb-0">23-Aug-2018</p>
</li> --}}
</ul>
<ul class="list-group" id="infoDriver">
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Driver Information</p>
<p id="infoDrv-updt" class="text-muted mb-0">20-Jan-2022 23:16:18</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Driver Name</p>
<p id="infoDrv-name" class="text-muted mb-0">Emrsyf</p>
</li>
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Phone</p>
<p class="mb-0">
<a href="tel:0" id="infoDrv-phone1-tel">
<i class="text-dark ion-ios-telephone"></i>&nbsp;
<span class="infoDrv-phone1-text"></span>
</a>
</p>
<p class="mb-0">
<a href="https://api.whatsapp.com/send/?phone=62&text=Halo&app_absent=0" id="infoDrv-phone1-wa" target="_blank"><i class="text-success ion-social-whatsapp"></i>
<span class="infoDrv-phone1-text"></span>
</a>
</p>
</li>
{{-- <li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Phone 2</p>
<p class="mb-0">
<a href="tel:0" id="infoDrv-phone2-tel">
<i class="text-dark ion-ios-telephone"></i>&nbsp;
<span class="infoDrv-phone2-text"></span>
</a>
</p>
<p class="mb-0">
<a href="https://api.whatsapp.com/send/?phone=62&text=Halo&app_absent=0" id="infoDrv-phone2-wa" target="_blank"><i class="text-success ion-social-whatsapp"></i>
<span class="infoDrv-phone2-text"></span>
</a>
</p>
</li> --}}
</ul>
<div id="infoJob">
{{-- @for ($i = 0; $i < 20; $i++)
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">#902192102910</p>
<div class="row d-flex align-items-center justify-content-between">
<div class="col-auto">
<small class="text-muted">Client name</small>
<p id="" class="mb-0">JNE</p>
</div>
<div class="col-auto">
<small class="text-muted">Destination</small>
<p id="" class="mb-0">JKT-01</p></div>
</div>
</li>
@endfor --}}
{{-- <ul class="list-group mb-3">
<li class="list-group-item p-1 px-2">
<div class="row d-flex align-items-center justify-content-between">
<div class="col-12">
<small class="text-muted">Client</small>
<p id="infoJob-ord_client_name" class="mb-0">PT</p>
</div>
</div>
</li>
</ul> --}}
<ul class="list-group mb-3">
<li class="list-group-item p-1 px-2">
{{-- <p class="text-bold mb-0">#902192102910</p> --}}
<div class="row d-flex align-items-center justify-content-between">
<div class="col-12">
<small class="text-muted">Origin</small>
{{-- <p id="infoJob-pck_city" class="">Jakarta</p> --}}
<p id="infoJob-pck_name" class="mb-1 text-bold">JKT-01</p>
<p id="infoJob-pck_addr" class="mb-0">Jl. Pancoran Timur Raya No.9, RT.8/RW.9, Pancoran, Kec. Pancoran, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12780</p>
</div>
</div>
</li>
<li class="list-group-item p-1 px-2">
{{-- <p class="text-bold mb-0">#902192102910</p> --}}
<div class="row d-flex align-items-center justify-content-between">
<div class="col-12">
<small class="text-muted">Destination</small>
{{-- <p id="infoJob-drop_city" class="">Indramayu</p> --}}
<p id="infoJob-drop_name" class="mb-1 text-bold">IND-01</p>
<p id="infoJob-drop_addr" class="mb-0">Jl. Jend. Sudirman, Karanganyar, Kec. Indramayu, Kabupaten Indramayu, Jawa Barat</p>
</div>
</div>
</li>
</ul>
<ul class="list-group">
<li class="list-group-item p-1 px-2">
{{-- <p class="text-bold mb-0">#902192102910</p> --}}
<div class="row d-flex align-items-center justify-content-between">
<div class="col-12">
<small class="text-muted">Status</small>
<p id="infoJob-ord_stts" class="mb-0">On Going</p>
</div>
</div>
</li>
</ul>
</div>
<ul class="list-group" id="infoMovement">
<li class="list-group-item p-1 px-2 mb-2" style="border-radius: 0.25rem;">
<p class="text-bold mb-0">Trip History</p>
<p id="infoVehicles-infoMove" class="text-muted mb-0">Most Recent</p>
</li>
<div>
<div class="mb-2">
<label class="text-muted">From</label>
<!-- <input class="form-control" id="historyStartDate"> -->
<input class="form-control" id="historyStartDate" value="11-08-2025 00:00">
</div>
<div class="mb-2">
<label class="text-muted">To</label>
<!-- <input class="form-control" id="historyEndDate"> -->
<input class="form-control" id="historyEndDate" value="11-08-2025 23:00">
</div>
<button class="btn btn-primary btn-sm w-100 mb-3" id="historySearch">Search</button>
</div>
<div id="infoMove-plots" class="infoMove-plots">
{{-- <a href="#" class="plotMove-item">
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">Number</p>
<p class="text-muted mb-0">${Number(obj.latitude).toFixed(6)} - ${Number(obj.longitude).toFixed(6)}</p>
<p class="text-muted mb-0">${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}</p>
</li>
</a> --}}
</div>
</ul>
</div>
{{-- vehicle list & filter --}}
<div class="col-sm-2 bg-white overflow-auto panel-right" style="{{ Auth::user()->role != 2 ? 'height: calc(100vh - 90.52px) !important' : '' }}" id="rightSideBar1">
{{-- filter --}}
<div class="row d-flex align-items-center mb-3 justify-content-between">
<div class="col-auto">
<div class="row">
<div class="col-auto text-start align-items-center d-flex">
<a href="javascript:void(0);" class="mb-0 text-bold text-dark" id="filterVhcZone" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Filter Vehicles Within and Outside the Zone">
<span class="ion-android-car me-1" style="font-size: 17px">
</span>
</a>
<span id="c_vhc_zone">-</span>
</div>
<div class="col-auto text-start align-items-center d-flex">
<a href="javascript:void(0);" class="mb-0 text-bold text-dark me-2" id="filterVhcMarker" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Marker Info">
<span class="ion-android-pin me-2 text-muted" style="font-size: 17px"></span>
</a>
</div>
{{-- <div class="col-auto text-start align-items-center d-flex">
<a href="javascript:void(0);" class="mb-0 text-bold text-dark" id="filterVhcGps" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Vehicle GPS Filter">
<span class="ion-pinpoint me-1 text-muted" style="font-size: 17px"></span>
</a>
<span id="c_vhc_gps">-</span>
</div>
<div class="col-auto text-start align-items-center d-flex">
<a href="javascript:void(0);" class="mb-0 text-bold text-dark" id="filterVhcGsm" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Vehicle GSM Filter">
<span class="ion-android-wifi me-1 text-muted" style="font-size: 17px"></span>
</a>
<span id="c_vhc_gsm">-</span>
</div> --}}
</div>
</div>
<div class="col-auto">
<div class="">
<div class="col text-end align-items-center d-flex">
{{-- <a href="javascript:void(0);" class="mb-0 text-bold text-dark me-2" id="filterVhcMarker" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Marker Info">
<span class="ion-android-pin me-2 text-muted" style="font-size: 17px"></span>
</a> --}}
<a href="javascript:void(0);" class="text-decoration-none text-dark fz-18" id="closeRightSideBar1">
<span class="icon ion-ios-arrow-right"></span>
</a>
</div>
</div>
</div>
</div>
<div class="form-group mb-3">
<input type="text" id="filterVhcSearch" class="form-control form-control-sm" placeholder="Search Vehicle">
</div>
{{-- vehicle list --}}
<ul id="listTrucks" class="list-group">
{{-- <li class="list-group-item vehicles-list-wrapper p-1 px-2">
<a href="#" class="text-dark">
<div class="row d-flex align-items-center">
<div class="col-3">
<img src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png"
class="img-fluid" alt="">
</div>
<div class="col ps-0">
<p class="text-bold mb-0">B 1201 SYX</p>
<p class="text-muted mb-0">Kebon Baru - Tebet</p>
</div>
</div>
</a>
</li>
<li class="list-group-item vehicles-list-wrapper p-1 px-2">
<a href="#" class="text-dark">
<div class="row d-flex align-items-center">
<div class="col-3">
<img src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png"
class="img-fluid" alt="">
</div>
<div class="col ps-0">
<p class="text-bold mb-0">B 1202 SYX</p>
<p class="text-muted mb-0">Kebon Baru - Tebet</p>
</div>
</div>
</a>
</li> --}}
</ul>
</div>
</div>
</div>
<div class="footer-dashboard">
<div class="container-fluid">
<div class="row">
<div class="col d-flex align-content-center">
<span class="badge p-1 ps-3 pe-3 bg-danger me-2">Stopped</span>
<span class="badge p-1 ps-3 pe-3 bg-warning me-2">Idling</span>
<span class="badge p-1 ps-3 pe-3 bg-success">Moving</span>
</div>
<div class="col text-end" id="tripInfo">
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#C0392B !important;">Trip 1</span>
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#2980B9 !important;">Trip 2</span>
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#27AE60 !important;">Trip 3</span>
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#D35400 !important;">Trip 4</span>
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#F39C12 !important;">Trip 5</span>
</div>
</div>
</div>
</div>
@endsection
@section('customjs')
<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://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
'use strict';
const State = {
isDrawPolygon: 0,
timingRouteAnimation: 100,
storage_lara: "{{ asset('storage') }}/",
ord_code: 0,
zone_boundary_type: {
circle: "{{ App\Models\Zone::ZONE_BOUNDARY_CIRCLE }}",
polygon: "{{ App\Models\Zone::ZONE_BOUNDARY_POLYGON }}",
rectangle: "{{ App\Models\Zone::ZONE_BOUNDARY_RECTANGLE }}",
},
zone_status: {
active: "{{ App\Models\Zone::STATUS_ACTIVE }}",
inactive: "{{ App\Models\Zone::STATUS_INACTIVE }}",
},
stts_engine: {
idling: "{{ App\Models\Tracks::STTS_EN_IDLING }}",
moving: "{{ App\Models\Tracks::STTS_EN_MOVING }}",
stoping: "{{ App\Models\Tracks::STTS_EN_STOPING }}",
},
stts_gps: {
active: "{{ App\Models\Tracks::STTS_GPS_ON }}",
inactive: "{{ App\Models\Tracks::STTS_GPS_OFF }}",
},
stts_gsm: {
no_signal: "{{ App\Models\Tracks::STTS_GSM_NO_SIGNAL }}",
bad_signal: "{{ App\Models\Tracks::STTS_GSM_BAD_SIGNAL }}",
weak_signal: "{{ App\Models\Tracks::STTS_GSM_WEAK_SIGNAL }}",
good_signal: "{{ App\Models\Tracks::STTS_GSM_GOOD_SIGNAL }}",
strong_signal: "{{ App\Models\Tracks::STTS_GSM_STRONG_SIGNAL }}",
},
stts_ignition: {
active: "{{ App\Models\Tracks::STTS_IGNITION_ON }}",
inactive: "{{ App\Models\Tracks::STTS_IGNITION_OFF }}",
low: "{{ App\Models\Tracks::STTS_IGNITION_LOW }}",
high: "{{ App\Models\Tracks::STTS_IGNITION_HIGH }}",
},
stts_filterDetail: {
vehicles: 1,
driver: 2,
assignJob: 3,
lastMove: 4,
},
stts_order: {
wait: "{{ App\Models\Orders::STTS_WAIT }}",
confirm: "{{ App\Models\Orders::STTS_CONFIRM }}",
have_get_vhc: "{{ App\Models\Orders::STTS_HAVE_GET_VHC }}",
pck: "{{ App\Models\Orders::STTS_PCK }}",
go: "{{ App\Models\Orders::STTS_GO }}",
arv: "{{ App\Models\Orders::STTS_ARV }}",
drop: "{{ App\Models\Orders::STTS_DROP }}",
client_pay: "{{ App\Models\Orders::STTS_CLIENT_PAY }}",
vendor_payed: "{{ App\Models\Orders::STTS_VENDOR_PAYED }}",
close: "{{ App\Models\Orders::STTS_CLOSE }}",
cancel: "{{ App\Models\Orders::STTS_CANCEL }}",
},
statusFilterPopupVhcMarker: 1, // 0=>hidden,1=>nopol,2=>speed,3=>address
eventFilterPopupVhcMarker: null,
statusFilterVhcGps: 0, // 0=>all,1=>active,2=>not
lastStatusFilterVhcGps: 0,
isShowToltipFilterVhcGps: 0,
eventFilterVhcGps: null,
statusFilterVhcGsm: 0, // 0=>all,1=>active,2=>not
lastStatusFilterVhcGsm: 0,
isShowToltipFilterVhcGsm: 0,
eventFilterVhcGsm: null,
statusFilterVhcZone: 0, // 0=>all,1=>inside,2=>outside
lastStatusFilterVhcZone: 0,
isShowToltipFilterVhcZone: 1,
eventFilterVhcZone: null,
eventRemoveListTrucks: null,
eventRemoveRouteStartEnd: null,
eventRemoveDetailPlotMovement: null,
eventHideTruckNotSelected: null,
eventHideAllTruck: null,
inShowVid: null,
inShowLastMove: null,
loadedLastMoveVid: null,
lastShowVids: [],
inShowZid: null,
delay_typing_front: 1000,
delay_hideTruckNotSelected: 1000,
delay_auto_refresh: 1 * (60 * 1000), // per n minute
historyStartDate: '',
historyEndDate: '',
isPanning: true,
playback: {
stts: 0, // 0=>not,1=>play,2=>pause,3=>resume,4=>stop
crntIndicator: 0,
minIndicator: 0,
maxIndicator: 0,
intrvl: null, // setInterval()
intrvlTime: 1000, // 200 per ms
},
};
const Icon = {
hub: function() {
return L.icon({
iconUrl: "{{ asset('assets/icons/pin-resto.png') }}",
iconSize: [38, 48],
iconAnchor: [20, 46], // lb, rt, bottom, rb. Positive
popupAnchor: [0, -32],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
destination: function() {
return L.icon({
iconUrl: "{{ asset('assets/icons/pin-tujuan.png') }}",
iconSize: [38, 48],
iconAnchor: [20, 46], // lb, rt, bottom, rb. Positive
popupAnchor: [0, -32],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
point: function() {
return L.icon({
// iconUrl: 'https://www.nicepng.com/png/full/101-1015767_map-marker-circle-png.png',
iconUrl: "{{ asset('assets/icons/maps-marker-circle-blue-radius.png') }}",
iconSize: [38, 38],
// iconAnchor: [20, 46], // lb, rt, bottom, rb. Positive
// popupAnchor: [0, -32],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
startNav: function() {
return L.icon({
iconUrl: 'https://image.flaticon.com/icons/png/512/803/803559.png',
iconSize: [38, 38],
iconAnchor: [20, 16], // lb, rt, bottom, rb. Positive
// popupAnchor: [0, -32],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
titikAwal: function() {
return L.icon({
iconUrl: "{{ asset('images/start.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
// popupAnchor: [0, -32],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
titikAkhir: function() {
return L.icon({
iconUrl: "{{ asset('images/finish.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
// popupAnchor: [0, -32],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
vechicleIcon: function() {
return L.icon({
iconUrl: "{{ asset('images/2active.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
popupAnchor: [-3, -35],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
vhcIdleIcon: function() {
return L.icon({
iconUrl: "{{ asset('images/2idle.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
popupAnchor: [-3, -35],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
vhcStopIcon: function() {
return L.icon({
iconUrl: "{{ asset('images/2stop.png') }}",
iconSize: [30, 30],
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
popupAnchor: [-3, -35],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
},
};
const Wrapper = {
activate: function() {
Wrapper.init();
Leaflet.activate();
Menu.activate();
Trucks.activate();
Filter.activate();
PgBar.activate();
},
init: function() {
const queryString = Helper.initQueryString();
State.ord_code = queryString.ord_code;
if (Wrapper.checkIsMobileDevice()) {
$('#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();
let idlingDur = 0;
let last_idle = moment.unix(lst_idle_unix);
let unit = 'min';
if (lst_speed <= 0 || lst_speed == null || lst_speed == '' || typeof lst_speed == 'undefined') {
if (last_idle.isValid()) {
let diff = moment.duration(now.diff(last_idle));
idlingDur = diff.asMinutes();
// parsing to hour
if (idlingDur > 60) {
idlingDur = idlingDur / 60;
unit = 'hour';
}
}
}
return {
unit,
dur: idlingDur.toFixed(0),
};
},
calcPeriodeDate: function(startDate, endDate) {
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 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');
const duration = moment.duration(endDate.diff(startDate));
const diffDays = duration.days();
if (diffDays > 30) {
Helper.toast('Warning', 'just now', 'Maximum period is 1 month');
return {
isValid: false
};
}
if (diffDays < 0) {
Helper.toast('Warning', 'just now', 'Invalid period range');
return {
isValid: false
};
}
return {
isValid: true,
data: {
startDate,
endDate
}
};
},
checkIsMobileDevice: function() {
return (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
},
};
// ## centering + zoom
// Leaflet.map.fitBounds([
// [40.712, -74.227],
// [40.774, -74.125]
// ]);
// ## centering with animation
// Leaflet.map.panTo([40.712, -74.227], { duration: 5 });
const Leaflet = {
map: null,
activate: function() {
// centering indonesia country => .setView([-1.38116, 117.6168817], 5.4);
// 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 timor leste
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data &copy; <a href="https://www.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
// maxZoom: 20,
// minZoom: 4,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'pk.eyJ1IjoibWV1c2luZmlybWFyeSIsImEiOiJja3lsd2xveDAydGhqMnVxaHJsZ2ZncG8yIn0.f7MJAyawHUdCegw7sWjrww',
}).addTo(Leaflet.map);
Leaflet.events();
L.control.scale({
position: 'bottomright'
}).addTo(Leaflet.map);
L.control.zoom({
position: 'bottomright'
}).addTo(Leaflet.map);
},
events: function() {
Leaflet.map.on('click', function(e) {
// e.latlng.lat, e.latlng.lng
});
// https://gis.stackexchange.com/questions/104507/disable-panning-dragging-on-leaflet-map-for-div-within-map // number 2 from bottom
$('.disablePanning').on('mousedown', function() {
if (State.isPanning) {
State.isPanning = false;
Leaflet.map.dragging.disable();
}
});
$('.disablePanning').on('mouseup', function() {
if (!State.isPanning) {
State.isPanning = true;
Leaflet.map.dragging.enable();
}
});
},
addMarkers: function(locs = [], cb = null) {
if (locs.constructor === Array) {
let markers = [];
for (let i = 0; i < locs.length; i++) {
let label = locs[i]?.label || '';
let marker = new L.marker([locs[i].lat, locs[i].lng], locs[i]?.options);
let popup = new L.Popup({
autoClose: false,
closeOnClick: true,
}).setContent(locs[i]?.label || '').setLatLng([locs[i].lat, locs[i].lng]);
// marker.bindPopup(locs[i]?.label || '');
marker.bindPopup(popup);
marker.bindTooltip(locs[i]?.label || '');
markers.push(marker);
if (cb) cb(marker);
marker.addTo(Leaflet.map);
}
return markers;
} else if (locs.constructor === Object) {
let label = locs.label;
let marker = new L.marker([locs.lat, locs.lng], locs?.options);
let popup = new L.Popup({
autoClose: false,
closeOnClick: true,
}).setContent(locs?.label || '').setLatLng([locs.lat, locs.lng]);
// marker.bindPopup(locs?.label || '');
marker.bindPopup(popup);
marker.bindTooltip(locs?.label || '');
if (cb) cb(marker);
marker.addTo(Leaflet.map);
return marker;
}
},
addCircles: function(locs = [], cb = null) {
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 || '');
circles.push(circle);
if (cb) cb(circle, i);
circle.addTo(Leaflet.map);
}
return circles;
} else if (locs.constructor === Object) {
let circle = L.circle([locs.lat, locs.lng], locs?.options);
circle.bindPopup(locs?.label || '');
circle.bindTooltip(locs?.label || '');
if (cb) cb(circle);
circle.addTo(Leaflet.map);
return circle;
}
},
addPolylines: function(locs = [], cb = null) {
let latLngs = [];
for (let i = 0; i < locs.length; i++) {
latLngs.push([locs[i].lat, locs[i].lng]);
}
let polyline = L.polyline(latLngs, locs[0]?.options).addTo(Leaflet.map);
if (cb) cb(polyline);
return polyline;
},
addRoutes: async function(locs = [], cb = null) {
let latLngs = [];
for (let i = 0; i < locs.length; i++) {
latLngs.push([locs[i].lat, locs[i].lng]);
}
function chunkArray(arr, size) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
function fetchOsrm(points) {
const coords = points;
const hints = ";".repeat(points.length - 1);
const body = {
coordinates: coords,
overview: "false",
alternatives: "true",
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) => {
return response.data;
})
.catch((err) => {
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;
}
async function getCoordinates(points) {
const chunkSize = 500;
const chunks = chunkArray(points, chunkSize); // Split the points array into chunks of 500
let allCoords = [];
for (const chunk of chunks) {
const osrm = await fetchOsrm(chunk); // Fetch OSRM data for each chunk
if (!osrm) {
console.log("OSRM failed for chunk");
return;
}
const coords = osrm.routes[0].legs.flatMap(leg =>
leg.steps.flatMap(step =>
decodeOSRMGeometry(step.geometry)
)
);
allCoords = allCoords.concat(coords); // Combine the result
}
// Now add the polyline to the map
return L.polyline(allCoords, {
color: locs[0]?.options?.color,
weight: 3,
opacity: 0.8
}).addTo(Leaflet.map);
// map.fitBounds(allCoords.map(c => L.latLng(c[0], c[1])));
}
// Usage: Pass the array of coordinates to the function
const routes = await getCoordinates(latLngs);
// optionally fit bounds
// Leaflet.map.fitBounds(coords.map(c => L.latLng(c[0], c[1])));
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 */
let latLngs = [];
for (let i = 0; i < locs.length; i++) {
latLngs.push([locs[i].lat, locs[i].lng]);
}
let SmoothPoly = L.Polyline.extend({
// override default method to use custom points-to-path method
_updatePath: function() {
let path = Leaflet.roundPathCorners(this._parts, radius)
this._renderer._setPath(this, path);
}
})
let polyline = new SmoothPoly(latLngs, locs[0]?.options).addTo(Leaflet.map);
if (cb) cb(polyline);
return polyline;
},
roundPathCorners: function(rings, radius) {
function moveTowardsFractional(movingPoint, targetPoint, fraction) {
return {
x: movingPoint.x + (targetPoint.x - movingPoint.x) * fraction,
y: movingPoint.y + (targetPoint.y - movingPoint.y) * fraction
};
}
function pointForCommand(cmd) {
return {
x: parseFloat(cmd[cmd.length - 2]),
y: parseFloat(cmd[cmd.length - 1])
};
}
let resultCommands = [];
if (+radius) {
// negative numbers create artifacts
radius = Math.abs(radius);
} else {
radius = 0.15;
}
for (let i = 0, len = rings.length; i < len; i++) {
let commands = rings[i];
// start point
resultCommands.push(["M", commands[0].x, commands[0].y]);
for (let cmdIndex = 1; cmdIndex < commands.length; cmdIndex++) {
let prevCmd = resultCommands[resultCommands.length - 1];
let curCmd = commands[cmdIndex];
let nextCmd = commands[cmdIndex + 1];
if (nextCmd && prevCmd) {
// Calc the points we're dealing with
let prevPoint = pointForCommand(prevCmd); // convert to Object
let curPoint = curCmd;
let nextPoint = nextCmd;
// The start and end of the cuve are just our point moved towards the previous and next points, respectivly
let curveStart, curveEnd;
curveStart = moveTowardsFractional(
curPoint,
prevCmd.origPoint || prevPoint,
radius
);
curveEnd = moveTowardsFractional(
curPoint,
nextCmd.origPoint || nextPoint,
radius
);
// Adjust the current command and add it
curCmd = Object.values(curveStart);
curCmd.origPoint = curPoint;
curCmd.unshift("L");
resultCommands.push(curCmd);
// The curve control points are halfway between the start/end of the curve and
// calculate curve, if radius is different than 0
if (radius) {
let startControl = moveTowardsFractional(curveStart, curPoint, 0.5);
let endControl = moveTowardsFractional(curPoint, curveEnd, 0.5);
// Create the curve
let curveCmd = [
"C",
startControl.x,
startControl.y,
endControl.x,
endControl.y,
curveEnd.x,
curveEnd.y
];
// Save the original point for fractional calculations
curveCmd.origPoint = curPoint;
resultCommands.push(curveCmd);
}
} else {
// Pass through commands that don't qualify
let el = Object.values(curCmd);
el.unshift("L");
resultCommands.push(el);
}
}
}
return (
resultCommands.reduce(function(str, c) {
return str + c.join(" ") + " ";
}, "") || "M0 0"
);
},
// end custom polylines
addPolygons: function(locs = [], cb = null) {
let latLngs = [];
for (let i = 0; i < locs.length; i++) {
latLngs.push([locs[i].lat, locs[i].lng]);
}
let polygon = L.polygon(latLngs, locs[0]?.options).addTo(Leaflet.map);
polygon.bindPopup(locs[0]?.label || '');
polygon.bindTooltip(locs[0]?.label || '');
if (cb) cb(polygon);
return polygon;
},
addWaypoints: function(locs = [], cb = null) {
let latLngs = [];
for (let i = 0; i < locs.length; i++) {
latLngs.push(L.latLng(locs[i].lat, locs[i].lng));
}
let control = L.Routing.control({
waypoints: latLngs,
show: false,
waypointMode: 'snap',
createMarker: function() {}
}).addTo(Leaflet.map);
if (cb) cb(control);
return control;
},
drawPolygon: function(lat, lng, options = {}) {
let polygon = L.polygon([
[lat, lng]
], options).addTo(Leaflet.map);
return polygon;
},
eventMarkerClick: function(marker, cb = null) {
marker.on('click', function(e) {
// console.log(e.target.options); // get passing data from set marker: https://stackoverflow.com/questions/17423261/how-to-pass-data-with-marker-in-leaflet-js
Leaflet.map.invalidateSize();
if (Leaflet.map.getZoom() <= 14) {
Leaflet.map.setView(e.target.getLatLng(), 14);
}
if (cb) cb(e);
});
},
clearLayer: function(type = 'all', cb = null) {
if (type == 'all') {
if (State.eventRemoveListTrucks) window.dispatchEvent(State.eventRemoveListTrucks);
if (State.eventRemoveRouteStartEnd) window.dispatchEvent(State.eventRemoveRouteStartEnd);
if (State.eventRemoveDetailPlotMovement) window.dispatchEvent(State
.eventRemoveDetailPlotMovement);
if (State.eventRemoveListZones) window.dispatchEvent(State.eventRemoveListZones);
if (cb) cb();
} else if (type == 'eventRemoveListTrucks') {
if (State.eventRemoveListTrucks) {
window.dispatchEvent(State.eventRemoveListTrucks);
if (cb) cb();
}
} else if (type == 'eventRemoveRouteStartEnd') {
// console.log('clear route eventRemoveRouteStartEnd');
if (State.eventRemoveRouteStartEnd) {
window.dispatchEvent(State.eventRemoveRouteStartEnd);
if (cb) cb();
}
} else if (type == 'eventRemoveDetailPlotMovement') {
if (State.eventRemoveDetailPlotMovement) {
window.dispatchEvent(State.eventRemoveDetailPlotMovement);
if (cb) cb();
}
} else if (type == 'eventRemoveListZones') {
if (State.eventRemoveListZones) {
window.dispatchEvent(State.eventRemoveListZones);
if (cb) cb();
}
} else if (type == 'eventAboutTruck') {
if (State.eventRemoveListTrucks) window.dispatchEvent(State.eventRemoveListTrucks);
if (State.eventRemoveRouteStartEnd) window.dispatchEvent(State.eventRemoveRouteStartEnd);
if (State.eventRemoveDetailPlotMovement) window.dispatchEvent(State
.eventRemoveDetailPlotMovement);
if (cb) cb();
}
},
filterLayer: function(type = 'all', cb = null) {
if (type == 'all') {
if (State.eventFilterPopupVhcMarker) window.dispatchEvent(State.eventFilterPopupVhcMarker);
if (State.eventFilterVhcGps) window.dispatchEvent(State.eventFilterVhcGps);
if (State.eventFilterVhcGsm) window.dispatchEvent(State.eventFilterVhcGsm);
if (State.eventFilterVhcZone) window.dispatchEvent(State.eventFilterVhcZone);
if (cb) cb();
} else if (type == 'eventFilterPopupVhcMarker') {
if (State.eventFilterPopupVhcMarker) {
window.dispatchEvent(State.eventFilterPopupVhcMarker);
if (cb) cb();
}
} else if (type == 'eventFilterVhcGps') {
if (State.eventFilterVhcGps) {
window.dispatchEvent(State.eventFilterVhcGps);
if (cb) cb();
}
} else if (type == 'eventFilterVhcGsm') {
if (State.eventFilterVhcGsm) {
window.dispatchEvent(State.eventFilterVhcGsm);
if (cb) cb();
}
} else if (type == 'eventFilterVhcZone') {
if (State.eventFilterVhcZone) {
window.dispatchEvent(State.eventFilterVhcZone);
if (cb) cb();
}
}
},
hideLayer: function(type = 'all', cb = null) {
if (type == 'all') {
if (State.eventHideAllTruck) window.dispatchEvent(State.eventHideAllTruck);
if (cb) cb();
} else if (type == 'eventHideTruckNotSelected') {
if (State.eventHideTruckNotSelected) {
if (State.eventHideTruckNotSelected) {
window.dispatchEvent(State.eventHideTruckNotSelected);
if (cb) cb();
}
}
} else if (type == 'eventHideAllTruck') {
if (State.eventHideAllTruck) {
if (State.eventHideAllTruck) {
window.dispatchEvent(State.eventHideAllTruck);
if (cb) cb();
}
}
}
},
};
const Menu = {
activate: function() {
$('.select2').select2();
$('#openRightSideBar1').on('click', function() {
$('#rightSideBar1').removeClass('d-none');
$('#rightSideBar1').addClass('d-block');
$(this).removeClass('d-block');
$(this).addClass('d-none');
Leaflet.map.invalidateSize();
})
$('#closeRightSideBar1').on('click', function() {
$('#rightSideBar1').addClass('d-none');
// if (Wrapper.checkIsMobileDevice()) {
// $('#openLeftSideBar1Mobile').removeClass('d-none');
// $('#openLeftSideBar1Mobile').addClass('d-block');
// }
$('#openRightSideBar1').removeClass('d-none');
$('#openRightSideBar1').addClass('d-block');
$('#rightSideBar2').addClass('d-none');
Leaflet.map.invalidateSize();
})
$('#openLeftSideBar1Mobile').on('click', function() {
Zone.bundleGetListZones(true);
$('#leftSideBar1').removeClass('d-none');
$('#leftSideBar1').addClass('d-block');
$(this).removeClass('d-block');
$(this).addClass('d-none');
Leaflet.map.invalidateSize();
});
$('#closeRightSideBar2').on('click', function() {
$('#rightSideBar2').addClass('d-none');
Leaflet.map.invalidateSize();
State.inShowVid = null;
Leaflet.clearLayer('eventAboutTruck');
Trucks.bundleGetListTrucks(true);
})
$('#openLeftSideBar1').on('click', function() {
Zone.bundleGetListZones(true);
$('#leftSideBar1').removeClass('d-none');
$('#leftSideBar1').addClass('d-block');
$(this).removeClass('d-block');
$(this).addClass('d-none');
Leaflet.map.invalidateSize();
})
$('#closeLeftSideBar1').on('click', function() {
Zone.bundleGetListZones(false);
$('#leftSideBar1').addClass('d-none');
if (Wrapper.checkIsMobileDevice()) {
$('#openLeftSideBar1Mobile').removeClass('d-none');
$('#openLeftSideBar1Mobile').addClass('d-block');
} else {
$('#openLeftSideBar1').removeClass('d-none');
$('#openLeftSideBar1').addClass('d-block');
}
Leaflet.map.invalidateSize();
})
$('#listZone').on('click', '.zone-item', function(e) {
$('#leftSideBar2').removeClass('d-none');
$('#leftSideBar2').addClass('d-block');
});
$('#closeLeftSideBar2').on('click', function() {
$('#leftSideBar2').addClass('d-none');
Leaflet.map.invalidateSize();
})
$('#selectFiter').on('select2:select', function(e) {
Menu.showViewDetailVehicle($(this).val());
});
Menu.showViewDetailVehicle(State.stts_filterDetail.vehicles);
Menu.eventListVehicle();
Menu.eventListMovement();
Menu.eventListZone();
Menu.eventFilter();
Menu.eventFilterHistoryDate();
},
showViewDetailVehicle: async function(type) {
if (type == State.stts_filterDetail.vehicles) { // vehicles
$('#infoVehicles').removeClass('d-none');
$('#infoVehicles').addClass('d-block');
$('#infoDriver').addClass('d-none');
$('#infoJob').addClass('d-none');
$('#infoMovement').addClass('d-none');
} else if (type == State.stts_filterDetail.driver) { // driver
$('#infoVehicles').addClass('d-none');
$('#infoDriver').removeClass('d-none');
$('#infoDriver').addClass('d-block');
$('#infoJob').addClass('d-none');
$('#infoMovement').addClass('d-none');
} else if (type == State.stts_filterDetail.assignJob) { // assign job
$('#infoVehicles').addClass('d-none');
$('#infoDriver').addClass('d-none');
$('#infoJob').removeClass('d-none');
$('#infoJob').addClass('d-block');
$('#infoMovement').addClass('d-none');
} else if (type == State.stts_filterDetail.lastMove) { // last movement
$('#infoVehicles').addClass('d-none');
// $('#infoDriver').addClass('d-none');
$('#infoJob').addClass('d-none');
$('#infoMovement').removeClass('d-none');
$('#infoMovement').addClass('d-block');
// if (State.inShowVid) {
// let cache = !(State.inShowVid != State.loadedLastMoveVid);
// Trucks.bundleShowRouteTruck(cache); // jika data yang diload sebelumnya beda, maka tidak mengambil dari cache
// }
Menu.clearListMovements();
}
},
eventListVehicle: function() {
$('#listTrucks').on('click', '.vhc-item', async function(e) {
let clicked = $(e.target)
let vid = clicked.closest('.vhc-item').data('vid');
if (Trucks.lists) {
for (let i = 0; i < Trucks.lists.length; i++) {
if (Trucks.lists[i].vid == vid) {
Trucks.showDetailGeneral(Trucks.lists[i]);
Leaflet.hideLayer('eventHideTruckNotSelected');
Leaflet.clearLayer('eventRemoveRouteStartEnd', async function() {
await Trucks.bundleGetListTrucks(true);
setTimeout(() => {
Leaflet.hideLayer('eventHideTruckNotSelected');
}, State.delay_hideTruckNotSelected);
});
Leaflet.clearLayer('eventRemoveDetailPlotMovement');
$('#selectFiter').val(State.stts_filterDetail.vehicles).trigger('change');
$('#selectFiter').val(State.stts_filterDetail.vehicles).trigger('select2:select');
$('#rightSideBar2').removeClass('d-none');
if (Trucks.lists[i]?.lst_lat == null || Trucks.lists[i]?.lst_lng == null) {
Helper.toast('Warning', 'just now',
`Last location for this vehicle not found\n${Trucks.lists[i].nopol1} ${Trucks.lists[i].nopol2} ${Trucks.lists[i].nopol3}`
);
continue;
}
// Leaflet.map.fitBounds([
// [Trucks.lists[i].lst_lat, Trucks.lists[i].lst_lng],
// ]);
if (Leaflet.map.getZoom() <= 14) {
Leaflet.map.setView([Trucks.lists[i].lst_lat, Trucks.lists[i].lst_lng],
14);
} else {
Leaflet.map.setView([Trucks.lists[i].lst_lat, Trucks.lists[i].lst_lng]);
}
}
}
}
});
},
showToListMovement: function(obj) {
let arrIdx = Helper.getIndexReversedSequence(obj.key_index - 1, Trucks.last_move.length - 1);
$('#infoMove-plots').append(`
<a href="#" class="plotMove-item" data-obj="${window.btoa( encodeURIComponent( JSON.stringify(obj) ) )}">
<li class="list-group-item p-1 px-2">
<p class="text-bold mb-0">${arrIdx + 1}</p>
<p class="text-bold mb-0">Time: ${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}</p>
<p class="text-muted mb-0">${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}</p>
<p class="text-muted mb-2">${Helper.shortenText(decodeURIComponent(obj?.fulladdress || 'address'), 255)}</p>
<p class="mb-0">Current speed: ${Number(obj.speed)}km/h</p>
</li>
</a>
`);
},
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);
})
},
createMarkerDetailPlotMovement: function(tr, opt = {}) {
Leaflet.clearLayer('eventRemoveDetailPlotMovement');
let marker = Leaflet.addMarkers({
lat: tr.latitude,
lng: tr.longitude,
// label: `<b>${tr.key_index}</b><br>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}<br>${moment.unix(tr?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof tr.lst_speed != 'undefined') ? tr.lst_speed : '0'}<br>${tr.latitude},${tr.longitude}<br>${decodeURIComponent(tr?.fulladdress || 'address')}`,
label: `<b>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}</b><br>${moment.unix(tr?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(tr?.fulladdress || 'address')}.<br><br>Current speed: ${tr?.speed}km/h`,
//label: `<b>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}</b><br>${moment.unix(tr?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(tr?.fulladdress || 'address')}.<br><br>Current speed: ${tr?.speed}km/h`,
options: {
// icon: Icon.destination()
}
});
marker.openPopup();
let curr_zoom = Leaflet.map.getZoom();
if (opt.nozoom) {
Leaflet.map.setView([tr.latitude, tr.longitude], curr_zoom);
} else {
if (curr_zoom <= 16) {
Leaflet.map.setView([tr.latitude, tr.longitude], 16);
} else {
Leaflet.map.setView([tr.latitude, tr.longitude], curr_zoom);
}
}
// remove marker, circle, event listener and all about this marker
State.eventRemoveDetailPlotMovement = new CustomEvent('eventRemoveDetailPlotMovement', {
marker,
});
window.addEventListener('eventRemoveDetailPlotMovement', function handler(e) {
marker.removeEventListener('click');
marker.remove();
e.currentTarget.removeEventListener(e.type,
handler); // window.removeEventListener('remove', this.handler, true);
State.eventRemoveDetailPlotMovement = null;
});
},
clearListMovements: function() {
$('#infoMove-plots').html('');
},
eventListZone: function() {
$('#listZone').on('click', '.zone-item', function(e) {
let clicked = $(e.target)
let zid = clicked.closest('.zone-item').data('zid');
if (Zone.lists) {
for (let i = 0; i < Zone.lists.length; i++) {
if (Zone.lists[i].id == zid) {
Zone.showDetailGeneral(Zone.lists[i]);
let boundary_latlngs = JSON.parse(Zone.lists[i].boundary_latlngs);
let fitBounds = [];
for (let row of boundary_latlngs) {
let corner = L.latLng(row.lat, row.lng);
fitBounds.push(L.latLngBounds(corner, corner));
}
Leaflet.map.fitBounds(fitBounds);
// if circle
// if (Leaflet.map.getZoom() <= 14) {
// Leaflet.map.setView([Zone.lists[i].lst_lat, Zone.lists[i].lst_lng],
// 14)
// }
}
}
}
});
$('#clearZone').on('click', function() {
Leaflet.clearLayer('eventRemoveListZones', null);
});
},
eventFilter: function() {
$('#filterVhcMarker').on('click', function() {
Leaflet.filterLayer('eventFilterPopupVhcMarker');
});
$('#filterVhcGps').on('click', function() {
Leaflet.filterLayer('eventFilterVhcGps');
});
$('#filterVhcGsm').on('click', function() {
Leaflet.filterLayer('eventFilterVhcGsm');
});
$('#filterVhcZone').on('click', function() {
Leaflet.filterLayer('eventFilterVhcZone');
});
// searching
let timeoutFilterVhcSearch = null;
$('#filterVhcSearch').on('keyup', function() {
clearTimeout(timeoutFilterVhcSearch);
timeoutFilterVhcSearch = setTimeout(() => {
Menu.handlerFilterVhcSearch($('#filterVhcSearch').val());
}, State.delay_typing_front);
});
let timeoutFilterZoneSearch = null;
$('#filterZoneSearch').on('keyup', function() {
clearTimeout(timeoutFilterZoneSearch);
timeoutFilterZoneSearch = setTimeout(() => {
Menu.handlerFilterZoneSearch($('#filterZoneSearch').val());
}, State.delay_typing_front);
});
},
eventFilterHistoryDate: function() {
$('#historySearch').on('click', function(e) {
e.preventDefault();
// console.log("change history date", this.id, this.value);
const value = this.value;
const id = this.id;
if(State[id] == moment(value, "DD-MM-YYYY HH:mm").unix())
return false;
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(
date0,
date1
)
if (!isValid) return false;
// 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();
// Leaflet.clearLayer('eventRemoveRouteStartEnd');
// Trucks.bundleShowRouteTruck(false);
// });
$('#historyStartDate').on('clearFilterHistoryDate', function(e) {
// 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) {
if (State.inShowLastMove) {
Helper.toast('Warning', 'just now', 'Cannot show marker info when see last movement');
return false;
}
// 0=>hidden,1=>nopol,2=>speed,3=>address
let latLng = Leaflet.map.getCenter();
for (let marker of markers) {
let mdata = marker.options.mdata;
if (!State.lastShowVids.includes(mdata.vid)) {
continue;
}
if (State.statusFilterPopupVhcMarker === 0) {
// let content =
// `<div class="bg-color"><b>${mdata.nopol1} ${mdata.nopol2} ${mdata.nopol3}</b></div>`;
// marker.bindTooltip(content);
// marker.closePopup();
} else if (State.statusFilterPopupVhcMarker === 1) {
// let content =
// `<div class="bg-color"><b>${mdata.nopol1} ${mdata.nopol2} ${mdata.nopol3}</b></div>`;
let content = `<b>${mdata.nopol1} ${mdata.nopol2} ${mdata.nopol3}</b>`;
if (mdata?.ord_pck_ktname && mdata?.ord_drop_ktname) {
content += `<div style="margin-bottom:10px;"><strong>${mdata?.ord_c_pt_name}</strong></div>`;
content += `<div style="margin-bottom:0;">Origin</div>`;
content += `<div style="margin-bottom:0.25rem;"><strong>${mdata?.ord_pck_ktname}</strong></div>`;
content += `<div style="margin-bottom:0;">Destination</div>`;
content += `<div style="margin-bottom:0;"><strong>${mdata?.ord_drop_ktname}</strong></div>`;
}
marker.setPopupContent(content);
marker.bindTooltip(content);
marker.openPopup();
} else if (State.statusFilterPopupVhcMarker === 2) {
// cara lama
// let speedOrIdle = (typeof mdata.lst_speed != 'undefined') ? mdata.lst_speed : 0;
// if (mdata.stts_engine == State.stts_engine.idling) speedOrIdle = 0;
// if (speedOrIdle === 0) {
// let idlingDur = Wrapper.calcIdlingDur(mdata?.lst_idle_at, mdata?.lst_speed);
// if (idlingDur.unit == 'hour') {
// let min = idlingDur.dur * 60;
// if (idlingDur.dur <= 1) {
// speedOrIdle = ` <= ${min.toFixed(0)} min`;
// } else if (idlingDur.dur > 6) {
// speedOrIdle = ' > 6 hr';
// } else if (idlingDur.dur > 4) {
// speedOrIdle = ' > 4 hr';
// } else if (idlingDur.dur > 2) {
// speedOrIdle = ' > 2 hr';
// } else if (idlingDur.dur > 1) {
// speedOrIdle = ' > 1 hr';
// }
// } else if (idlingDur.unit == 'min') {
// let hr = idlingDur.dur / 60;
// if (hr <= 1) {
// speedOrIdle = ` <= ${idlingDur.dur} min`;
// } else if (hr > 6) {
// speedOrIdle = ' > 6 hr';
// } else if (hr > 4) {
// speedOrIdle = ' > 4 hr';
// } else if (hr > 2) {
// speedOrIdle = ' > 2 hr';
// } else if (hr > 1) {
// speedOrIdle = ' > 1 hr';
// }
// }
// } else {
// speedOrIdle += ' Kph';
// }
// differentation minute / hour
function getDiff(last) {
let now = moment(); // as start
let end = moment.unix(last ?? now.unix()); // as end
let duration = moment.duration(end.diff(now));
let diff = duration.asMinutes() * -1;
let unit = 'min';
// parsing to hour
if (diff > 60) {
diff = diff / 60;
unit = 'hr';
}
return {
duration,
diff,
unit,
}
}
let speedOrIdle = '-';
let a = getDiff(mdata.lst_idle_at);
let diff = a.diff.toFixed(0);
let unit = a.unit;
if (mdata.stts_engine == State.stts_engine.moving) {
speedOrIdle = `${mdata.lst_speed} Kph`;
if (typeof mdata.lst_speed == 'undefined' || mdata.lst_speed == 0 || mdata.lst_speed == null) {
speedOrIdle = `> ${diff} ${unit}`;
}
} else if (mdata.stts_engine == State.stts_engine.idling) {
speedOrIdle = `> ${diff} ${unit}`;
} else if (mdata.stts_engine == State.stts_engine.stoping) {
a = getDiff(mdata.lst_stop_at);
diff = a.diff.toFixed(0);
unit = a.unit;
speedOrIdle = `> ${diff} ${unit}`;
}
let content = `<div class="bg-color"><b>${speedOrIdle}</b></div>`;
marker.setPopupContent(content);
marker.bindTooltip(content);
marker.openPopup();
} else if (State.statusFilterPopupVhcMarker === 3) {
let content =
`<div class="bg-color"><b>${Helper.shortenText(decodeURIComponent(mdata?.lst_fulladdress || 'address'), 100)}</b></div>`;
marker.setPopupContent(content);
marker.bindTooltip(content);
marker.openPopup();
}
Leaflet.map.setView(latLng);
}
if (State.statusFilterPopupVhcMarker === 3) {
State.statusFilterPopupVhcMarker = 1;
} else {
State.statusFilterPopupVhcMarker += 1;
}
},
handlerFilterVhcGps: function(markers) {
if (State.inShowVid) {
Helper.toast('Warning', 'just now', 'Cannot filter when see detail vehicle');
return false;
}
// 0=>all,1=>active,2=>not
if (State.statusFilterVhcGps === 2) {
State.statusFilterVhcGps = 0;
} else {
State.statusFilterVhcGps += 1;
}
State.lastShowVids = [];
function show(marker, mdata) {
marker.setOpacity(1);
$(`.vhc-item[data-vid="${mdata.vid}"]`).removeClass('d-none');
State.lastShowVids.push(mdata.vid);
}
function hide(marker, mdata) {
marker.setOpacity(0);
$(`.vhc-item[data-vid="${mdata.vid}"]`).addClass('d-none');
}
function validate(marker, mdata) {
if ((State.statusFilterVhcGsm === 1 || State.statusFilterVhcGsm === 2) && (State.statusFilterVhcZone === 1 || State.statusFilterVhcZone === 2)) {
if (Menu.isFilterVhc_Gsm(mdata) && Menu.isFilterVhc_Zone(mdata)) {
show(marker, mdata);
}
} else if (State.statusFilterVhcGsm === 1 || State.statusFilterVhcGsm === 2) {
if (Menu.isFilterVhc_Gsm(mdata)) {
show(marker, mdata);
}
} else if (State.statusFilterVhcZone === 1 || State.statusFilterVhcZone === 2) {
if (Menu.isFilterVhc_Zone(mdata)) {
show(marker, mdata);
}
} else {
show(marker, mdata);
}
}
let latLng = Leaflet.map.getCenter();
let c_vhc_gps = 0;
for (let marker of markers) {
let mdata = marker.options.mdata;
if (State.statusFilterVhcGps === 0) {
c_vhc_gps += 1;
validate(marker, mdata);
$($('#filterVhcGps > span')[0]).removeClass('text-danger text-success').addClass(
'text-muted');
$('#filterVhcGps').attr('data-bs-original-title', 'Filter vehicle GPS');
if (State.isShowToltipFilterVhcGps) $('#filterVhcGps').tooltip('show');
} else if (State.statusFilterVhcGps === 1) {
if (mdata.stts_gps == State.stts_gps.active) {
c_vhc_gps += 1;
validate(marker, mdata);
} else {
hide(marker, mdata);
}
$($('#filterVhcGps > span')[0]).removeClass('text-muted text-danger').addClass(
'text-success');
$('#filterVhcGps').attr('data-bs-original-title', 'Filter vehicle GPS Active');
if (State.isShowToltipFilterVhcGps) $('#filterVhcGps').tooltip('show');
} else if (State.statusFilterVhcGps === 2) {
if (mdata.stts_gps != State.stts_gps.active) {
c_vhc_gps += 1;
validate(marker, mdata);
} else {
hide(marker, mdata);
}
$($('#filterVhcGps > span')[0]).removeClass('text-success text-muted').addClass(
'text-danger');
$('#filterVhcGps').attr('data-bs-original-title', 'Filter vehicle GPS Inactive');
if (State.isShowToltipFilterVhcGps) $('#filterVhcGps').tooltip('show');
}
Leaflet.map.setView(latLng);
}
$('#c_vhc_gps').text(c_vhc_gps);
State.lastStatusFilterVhcGps = State.statusFilterVhcGps;
},
handlerFilterVhcGsm: function(markers) {
if (State.inShowVid) {
Helper.toast('Warning', 'just now', 'Cannot filter when see detail vehicle');
return false;
}
// 0=>all,1=>active,2=>not
if (State.statusFilterVhcGsm === 2) {
State.statusFilterVhcGsm = 0;
} else {
State.statusFilterVhcGsm += 1;
}
State.lastShowVids = [];
function show(marker, mdata) {
marker.setOpacity(1);
$(`.vhc-item[data-vid="${mdata.vid}"]`).removeClass('d-none');
State.lastShowVids.push(mdata.vid);
}
function hide(marker, mdata) {
marker.setOpacity(0);
$(`.vhc-item[data-vid="${mdata.vid}"]`).addClass('d-none');
}
function validate(marker, mdata) {
if ((State.statusFilterVhcGps === 1 || State.statusFilterVhcGps === 2) && (State.statusFilterVhcZone === 1 || State.statusFilterVhcZone === 2)) {
if (Menu.isFilterVhc_Gps(mdata) && Menu.isFilterVhc_Zone(mdata)) {
show(marker, mdata);
}
} else if (State.statusFilterVhcGps === 1 || State.statusFilterVhcGps === 2) {
if (Menu.isFilterVhc_Gps(mdata)) {
show(marker, mdata);
}
} else if (State.statusFilterVhcZone === 1 || State.statusFilterVhcZone === 2) {
if (Menu.isFilterVhc_Zone(mdata)) {
show(marker, mdata);
}
} else {
show(marker, mdata);
}
}
let latLng = Leaflet.map.getCenter();
let c_vhc_gsm = 0;
for (let marker of markers) {
let mdata = marker.options.mdata;
if (State.statusFilterVhcGsm === 0) {
c_vhc_gsm += 1;
validate(marker, mdata);
$($('#filterVhcGsm > span')[0]).removeClass('text-danger text-success').addClass(
'text-muted');
$('#filterVhcGsm').attr('data-bs-original-title', 'Filter vehicle GSM');
if (State.isShowToltipFilterVhcGsm) $('#filterVhcGsm').tooltip('show');
} else if (State.statusFilterVhcGsm === 1) {
if (mdata.stts_gsm >= State.stts_gsm.bad_signal) {
if (mdata.lst_heartbeat > 0) {
c_vhc_gsm += 1;
validate(marker, mdata);
} else {
hide(marker, mdata);
}
} else {
hide(marker, mdata);
}
$($('#filterVhcGsm > span')[0]).removeClass('text-muted text-danger').addClass(
'text-success');
$('#filterVhcGsm').attr('data-bs-original-title', 'Filter vehicle GSM Active');
if (State.isShowToltipFilterVhcGsm) $('#filterVhcGsm').tooltip('show');
} else if (State.statusFilterVhcGsm === 2) {
if (mdata.stts_gsm <= State.stts_gsm.no_signal) {
c_vhc_gsm += 1;
validate(marker, mdata);
} else {
if (mdata.lst_heartbeat < 1) {
c_vhc_gsm += 1;
validate(marker, mdata);
} else {
hide(marker, mdata);
}
}
$($('#filterVhcGsm > span')[0]).removeClass('text-success text-muted').addClass(
'text-danger');
$('#filterVhcGsm').attr('data-bs-original-title', 'Filter vehicle GSM No Signal');
if (State.isShowToltipFilterVhcGsm) $('#filterVhcGsm').tooltip('show');
}
Leaflet.map.setView(latLng);
}
$('#c_vhc_gsm').text(c_vhc_gsm);
State.lastStatusFilterVhcGsm = State.statusFilterVhcGsm;
},
handlerFilterVhcZone: function(markers) {
if (State.inShowVid) {
Helper.toast('Warning', 'just now', 'Cannot filter when see detail vehicle');
return false;
}
// 0=>all,1=>inside,2=>outside
if (State.statusFilterVhcZone === 2) {
State.statusFilterVhcZone = 0;
} else {
State.statusFilterVhcZone += 1;
}
State.lastShowVids = [];
function show(marker, mdata) {
marker.setOpacity(1);
$(`.vhc-item[data-vid="${mdata.vid}"]`).removeClass('d-none');
State.lastShowVids.push(mdata.vid);
}
function hide(marker, mdata) {
marker.setOpacity(0);
$(`.vhc-item[data-vid="${mdata.vid}"]`).addClass('d-none');
}
function validate(marker, mdata) {
if ((State.statusFilterVhcGps === 1 || State.statusFilterVhcGps === 2) && (State.statusFilterVhcGsm === 1 || State.statusFilterVhcGsm === 2)) {
if (Menu.isFilterVhc_Gps(mdata) && Menu.isFilterVhc_Gsm(mdata)) {
show(marker, mdata);
}
} else if (State.statusFilterVhcGps === 1 || State.statusFilterVhcGps === 2) {
if (Menu.isFilterVhc_Gps(mdata)) {
show(marker, mdata);
}
} else if (State.statusFilterVhcGsm === 1 || State.statusFilterVhcGsm === 2) {
if (Menu.isFilterVhc_Gsm(mdata)) {
show(marker, mdata);
}
} else {
show(marker, mdata);
}
}
let latLng = Leaflet.map.getCenter();
let c_vhc_zone = 0;
for (let marker of markers) {
let mdata = marker.options.mdata;
if (State.statusFilterVhcZone === 0) {
c_vhc_zone += 1;
validate(marker, mdata);
$($('#filterVhcZone > span')[0]).removeClass('text-danger text-success').addClass(
'text-muted');
$('#filterVhcZone').attr('data-bs-original-title', 'Filter vehicle inside & outside zone');
if (State.isShowToltipFilterVhcZone) $('#filterVhcZone').tooltip('show');
} else if (State.statusFilterVhcZone === 1) {
if (mdata.inside_zones != null) {
c_vhc_zone += 1;
validate(marker, mdata);
} else {
hide(marker, mdata);
}
$($('#filterVhcZone > span')[0]).removeClass('text-muted text-danger').addClass(
'text-success');
$('#filterVhcZone').attr('data-bs-original-title', 'Filter vehicle inside zone');
if (State.isShowToltipFilterVhcZone) $('#filterVhcZone').tooltip('show');
} else if (State.statusFilterVhcZone === 2) {
if (mdata.inside_zones == null) {
c_vhc_zone += 1;
validate(marker, mdata);
} else {
hide(marker, mdata);
}
$($('#filterVhcZone > span')[0]).removeClass('text-success text-muted').addClass(
'text-danger');
$('#filterVhcZone').attr('data-bs-original-title', 'Filter vehicle outside zone');
if (State.isShowToltipFilterVhcZone) $('#filterVhcZone').tooltip('show');
}
Leaflet.map.setView(latLng);
}
$('#c_vhc_zone').text(c_vhc_zone);
State.lastStatusFilterVhcZone = State.statusFilterVhcZone;
},
handlerFilterVhcSearch: function(search) {
let vhcItems = $('#listTrucks').find('.vhc-item');
for (let item of vhcItems) {
let vid = $(item).data('vid');
let textNopol = $($(item).find('.textNopol')[0]).text();
let textAddr = $($(item).find('.textAddr')[0]).text();
if (textNopol.toLowerCase().indexOf(search.toLowerCase()) > -1) {
$(item).removeClass('d-none');
} else if (textAddr.toLowerCase().indexOf(search.toLowerCase()) > -1) {
$(item).removeClass('d-none');
} else {
$(item).addClass('d-none');
}
}
},
handlerFilterZoneSearch: function(search) {
let zoneItems = $('#listZone').find('.zone-item');
for (let item of zoneItems) {
let zid = $(item).data('zid');
let textZoneName = $($(item).find('.textZoneName')[0]).text();
let textZoneType = $($(item).find('.textZoneType')[0]).text();
if (textZoneName.toLowerCase().indexOf(search.toLowerCase()) > -1) {
$(item).removeClass('d-none');
} else if (textZoneType.toLowerCase().indexOf(search.toLowerCase()) > -1) {
$(item).removeClass('d-none');
} else {
$(item).addClass('d-none');
}
}
},
isFilterVhc_GpsGsmZone: function(truck) {
// if return false no filter, true there filter
if (Menu.isFilterVhc_Gps(truck)) return true;
if (Menu.isFilterVhc_Gsm(truck)) return true;
if (Menu.isFilterVhc_Zone(truck)) return true;
return false;
},
isFilterVhc_Gps: function(truck) {
// if return false no filter, true there filter
if (State.statusFilterVhcGps === 0) {} else if (State.statusFilterVhcGps === 1) {
if (truck.stts_gps == State.stts_gps.active) return true;
} else if (State.statusFilterVhcGps === 2) {
if (truck.stts_gps != State.stts_gps.active) return true;
}
return false;
},
isFilterVhc_Gsm: function(truck) {
// if return false no filter, true there filter
if (State.statusFilterVhcGsm === 0) {} else if (State.statusFilterVhcGsm === 1) {
if (truck.stts_gsm >= State.stts_gsm.bad_signal) return true;
} else if (State.statusFilterVhcGsm === 2) {
if (truck.stts_gsm <= State.stts_gsm.no_signal) return true;
}
return false;
},
isFilterVhc_Zone: function(truck) {
// if return false no filter, true there filter
if (State.statusFilterVhcZone === 0) {} else if (State.statusFilterVhcZone === 1) {
if (truck.inside_zones != null) return true;
} else if (State.statusFilterVhcZone === 2) {
if (truck.inside_zones == null) return true;
}
return false;
},
isLastFilterVhc_Gps: function(truck) {
// if return false no filter, true there filter
if (State.lastStatusFilterVhcGps === 0) {} else if (State.lastStatusFilterVhcGps === 1) {
if (truck.stts_gps == State.stts_gps.active) return true;
} else if (State.lastStatusFilterVhcGps === 2) {
if (truck.stts_gps != State.stts_gps.active) return true;
}
return false;
},
isLastFilterVhc_Gsm: function(truck) {
// if return false no filter, true there filter
if (State.lastStatusFilterVhcGsm === 0) {} else if (State.lastStatusFilterVhcGsm === 1) {
if (truck.stts_gsm >= State.stts_gsm.bad_signal) return true;
} else if (State.lastStatusFilterVhcGsm === 2) {
if (truck.stts_gsm <= State.stts_gsm.no_signal) return true;
}
return false;
},
isLastFilterVhc_Zone: function(truck) {
// if return false no filter, true there filter
if (State.lastStatusFilterVhcZone === 0) {} else if (State.lastStatusFilterVhcZone === 1) {
if (truck.inside_zones != null) return true;
} else if (State.lastStatusFilterVhcZone === 2) {
if (truck.inside_zones == null) return true;
}
return false;
},
}
const Trucks = {
lists: null,
last_move: null,
activate: function() {
Trucks.bundleGetListTrucks(false);
Trucks.event();
},
event: function() {
setInterval(async () => {
if (State.inShowLastMove) return false;
await Trucks.bundleGetListTrucks(false);
if (State.inShowVid) {
setTimeout(() => {
Leaflet.hideLayer('eventHideTruckNotSelected');
}, State.delay_hideTruckNotSelected);
}
State.loadedLastMoveVid = null;
if ($('#selectFiter').val() == State.stts_filterDetail.vehicles) {
setTimeout(() => {
if (Trucks.lists) {
for (let i = 0; i < Trucks.lists.length; i++) {
if (Trucks.lists[i].vid == State.inShowVid) {
Trucks.showDetailGeneral(Trucks.lists[i]);
}
}
}
}, 1000);
}
}, State.delay_auto_refresh);
},
bundleGetListTrucks: async function(cache = false) {
Leaflet.clearLayer('eventRemoveListTrucks');
Trucks.lists = await Trucks.getListTrucks(cache);
Trucks.showToLists(Trucks.lists);
Trucks.showListsToMap(Trucks.lists);
},
getListTrucks: async function(cache = false) {
if (cache) {
if (Trucks.lists == null) {
return (await Trucks.reqListTrucks()).data;
} else {
return Trucks.lists;
}
}
return (await Trucks.reqListTrucks()).data;
},
reqListTrucks: function(params) {
return new Promise((resolve, reject) => {
let url = "{{ route('api_list_currect_track_vhc') }}?cptid=" + AppState.current_company;
if (State.ord_code) {
url += "&ord_code=" + State.ord_code;
}
$.ajax({
url,
method: 'GET',
crossDomain: true,
processData: true,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
},
data: params,
success: (data, textStatus, jqXHR) => {
if (data.meta.type != 'success') {
resolve({
type: 'fail',
data: null,
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
resolve({
type: 'success',
data: data.data,
});
},
error: (jqXHR, textStatus, error) => {
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Cannot get lists vehicles');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error',
data: null,
});
}
})
});
},
showToLists: function(trucks) {
$('#listTrucks').html('');
let str = '',
refilter = '';
let c_vhc_gps = 0,
c_vhc_gsm = 0,
c_vhc_zone = 0;
State.statusFilterVhcGps = (State.lastStatusFilterVhcGps) ? State.lastStatusFilterVhcGps : State.statusFilterVhcGps;
State.statusFilterVhcGsm = (State.lastStatusFilterVhcGsm) ? State.lastStatusFilterVhcGsm : State.statusFilterVhcGsm;
State.statusFilterVhcZone = (State.lastStatusFilterVhcZone) ? State.lastStatusFilterVhcZone : State.statusFilterVhcZone;
for (let i = 0; i < trucks.length; i++) {
// refilter list trucks
refilter = 'd-none';
if (State.lastStatusFilterVhcGps !== 0 || State.lastStatusFilterVhcGsm !== 0 || State.lastStatusFilterVhcZone !== 0) {
c_vhc_gps = Number($('#c_vhc_gps').text());
c_vhc_gsm = Number($('#c_vhc_gsm').text());
c_vhc_zone = Number($('#c_vhc_zone').text());
if (State.lastStatusFilterVhcGps !== 0) {
if ((State.lastStatusFilterVhcGsm === 1 || State.lastStatusFilterVhcGsm === 2) && (State.lastStatusFilterVhcZone === 1 || State.lastStatusFilterVhcZone === 2)) {
if (Menu.isLastFilterVhc_Gps(trucks[i]) && Menu.isLastFilterVhc_Gsm(trucks[i]) && Menu.isLastFilterVhc_Zone(trucks[i])) {
refilter = '';
// c_vhc_gps += 1;
// c_vhc_gsm += 1;
// c_vhc_zone += 1;
}
} else if (State.lastStatusFilterVhcGsm === 1 || State.lastStatusFilterVhcGsm === 2) {
if (Menu.isLastFilterVhc_Gps(trucks[i]) && Menu.isLastFilterVhc_Gsm(trucks[i])) {
refilter = '';
// c_vhc_gps += 1;
// c_vhc_gsm += 1;
}
} else if (State.lastStatusFilterVhcZone === 1 || State.lastStatusFilterVhcZone === 2) {
if (Menu.isLastFilterVhc_Gps(trucks[i]) && Menu.isLastFilterVhc_Zone(trucks[i])) {
refilter = '';
// c_vhc_gps += 1;
// c_vhc_zone += 1;
}
} else {
if (Menu.isLastFilterVhc_Gps(trucks[i])) {
refilter = '';
// c_vhc_gps += 1;
// c_vhc_gsm += 1;
// c_vhc_zone += 1;
} else {
// c_vhc_gsm += 1;
// c_vhc_zone += 1;
}
}
} else if (State.lastStatusFilterVhcGsm !== 0) {
if ((State.lastStatusFilterVhcGps === 1 || State.lastStatusFilterVhcGps === 2) && (State.lastStatusFilterVhcZone === 1 || State.lastStatusFilterVhcZone === 2)) {
if (Menu.isLastFilterVhc_Gsm(trucks[i]) && Menu.isLastFilterVhc_Gps(trucks[i]) && Menu.isLastFilterVhc_Zone(trucks[i])) {
refilter = '';
// c_vhc_gsm += 1;
// c_vhc_gps += 1;
// c_vhc_zone += 1;
}
} else if (State.lastStatusFilterVhcGps === 1 || State.lastStatusFilterVhcGps === 2) {
if (Menu.isLastFilterVhc_Gsm(trucks[i]) && Menu.isLastFilterVhc_Gps(trucks[i])) {
refilter = '';
// c_vhc_gsm += 1;
// c_vhc_gps += 1;
}
} else if (State.lastStatusFilterVhcZone === 1 || State.lastStatusFilterVhcZone === 2) {
if (Menu.isLastFilterVhc_Gsm(trucks[i]) && Menu.isLastFilterVhc_Zone(trucks[i])) {
refilter = '';
// c_vhc_gsm += 1;
// c_vhc_zone += 1;
}
} else {
if (Menu.isLastFilterVhc_Gsm(trucks[i])) {
refilter = '';
// c_vhc_gsm += 1;
// c_vhc_gps += 1;
// c_vhc_zone += 1;
} else {
// c_vhc_gps += 1;
// c_vhc_zone += 1;
}
}
} else if (State.lastStatusFilterVhcZone !== 0) {
if ((State.lastStatusFilterVhcGps === 1 || State.lastStatusFilterVhcGps === 2) && (State.lastStatusFilterVhcGsm === 1 || State.lastStatusFilterVhcGsm === 2)) {
if (Menu.isLastFilterVhc_Zone(trucks[i]) && Menu.isLastFilterVhc_Gps(trucks[i]) && Menu.isLastFilterVhc_Gsm(trucks[i])) {
refilter = '';
// c_vhc_zone += 1;
// c_vhc_gps += 1;
// c_vhc_gsm += 1;
}
} else if (State.lastStatusFilterVhcGps === 1 || State.lastStatusFilterVhcGps === 2) {
if (Menu.isLastFilterVhc_Zone(trucks[i]) && Menu.isLastFilterVhc_Gps(trucks[i])) {
refilter = '';
// c_vhc_zone += 1;
// c_vhc_gps += 1;
}
} else if (State.lastStatusFilterVhcGsm === 1 || State.lastStatusFilterVhcGsm === 2) {
if (Menu.isLastFilterVhc_Zone(trucks[i]) && Menu.isLastFilterVhc_Gsm(trucks[i])) {
refilter = '';
// c_vhc_zone += 1;
// c_vhc_gsm += 1;
}
} else {
if (Menu.isLastFilterVhc_Zone(trucks[i])) {
refilter = '';
// c_vhc_zone += 1;
// c_vhc_gps += 1;
// c_vhc_gsm += 1;
} else {
// c_vhc_gps += 1;
// c_vhc_gsm += 1;
}
}
}
} else {
// without filter
refilter = '';
c_vhc_gps += 1;
c_vhc_gsm += 1;
c_vhc_zone += 1;
State.lastShowVids.push(trucks[i].vid);
}
// list trucks
// <img src="${State.storage_lara}${trucks[i].fvhc_img}" class="img-fluid" alt="">
// <img src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png" class="img-fluid" alt="">
// <p class="text-muted mb-0"> ${(trucks[i]?.lst_city_text || trucks[i]?.lst_state_text || 'address')} - ${(trucks[i]?.lst_postcode || 'postcode')}</p>
str += `
<li class="list-group-item vehicles-list-wrapper p-1 px-2 vhc-item ${refilter}" data-vid="${trucks[i].vid}">
<a href="#" class="text-dark">
<div class="row d-flex align-items-center">
<div class="col-4">
<img src="${State.storage_lara}${trucks[i].fvhc_img}" class="img-fluid thumb-img-small" alt="">
</div>
<div class="col ps-0">
<p class="text-bold mb-0 textNopol">${trucks[i].nopol1} ${trucks[i].nopol2} ${trucks[i].nopol3}</p>
<p class="text-muted mb-0 textAddr">${Helper.shortenText(decodeURIComponent(trucks[i]?.lst_fulladdress || 'address'), 25)}</p>
</div>
</div>
</a>
</li>
`;
}
$('#c_vhc_zone').text(c_vhc_zone);
$('#c_vhc_gsm').text(c_vhc_gsm);
$('#c_vhc_gps').text(c_vhc_gps);
$('#listTrucks').html(str);
},
showListsToMap: function(trucks) {
// let locations = trucks.map((tr) => {
// let at = moment.unix(tr?.lst_loc_crt).format('DD MMM YYYY HH:mm')
// return {
// lat: tr.lst_lat,
// lng: tr.lst_lng,
// label: `<b>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}</b><br>${at}<br>${tr.lst_lat},${tr.lst_lng}`,
// options: {
// mdata: tr,
// },
// };
// });
let locations = [];
for (let i = 0; i < trucks.length; i++) {
if (trucks[i]?.lst_lat == null || trucks[i]?.lst_lng == null) {
continue;
}
let icon_stts_engine = Icon.vechicleIcon(); // moving
if (trucks[i].stts_engine == State.stts_engine.moving) {
icon_stts_engine = Icon.vechicleIcon();
if (trucks[i].lst_speed == 0 || trucks[i].lst_speed == null) {
icon_stts_engine = Icon.vhcIdleIcon();
}
} else if (trucks[i].stts_engine == State.stts_engine.idling) {
icon_stts_engine = Icon.vhcIdleIcon();
} else if (trucks[i].stts_engine == State.stts_engine.stoping) {
icon_stts_engine = Icon.vhcStopIcon();
}
// no updated data more than 1 day
if (trucks[i]?.lst_loc_crt < moment().subtract(24, 'hour').unix()) {
icon_stts_engine = Icon.vhcStopIcon();
}
let templateLabel = `<b>${trucks[i].nopol1} ${trucks[i].nopol2} ${trucks[i].nopol3}</b>`;
if (trucks[i]?.ord_pck_ktname && trucks[i]?.ord_drop_ktname) {
templateLabel += `<div style="margin-bottom:0;"><strong>${trucks[i]?.ord_c_pt_name}</strong></div>`;
templateLabel += `<div style="margin-bottom:0;">Dari</div>`;
templateLabel += `<div style="margin-bottom:0.25rem;"><strong>${trucks[i]?.ord_pck_ktname}</strong></div>`;
templateLabel += `<div style="margin-bottom:0;">Ke</div>`;
templateLabel += `<div style="margin-bottom:0;"><strong>${trucks[i]?.ord_drop_ktname}</strong></div>`;
}
locations.push({
lat: trucks[i].lst_lat,
lng: trucks[i].lst_lng,
// label: `<b>${trucks[i].nopol1} ${trucks[i].nopol2} ${trucks[i].nopol3}</b><br>${moment.unix(trucks[i]?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof trucks[i].lst_speed != 'undefined') ? trucks[i].lst_speed : '0'}<br>${Number(trucks[i].lst_lat).toFixed(5)},${Number(trucks[i].lst_lng).toFixed(6)}<br>${Helper.shortenText(decodeURIComponent(trucks[i]?.lst_fulladdress || 'address'), 25)}`,
label: templateLabel,
options: {
mdata: trucks[i],
icon: icon_stts_engine,
// autoClose: false,
},
});
}
let markers = Leaflet.addMarkers(locations, function(marker) {
Leaflet.eventMarkerClick(marker, function(e) {
let tr = e.target.options.mdata;
$('#selectFiter').val(1).trigger('change');
$('#selectFiter').val(1).trigger('select2:select');
Trucks.showDetailGeneral(tr);
$('#rightSideBar2').removeClass('d-none');
});
});
for (let m of markers) {
if (!State.lastShowVids.includes(m.options.mdata.vid)) {
m.setOpacity(0);
}
}
// filter popup
State.eventFilterPopupVhcMarker = new CustomEvent('eventFilterPopupVhcMarker', {
detail: {
markers,
},
});
function handlerFilterPopupVhcMarker(e) {
Menu.handlerFilterPopupVhcMarker(e.detail.markers);
}
window.addEventListener('eventFilterPopupVhcMarker', handlerFilterPopupVhcMarker);
// filter vehicle gps
State.eventFilterVhcGps = new CustomEvent('eventFilterVhcGps', {
detail: {
markers,
},
});
function handlerFilterVhcGps(e) {
Menu.handlerFilterVhcGps(e.detail.markers);
}
window.addEventListener('eventFilterVhcGps', handlerFilterVhcGps);
// filter vehicle gsm
State.eventFilterVhcGsm = new CustomEvent('eventFilterVhcGsm', {
detail: {
markers,
},
});
function handlerFilterVhcGsm(e) {
Menu.handlerFilterVhcGsm(e.detail.markers);
}
window.addEventListener('eventFilterVhcGsm', handlerFilterVhcGsm);
// filter vehicle zone
State.eventFilterVhcZone = new CustomEvent('eventFilterVhcZone', {
detail: {
markers,
},
});
function handlerFilterVhcZone(e) {
Menu.handlerFilterVhcZone(e.detail.markers);
}
window.addEventListener('eventFilterVhcZone', handlerFilterVhcZone);
// hide all truck
State.eventHideAllTruck = new CustomEvent('eventHideAllTruck', {
detail: {
markers,
},
});
function handlerHideAllTruck(e) {
for (let marker of e.detail.markers) {
marker.setOpacity(0);
}
}
window.addEventListener('eventHideAllTruck', handlerHideAllTruck);
// hide truck not selected
State.eventHideTruckNotSelected = new CustomEvent('eventHideTruckNotSelected', {
detail: {
markers,
},
});
function handlerHideTruckNotSelected(e) {
for (let marker of e.detail.markers) {
if (State.inShowVid == marker.options.mdata.vid) {
marker.setOpacity(1);
continue;
}
marker.setOpacity(0);
}
}
window.addEventListener('eventHideTruckNotSelected', handlerHideTruckNotSelected);
// remove marker, circle, event listener and all about this marker
State.eventRemoveListTrucks = new CustomEvent('eventRemoveListTrucks', {
detail: {
markers,
},
});
window.addEventListener('eventRemoveListTrucks', function handler(e) {
for (let marker of e.detail.markers) {
marker.removeEventListener('click');
marker.removeEventListener('moveend');
marker.remove();
}
e.currentTarget.removeEventListener(e.type,
handler); // window.removeEventListener('remove', this.handler, true);
window.removeEventListener('eventFilterPopupVhcMarker', handlerFilterPopupVhcMarker);
window.removeEventListener('eventFilterVhcGps', handlerFilterVhcGps);
window.removeEventListener('eventFilterVhcGsm', handlerFilterVhcGsm);
window.removeEventListener('eventFilterVhcZone', handlerFilterVhcZone);
window.removeEventListener('eventHideTruckNotSelected', handlerHideTruckNotSelected);
window.removeEventListener('eventHideAllTruck', handlerHideAllTruck);
State.eventRemoveListTrucks = null;
State.statusFilterPopupVhcMarker = 1;
State.eventFilterPopupVhcMarker = null;
State.statusFilterVhcGps = 0;
State.eventFilterVhcGps = null;
State.statusFilterVhcGsm = 0;
State.eventFilterVhcGsm = null;
State.statusFilterVhcZone = 0;
State.eventFilterVhcZone = null;
State.eventHideTruckNotSelected = null;
State.eventHideAllTruck = null;
});
},
showDetailGeneral: function(truck) {
State.inShowVid = truck.vid;
// title
// <img src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png" class="img-fluid" alt="">
// $('#infoVehicles-thumb-md').attr('src',`${State.storage_lara}${truck?.fvhc_img}`);
$('#infoVehicles-thumb-md').attr('src',
`${State.storage_lara}${truck?.fvhc_img}`);
// $('#infoVehicles-thumb-sm').attr('src',`${State.storage_lara}${truck?.fvhc_img}`);
$('#infoVehicles-thumb-sm').attr('src',
`${State.storage_lara}${truck?.fvhc_img}`);
$('#infoVehicles-platno').text(`${truck?.nopol1} ${truck?.nopol2} ${truck?.nopol3}`);
// vehicles
$('#infoVehicles-crt').text(moment.unix(truck?.lst_loc_crt).format('DD MMM YYYY HH:mm'));
// $('#infoVehicles-crt').text(moment.unix(truck?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss'));
// ${(truck?.city_text || truck?.state_text || 'address')} - ${(truck?.postcode || 'postcode')}
if (truck?.ignition == State.stts_ignition.high) {
$('#infoVehicles-ignition').text('ON');
} else {
$('#infoVehicles-ignition').text('OFF');
}
if (truck?.stts_engine == State.stts_engine.moving) {
$('#infoVehicles-engineStatus').text('MOVING');
if (truck?.lst_speed == 0 || truck?.lst_speed == null) {
$('#infoVehicles-engineStatus').text('IDLING');
}
} else if (truck?.stts_engine == State.stts_engine.idling) {
$('#infoVehicles-engineStatus').text('IDLING');
} else if (truck?.stts_engine == State.stts_engine.stoping) {
$('#infoVehicles-engineStatus').text('STOPPED');
}
// no updated data more than 1 day
if (truck?.lst_loc_crt < moment().subtract(24, 'hour').unix()) {
$('#infoVehicles-ignition').text('OFF');
$('#infoVehicles-engineStatus').text('STOPPED');
}
$('#infoVehicles-addr-title').text(
`${Helper.shortenText(decodeURIComponent(truck?.lst_fulladdress || 'address'), 25)}`);
$('#infoVehicles-addr').text(
`${Helper.shortenText(decodeURIComponent(truck?.lst_fulladdress || 'address'), 25)}`);
$('#infoVehicles-lat_lng').text(Number(truck?.lst_lat).toFixed(5) + ', ' + Number(truck?.lst_lng).toFixed(6));
$('#infoVehicles-mileage').text(Number(truck?.vhc_sum_milleage_1).toFixed(0));
$('#infoVehicles-speedLimit').text(truck?.speed_limit);
$('#infoVehicles-currentSpeed').text(truck?.lst_speed);
let idlingDur = Wrapper.calcIdlingDur(truck?.lst_idle_at, truck?.lst_speed);
$('#infoVehicles-idlingDuration').text(idlingDur.dur);
$('#infoVehicles-idlingUnit').text(idlingDur.unit);
$('#infoVehicles-alertZones').text('-');
$('#infoVehicles-isTrackHoliday').text(truck?.is_track_holiday_text);
$('#infoVehicles-trackSch').text(truck?.track_schedule);
$('#infoVehicles-company').text(truck?.client_group_name);
$('#infoVehicles-serviceStart').text(moment.unix(truck?.vhc_crt).format('DD MMM YYYY HH:mm:ss'));
// driver
$('#infoDrv-updt').text((truck?.ord_crt) ? moment.unix(truck?.ord_crt).format('DD MMM YYYY HH:mm:ss') : '-');
$('#infoDrv-name').text(truck?.ord_drv_name ?? 'Off Duty');
$('.infoDrv-phone1-text').text((truck?.ord_drv_phone_val) ? Helper.splitEvery4Char('0' + truck?.ord_drv_phone_val) : '-');
$('#infoDrv-phone1-tel').attr('tel:0' + (truck?.ord_drv_phone_val ?? ''));
$('#infoDrv-phone1-wa').attr('https://api.whatsapp.com/send/?phone=62' + (truck?.ord_drv_phone_val ?? '') + '&text=Halo&app_absent=0');
$('.infoDrv-phone2-text').text((truck?.ord_drv_phone2_val) ? Helper.splitEvery4Char('0' + truck?.ord_drv_phone2_val) : '-');
$('#infoDrv-phone2-tel').attr('tel:0' + (truck?.ord_drv_phone2_val ?? ''));
$('#infoDrv-phone2-wa').attr('https://api.whatsapp.com/send/?phone=62' + (truck?.ord_drv_phone2_val ?? '') + '&text=Halo&app_absent=0');
// job
// $('#infoJob').html('');
// for (let i = 0; i < 20; i++) {
// $('#infoJob').append(`
// <li class="list-group-item p-1 px-2">
// <p class="text-bold mb-0">#902192${truck.vid}${Math.floor(Math.random()*90000) + 10000}</p>
// <div class="row d-flex align-items-center justify-content-between">
// <div class="col-auto">
// <small class="text-muted">Client name</small>
// <p id="" class="mb-0">JNE</p>
// </div>
// <div class="col-auto">
// <small class="text-muted">Destination</small>
// <p id="" class="mb-0">JKT-01</p></div>
// </div>
// </li>
// `);
// }
$('#infoJob-ord_client_name').text(truck?.ord_c_pt_name ?? '-');
$('#infoJob-pck_city').text(truck?.ord_pck_ktname ?? '-')
$('#infoJob-pck_name').text(truck?.ord_pck_name ?? '-');
$('#infoJob-pck_addr').text(truck?.ord_pck_addr ?? '-');
$('#infoJob-drop_city').text(truck?.ord_drop_ktname ?? '-')
$('#infoJob-drop_name').text(truck?.ord_drop_name ?? '-');
$('#infoJob-drop_addr').text(truck?.ord_drop_addr ?? '-');
let txtOrdStts = 'Not in order';
if (State.stts_order.wait == truck?.ord_stts) {
txtOrdStts = 'Waiting for Confirmation';
} else if (State.stts_order.confirm == truck?.ord_stts) {
txtOrdStts = 'Searching for Vehicle';
} else if (State.stts_order.have_get_vhc == truck?.ord_stts) {
txtOrdStts = 'Vehicle Heading to Pickup Location';
} else if (State.stts_order.pck == truck?.ord_stts) {
txtOrdStts = 'Order Successfully Picked Up';
} else if (State.stts_order.go == truck?.ord_stts) {
txtOrdStts = 'Heading to Delivery Location';
} else if (State.stts_order.arv == truck?.ord_stts) {
txtOrdStts = 'Arrived at Delivery Location';
} else if (State.stts_order.drop == truck?.ord_stts) {
txtOrdStts = 'Delivery Completed';
} else if (State.stts_order.client_pay == truck?.ord_stts) {
// txtOrdStts = 'Invoicing to Client';
txtOrdStts = 'Completed (Waiting for Payment)';
} else if (State.stts_order.vendor_payed == truck?.ord_stts) {
// txtOrdStts = 'Payment to Vendor';
txtOrdStts = 'Completed (Awaiting Vendor Payment)';
} else if (State.stts_order.close == truck?.ord_stts) {
txtOrdStts = 'Completed';
} else if (State.stts_order.cancel == truck?.ord_stts) {
txtOrdStts = 'Cancelled';
}
$('#infoJob-ord_stts').text(txtOrdStts);
// last movement
// $('#infoVehicles-infoMove').text('Last 24H from ' + moment.unix(truck?.lst_loc_crt).format('DD MMM YYYY HH:mm'));
},
bundleShowRouteTruck: async function(cache = false) {
Menu.clearListMovements();
if (State.inShowVid != State.loadedLastMoveVid) $('#historyStartDate').trigger('clearFilterHistoryDate');
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(getLastMove);
},
getLastMove: async function(vid, cache = false) {
State.loadedLastMoveVid = vid;
State.inShowLastMove = vid;
if (cache) {
if (Trucks.last_move == null) {
return (await Trucks.reqLastMove({
vid
})).data;
} else {
return Trucks.last_move;
}
}
return (await Trucks.reqLastMove({
vid
})).data;
},
reqLastMove: function(params) {
return new Promise((resolve, reject) => {
$.ajax({
url: "{{ route('api_last_move_track_vhc') }}?start_date=" + `${State.historyStartDate}&end_date=${State.historyEndDate}`,
method: 'GET',
crossDomain: true,
processData: true,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
},
data: params,
success: (data, textStatus, jqXHR) => {
if (data.meta.type != 'success') {
resolve({
type: 'fail',
data: null,
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
resolve({
type: 'success',
data: data.data,
});
},
error: (jqXHR, textStatus, error) => {
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Cannot get lists trucks');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error',
data: null,
});
}
})
});
},
showLastMoveToView: function(truckRoutes) {
// Leaflet.clearLayer('eventAboutTruck');
Leaflet.hideLayer('eventHideAllTruck');
// 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);
// 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: async function(truckRoutes) {
const colors = [
"#2980B9", // Dark Blue
"#C0392B", // Dark Red
"#27AE60", // Dark Green
"#D35400", // Dark Orange
"#F39C12", // Dark Yellow/Gold
]
let i = 1
let allStartStop = []
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){
const marker = Leaflet.addMarkers({
lat: obj.latitude,
lng: obj.longitude,
label: `
<b>${(key == 0) ? 'Finish' : '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
}
})
allStartStop.push(marker)
}
return {
lat: obj.latitude,
lng: obj.longitude,
options: {
// polyline
color : colors[key0 % colors.length],
smoothFactor : 0,
noClip : true,
bubblingMouseEvents : false,
// circle
radius: 5,
markerOpacity: 0
},
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 circleCounter = 0
for (const [idx, poly] of polyTruckRoutes.entries()) {
// console.log("poly", poly);
function addCirclesAsync(polyCircle) {
// console.log("circleCounter", circleCounter);
// return array of circles start end only
return new Promise(resolve => {
let circles = [];
Leaflet.addCircles(polyCircle, function(circle, i) {
// console.log("circle", i, circleCounter);
if (i === 0 || i === (polyCircle.length - 1)) {
circles.push(circle);
}
const currentCounter = circleCounter;
circle.on('click', function() {
PgBar.syncToPlotTravelHistory(currentCounter);
});
circleCounter++
// ✅ When last point processed, resolve
if (i === polyCircle.length - 1) {
resolve(circles);
}
});
});
}
let polyline = await Leaflet.addRoutes(poly);
// console.log("polyline", polyline);
allStartStop.push(polyline)
// wait for all circles
const ssmarker = await addCirclesAsync(poly);
// console.log("ssmarker", ssmarker);
allStartStop.push(...ssmarker)
}
console.log("allStartStop", allStartStop);
// console.log("circlesStartStop", circlesStartStop);
// // remove marker, circle, event listener and all about this marker
State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
// detail: {
allStartStop,
// circlesStartStop
// }
});
// window.addEventListener('eventRemoveRouteStartEnd', function (e) {
// // allStartStop.remove();
// allStartStop.forEach(c => c.remove())
// // circlesStartStop.forEach(c => c.remove())
// });
window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
allStartStop.forEach(c => c.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, Trucks.last_move.length - 1);
},
routePerPoint: function() {
Leaflet.addMarkers(truckRoutes.routes.map((obj) => {
return {
lat: obj.lat,
lng: obj.lng,
options: {
icon: Icon.point(),
vhc_id: truckRoutes.vhc_id,
gps_id: truckRoutes.gps_id
}
};
}));
},
routeStartEndWithStops: function() {
Leaflet.addPolylines(truckRoutes.routes.map((obj) => {
return {
lat: obj.lat,
lng: obj.lng,
options: {}
}
}), function(polyline) {
// zoom the map to the polyline
// Leaflet.map.fitBounds(polyline.getBounds());
});
Leaflet.addMarkers([{
...truckRoutes.routes.at(0),
label: 'Lokasi Mulai Perjalanan Truk',
options: {
icon: Icon.startNav(),
rotationAngle: 290
}
}]);
Leaflet.addMarkers([{
...truckRoutes.routes.at(20),
label: 'Lokasi Berhenti Truk',
options: {
icon: Icon.point()
}
}]);
Leaflet.addMarkers([{
...truckRoutes.routes.at(40),
label: 'Lokasi Berhenti Truk',
options: {
icon: Icon.point()
}
}]);
Leaflet.addMarkers([{
...truckRoutes.routes.at(60),
label: 'Lokasi Berhenti Truk',
options: {
icon: Icon.point()
}
}]);
Leaflet.addMarkers([{
...truckRoutes.routes.at(-1),
label: 'Lokasi Tujuan Truk',
options: {
icon: Icon.destination()
}
}]);
},
routeAnimationStartShringkingToEnd: function() {
let polyline = null,
marker = null,
timeouts = [];
for (let i = 0; i < truckRoutes.routes.length; i++) {
timeouts.push(setTimeout(() => {
if (polyline) polyline.remove();
if (marker) marker.remove();
// jika typeof variable !== 'undefined'
if (!!truckRoutes.routes.at(i + 1)) {
polyline = Leaflet.addPolylines(truckRoutes.routes.slice((i + 1)).map((
obj) => {
return {
lat: obj.lat,
lng: obj.lng,
options: {}
}
}), function(polyline) {
// zoom the map to the polyline
Leaflet.map.fitBounds(polyline.getBounds());
});
}
marker = Leaflet.addMarkers({
...truckRoutes.routes.at(i),
label: 'Lokasi Truk',
options: {
icon: Icon.startNav(),
rotationAngle: 0
}
});
}, (i + 1) * State.timingRouteAnimation));
}
// remove marker, polyline, event listener and all about this marker
State.eventRemoveRouteAnimationStartShrinkingToEnd = new CustomEvent(
'eventRemoveRouteAnimationStartShrinkingToEnd', {
marker: marker,
polyline: polyline
});
window.addEventListener('eventRemoveRouteAnimationStartShrinkingToEnd', function handler(e) {
for (let i = 0; i < timeouts.length; i++) {
clearTimeout(timeouts[i]);
}
if (marker) marker.remove();
if (polyline) polyline.remove();
e.currentTarget.removeEventListener(e.type,
handler); // window.removeEventListener('remove', this.handler, true);
State.eventRemoveRouteAnimationStartShrinkingToEnd = null;
});
},
routeAnimationStartFootprintsTillEnd: function() {
let polyline = null,
marker = null,
timeouts = [];
for (let i = 0; i < truckRoutes.routes.length; i++) {
timeouts.push(setTimeout(() => {
if (polyline) polyline.remove();
if (marker) marker.remove();
polyline = Leaflet.addPolylines(truckRoutes.routes.slice(0, (i + 1)).map((
obj) => {
return {
lat: obj.lat,
lng: obj.lng,
options: {}
}
}), function(polyline) {
// zoom the map to the polyline
Leaflet.map.fitBounds(polyline.getBounds());
});
marker = Leaflet.addMarkers({
...truckRoutes.routes.at(i),
label: 'Lokasi Truk',
options: {
icon: Icon.startNav(),
rotationAngle: 0
}
});
}, (i + 1) * State.timingRouteAnimation));
}
// remove marker, polyline, event listener and all about this marker
State.eventRemoveRouteAnimationStartFootprintsTillEnd = new CustomEvent(
'eventRemoveRouteAnimationStartFootprintsTillEnd', {
marker: marker,
polyline: polyline
});
window.addEventListener('eventRemoveRouteAnimationStartFootprintsTillEnd', function handler(e) {
for (let i = 0; i < timeouts.length; i++) {
clearTimeout(timeouts[i]);
}
if (marker) marker.remove();
if (polyline) polyline.remove();
e.currentTarget.removeEventListener(e.type,
handler); // window.removeEventListener('remove', this.handler, true);
State.eventRemoveRouteAnimationStartFootprintsTillEnd = null;
});
},
}
const Zone = {
lists: null,
activate: function() {
Zone.bundleGetListZones(false);
},
bundleGetListZones: async function(cache = false) {
Zone.lists = await Zone.getListZones(cache);
Zone.showToLists(Zone.lists);
Zone.showListsToMap(Zone.lists);
},
getListZones: async function(cache = false) {
if (cache) {
if (Zone.lists == null) {
return (await Zone.reqListZones()).data;
} else {
return Zone.lists;
}
}
return (await Zone.reqListZones()).data;
},
reqListZones: function(params) {
return new Promise((resolve, reject) => {
$.ajax({
url: "{{ route('api_universal_list_zones') }}?status=" + State.zone_status.active + "&cptid=" + AppState.current_company,
method: 'GET',
crossDomain: true,
processData: true,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
},
data: params,
success: (data, textStatus, jqXHR) => {
if (data.meta.type != 'success') {
resolve({
type: 'fail',
data: null,
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
resolve({
type: 'success',
data: data.data,
});
},
error: (jqXHR, textStatus, error) => {
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Cannot get lists trucks');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error',
data: null,
});
}
})
});
},
showToLists: function(zones) {
$('#listZone').html('');
let str = '';
for (let i = 0; i < zones.length; i++) {
str += `
<li class="list-group-item vehicles-list-wrapper zone-item p-1 px-2" data-zid="${zones[i].id}">
<a href="#" class="text-dark">
<div class="row d-flex align-items-center">
<div class="col-3 d-flex justify-content-center">
<div class="align-items-center d-flex justify-content-center zone-icon" style="background: ${zones[i].boundary_hex_color}">
<span class="ion-android-pin text-white"></span>
</div>
</div>
<div class="col ps-0">
<p class="text-bold mb-0 textZoneName">${zones[i].name}</p>
<p class="text-muted mb-0 textZoneType">${zones[i].type_name}</p>
</div>
</div>
</a>
</li>
`;
}
$('#c_list_zone').text(zones.length);
$('#listZone').html(str);
},
showListsToMap: function(zones) {
let locations = []; // [{ lat,lng,label,options:{} }]
let circles = [],
polygons = [];
for (let i = 0; i < zones.length; i++) {
let boundary_latlngs = JSON.parse(zones[i].boundary_latlngs);
boundary_latlngs = boundary_latlngs.map((obj) => {
return {
lat: obj.lat,
lng: obj.lng,
label: `<b>${zones[i].name}</b><br>${decodeURIComponent(zones[i].fulladdress || 'address')}`,
options: {
mdata: zones[i],
color: zones[i].boundary_hex_color,
fillColor: zones[i].boundary_hex_color,
radius: zones[i].boundary_radius,
},
};
});
if (zones[i].boundary_type == State.zone_boundary_type.circle) {
let circle = Leaflet.addCircles(boundary_latlngs[0]);
circles.push(circle);
} else if (zones[i].boundary_type == State.zone_boundary_type.polygon || zones[i]
.boundary_type == State.zone_boundary_type.rectangle) {
let polygon = Leaflet.addPolygons(boundary_latlngs);
polygons.push(polygon);
} else {
Helper.toast('Error', 'just now', 'unknown boundary type');
continue;
}
}
// remove marker, circle, event listener and all about this marker
State.eventRemoveListZones = new CustomEvent('eventRemoveListZones', {
circles,
polygons
});
window.addEventListener('eventRemoveListZones', function handler(e) {
for (let circle of circles) {
circle.removeEventListener('click');
circle.remove();
}
for (let polygon of polygons) {
polygon.removeEventListener('click');
polygon.remove();
}
e.currentTarget.removeEventListener(e.type,
handler); // window.removeEventListener('remove', this.handler, true);
State.eventRemoveListZones = null;
});
},
showDetailGeneral: function(zone) {
State.inShowZid = zone.zid;
$('#zd-name').text(zone.name);
$('#zd-boundary_hex_color').css('background-color', zone.boundary_hex_color || '#000000')
$('#zd-type_name').text(zone.type_name);
$('#zd-type_name1').text(zone.type_name);
$('#zd-client').text(zone.client_group_name);
$('#zd-workflow_type_name').text(zone.workflow_type_name);
$('#zd-fulladdress').text(decodeURIComponent(zone.fulladdress || 'address'));
$('#zd-shiptocode').text(zone.shiptocode);
$('#zd-updt_at').text(moment(zone.updt).format('DD MMM YYYY HH:mm'));
$('#zd-updt_by').text(zone.updt_name);
},
}
const Client = {
client: null,
activate: function() {
Client.bundleGetClient(false);
},
bundleGetClient: async function(cache = false) {
Client.client = await Client.getClient(cache);
Client.showToView(Client.client);
},
getClient: async function(cache = false) {
if (cache) {
if (Client.client == null) {
return (await Client.reqClient()).data;
} else {
return Client.client;
}
}
return (await Client.reqClient()).data;
},
reqClient: function(params) {
return new Promise((resolve, reject) => {
$.ajax({
url: "{{ route('api_universal_show_client_pt') }}?cptid=" + AppState.current_company,
method: 'GET',
crossDomain: true,
processData: true,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
},
data: params,
success: (data, textStatus, jqXHR) => {
if (data.meta.type != 'success') {
resolve({
type: 'fail',
data: null,
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
resolve({
type: 'success',
data: data.data,
});
},
error: (jqXHR, textStatus, error) => {
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Cannot get company information');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error',
data: null,
});
}
})
});
},
showToView: function(client) {
$('#c_name').text(client.c_name);
$('#ptName').text(client.c_name);
$('#c_logo').attr('src', State.storage_lara + '/' + client.c_logo);
},
}
const Filter = {
activate: function() {
Filter.event();
},
event: function() {},
triggerFilterCompany: async function() {
Leaflet.clearLayer('all');
// client
await Client.bundleGetClient(false);
// trucks
State.loadedLastMoveVid = null;
State.inShowZid = null;
State.lastShowVids = [];
await Trucks.bundleGetListTrucks(false);
// zones
State.inShowZid = null;
await Zone.bundleGetListZones(false);
},
}
const PgBar = {
activate: function() {
PgBar.event();
},
event: function() {
$('#pgplay').on('click', function(e) {
const click = $(e.target);
if (State.playback.stts === 0 || State.playback.stts === 2 || State.playback.stts === 4) {
PgBar.resume();
} else if (State.playback.stts === 1 || State.playback.stts === 3) {
PgBar.pause();
}
});
document.getElementById('pgbar').oninput = function() {
this.value = Number(this.value);
this.min = Number(this.min);
this.max = Number(this.max);
State.playback.crntPgIndicator = this.value;
let indicator = Helper.getPercentRange(this.value, this.min, this.max);
this.style.background = `linear-gradient(to right, var(--bs-blue) 0%, var(--bs-blue) ${indicator}%, #d3d3d3 0%)`;
let arrIdx = Helper.getIndexReversedSequence(this.value, this.max);
if (Trucks.last_move === null || Trucks.last_move.length < 1) {} else {
let tr = Trucks.last_move[arrIdx];
setTimeout(() => {
Menu.createMarkerDetailPlotMovement(tr);
}, 1);
}
PgBar.syncToPlotTravelHistory(arrIdx);
}
},
setMinMax: function(min, max) {
min = Number(min);
max = Number(max);
PgBar.reset();
PgBar.tglMenuPlayback(true);
const bar = document.getElementById('pgbar');
bar.min = min;
bar.max = max;
State.playback.minIndicator = min;
State.playback.maxIndicator = max;
},
setCrntVal: function(val) {
val = Number(val);
State.playback.crntIndicator = val;
const bar = document.getElementById('pgbar');
bar.value = State.playback.crntIndicator;
let indicator = Helper.getPercentRange(bar.value, bar.min, bar.max);
bar.style.background = `linear-gradient(to right, var(--bs-blue) 0%, var(--bs-blue) ${indicator}%, #d3d3d3 0%)`;
},
reset: function() {
State.playback.stts = 0;
State.playback.crntIndicator = 0;
State.playback.minIndicator = 0;
State.playback.maxIndicator = 1000;
clearInterval(State.playback.intrvl);
const bar = document.getElementById('pgbar');
bar.min = State.playback.minIndicator;
bar.max = State.playback.maxIndicator;
bar.value = State.playback.crntIndicator;
bar.style.background = `linear-gradient(to right, var(--bs-blue) 0%, var(--bs-blue) ${0}%, #d3d3d3 0%)`;
PgBar.tglIconPlayback(State.playback.stts);
},
resume: function() {
// not allowed
if (State.playback.stts === 1 || State.playback.stts === 3) return false;
if (Trucks.last_move === null || Trucks.last_move.length < 1) {
Helper.toast('Warning', 'just now', 'Data riwayat tidak ada');
return false;
}
State.playback.stts = 1;
PgBar.tglIconPlayback(State.playback.stts);
State.playback.intrvl = setInterval(frame, State.playback.intrvlTime);
function frame() {
const bar = document.getElementById('pgbar');
let value = Number(bar.value);
let min = Number(bar.min);
let max = Number(bar.max);
let arrIdx = Helper.getIndexReversedSequence(value, max);
if (value >= max) {
clearInterval(State.playback.intrvl);
State.playback.stts = 4;
PgBar.tglIconPlayback(State.playback.stts);
} else {
++value;
bar.value = value;
let indicator = Helper.getPercentRange(value, min, max);
bar.style.background = `linear-gradient(to right, var(--bs-blue) 0%, var(--bs-blue) ${indicator}%, #d3d3d3 0%)`;
let tr = Trucks.last_move[arrIdx];
Menu.createMarkerDetailPlotMovement(tr, {
nozoom: true
});
}
PgBar.syncToPlotTravelHistory(arrIdx);
}
},
pause: function() {
// not allowed
if (State.playback.stts === 0 || State.playback.stts === 2 || State.playback.stts === 4) return false;
State.playback.stts = 2;
const bar = document.getElementById('pgbar');
PgBar.tglIconPlayback(State.playback.stts);
clearInterval(State.playback.intrvl);
// just show markers with openPopup
let value = Number(bar.value);
let min = Number(bar.min);
let max = Number(bar.max);
let arrIdx = Helper.getIndexReversedSequence(value, max);
let tr = Trucks.last_move[arrIdx];
setTimeout(() => {
Menu.createMarkerDetailPlotMovement(tr, {
nozoom: true
});
}, 1);
},
play1: function() {
let indicator = 0; // percent: double
const bar = document.getElementById('pgbar');
let frameProgress = setInterval(frame, 10);
function frame() {
if (indicator >= 100) {
clearInterval(frameProgress);
} else {
++indicator;
bar.style.width = indicator + '%';
}
}
},
tglMenuPlayback: function(show = true) {
if (show) document.getElementById('menuPlayback').classList.remove('d-none');
else document.getElementById('menuPlayback').classList.add('d-none');
},
tglIconPlayback: function(stts) {
const iconPg = document.getElementById('icon-pg');
if (stts === 0 || stts === 2 || stts === 4) {
iconPg.classList.remove('ion-pause');
iconPg.classList.add('ion-play');
} else if (stts === 1 || stts === 3) {
iconPg.classList.remove('ion-play');
iconPg.classList.add('ion-pause');
}
},
syncToPlotTravelHistory: function(arrIdx) {
console.log("syncToPlotTravelHistory", arrIdx);
const listPlotTravelHistory = document.querySelectorAll('#infoMove-plots .plotMove-item')[arrIdx];
listPlotTravelHistory.scrollIntoView();
listPlotTravelHistory.querySelector('li').classList.add('hover');
setTimeout(() => {
listPlotTravelHistory.querySelector('li').classList.remove('hover');
}, 500);
}
}
Wrapper.activate();
</script>
@endsection