diff --git a/app/Http/Controllers/TripsLabelingController.php b/app/Http/Controllers/TripsLabelingController.php
new file mode 100644
index 0000000..c30a40a
--- /dev/null
+++ b/app/Http/Controllers/TripsLabelingController.php
@@ -0,0 +1,241 @@
+where('id', $id)
+ ->first();
+
+ if (!$data) {
+ $apiResp = Responses::error("Sites labeling not found");
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+
+ $apiResp = [
+ "meta" => [
+ "code" => 200,
+ "type" => "success",
+ "message" => "success",
+ ],
+ "data" => $data,
+ ];
+
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+
+ } catch (\Exception $e) {
+ $apiResp = Responses::error($e->getMessage());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+ }
+ /**
+ * View
+ */
+
+ public function view_trips_label(Request $req)
+ {
+ $data = [];
+
+ $log = [
+ "module" => "Trips Label",
+ "action" => "View",
+ "desc" => "Open Trips Label",
+ ];
+ UserLogs::insert(Auth::user()->id, $log);
+ return view("menu_v1.trips_label", $data);
+ }
+
+ /**
+ * API
+ */
+ public function api_list_trips_label(Request $req)
+ {
+ try {
+ $datas = DB::table('t_sites_label')
+ ->where('isdeleted', 0)
+ ->get();
+
+ foreach ($datas as $key => $row) {
+ $datas[$key]->DT_RowIndex = $key + 1;
+ $datas[$key]->action = "-";
+ }
+
+ $apiResp = Responses::success("success list sites labeling");
+ $apiResp["count"] = count($datas);
+ $apiResp["data"] = $datas;
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ } catch (\Exception $e) {
+ $apiResp = Responses::error($e->getMessage());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+ }
+
+ /**
+ * Show the form for creating a new resource.
+ *
+ * @return Response
+ */
+ public function api_add_trips_label(Request $req)
+ {
+ try {
+ $now = time();
+
+ $input = [
+ "address" => $req->address,
+ "lat" => $req->lat,
+ "lng" => $req->lng,
+ "radius" => $req->radius
+ ];
+ $rulesInput = [
+ "address" => "required|string",
+ "lat" => "required|numeric|between:-90,90",
+ "lng" => "required|numeric|between:-180,180",
+ "radius" => "required|integer|min:0",
+ ];
+
+ // validasi input
+ $isValidInput = Validator::make($input, $rulesInput);
+ if (!$isValidInput->passes()) {
+ $apiResp = Responses::bad_input($isValidInput->messages()->first());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+
+ DB::beginTransaction();
+
+ $insert = [
+ "address" => $req->address,
+ "lat" => $req->lat,
+ "lng" => $req->lng,
+ "radius" => $req->radius,
+ // "created_at" => date("Y-m-d H:i:s", $now),
+ // "udt" => date("Y-m-d H:i:s", $now),
+ // "created_by" => Auth::user()->id,
+ // "uby" => Auth::user()->id
+ ];
+ DB::table('t_sites_label')->insert($insert);
+ $apiResp = Responses::created("success add new trips label");
+
+ DB::commit();
+
+
+ $log = [
+ "module" => "Trips Label",
+ "action" => "Create",
+ "desc" => "Add new trips label: " . $req->address,
+ ];
+ UserLogs::insert(Auth::user()->id, $log);
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ } catch (\Exception $e) {
+ DB::rollBack();
+ $apiResp = Responses::error($e->getMessage());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+ }
+
+ /**
+ * Update the specified resource in storage.
+ *
+ * @param Request $req
+ * @param int $id
+ * @return Response
+ */
+ public function api_edit_trips_label(Request $req, $id)
+ {
+ try {
+ $now = time();
+
+ $input = [
+ "address" => $req->address,
+ "lat" => $req->lat,
+ "lng" => $req->lng,
+ "radius" => $req->radius
+ ];
+ $rulesInput = [
+ "address" => "required|string",
+ "lat" => "required|numeric|between:-90,90",
+ "lng" => "required|numeric|between:-180,180",
+ "radius" => "required|integer|min:0",
+ ];
+
+ // validasi input
+ $isValidInput = Validator::make($input, $rulesInput);
+ if (!$isValidInput->passes()) {
+ $apiResp = Responses::bad_input($isValidInput->messages()->first());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+
+ DB::beginTransaction();
+
+ $update = [
+ "address" => $req->address,
+ "lat" => $req->lat,
+ "lng" => $req->lng,
+ "radius" => $req->radius,
+ ];
+ DB::table('t_sites_label')->where('id', $id)->update($update);
+
+ $apiResp = Responses::created("success update trips label");
+
+ DB::commit();
+
+ $log = [
+ "module" => "Trips Label",
+ "action" => "Update",
+ "desc" => "Update trips label: " . $req->address,
+ ];
+ UserLogs::insert(Auth::user()->id, $log);
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ } catch (\Exception $e) {
+ DB::rollBack();
+ $apiResp = Responses::error($e->getMessage());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ *
+ * @param int $id
+ * @return Response
+ */
+ public function api_del_trips_label($id)
+ {
+ try {
+ DB::beginTransaction();
+
+ DB::table('t_sites_label')->where('id', $id)->update([
+ 'isdeleted' => 1,
+ // 'ddt' => date("Y-m-d H:i:s", time()),
+ // 'dby' => Auth::user()->id
+ ]);
+
+ DB::commit();
+
+ $apiResp = Responses::success("success delete trips label");
+
+ $log = [
+ "module" => "Trips Label",
+ "action" => "Delete",
+ "desc" => "Delete trips label: " . $id,
+ ];
+ UserLogs::insert(Auth::user()->id, $log);
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ } catch (\Exception $e) {
+ DB::rollBack();
+ $apiResp = Responses::error($e->getMessage());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/VehicleMaintenanceController.php b/app/Http/Controllers/VehicleMaintenanceController.php
index 479be71..2592dc4 100644
--- a/app/Http/Controllers/VehicleMaintenanceController.php
+++ b/app/Http/Controllers/VehicleMaintenanceController.php
@@ -20,7 +20,7 @@ class VehicleMaintenanceController extends Controller
->first();
if (!$data) {
- $apiResp = Responses::error("Truck type not found", 404);
+ $apiResp = Responses::error("Vehicle Maintenance type not found");
return new Response($apiResp, $apiResp["meta"]["code"]);
}
diff --git a/resources/views/menu_v1/reports/vehicle_trips.blade.php b/resources/views/menu_v1/reports/vehicle_trips.blade.php
index 3011ca2..ef7e2cc 100644
--- a/resources/views/menu_v1/reports/vehicle_trips.blade.php
+++ b/resources/views/menu_v1/reports/vehicle_trips.blade.php
@@ -129,74 +129,6 @@
Detail |
-
@@ -207,18 +139,6 @@
-
@endsection
@@ -228,9 +148,6 @@
-
@@ -254,15 +171,12 @@
activate: function() {
Wrapper.init();
Wrapper.event();
- // DTable.table = $('#tVehicleTrips').DataTable()
- // DTable.activate();
},
init: () => {
$('#tgl0, #tgl1').datetimepicker({
format: 'd-m-Y H:i',
defaultTime: '00:00',
closeOnDateSelect: true,
- // mask:true
});
},
@@ -283,7 +197,6 @@
const tgl1 = $(this).data('tgl1');
const nopol1 = $(this).data('nopol1');
- // $("#mdlDetailTrip").load("{{ route('view_report_trip_detail') }}");
$('#mdlDetailTrip').empty().load("{{ route('view_report_trip_detail') }}",
`vid=${vid}&tgl0=${tgl0}&tgl1=${tgl1}&nopol1=${nopol1}`, () => {
$('#mdlDetailTrip').modal('show')
@@ -293,35 +206,38 @@
$('#filterNopol').select2({});
},
};
- // Data referensi site (lat/lng dalam desimal, bukan koma)
- const SITE_LOCATIONS = [{
- name: 'Bitterlaun',
- district: 'Dili',
- subdistrict: 'Cristo Rei',
- village: 'Hera',
- lat: -8.548328,
- lng: 125.623808
- },
- {
- name: 'Bebonuk',
- district: 'Dili',
- subdistrict: 'Dom Aleixo',
- village: 'Comoro',
- lat: -8.547527,
- lng: 125.548280
- },
- {
- name: 'Balide',
- district: 'Dili',
- subdistrict: 'Nain Feto',
- village: 'Santa Cruz',
- lat: -8.564396,
- lng: 125.582151
- },
- ];
- // Radius toleransi "berdekatan" dalam meter — sesuaikan sesuai kebutuhan
- const SITE_PROXIMITY_RADIUS_METERS = 500;
+ // ================================
+ // SITE LABELING (dari API, bukan hardcode)
+ // ================================
+
+ // Data referensi site (lat/lng dalam desimal) — diisi via loadSiteLocations()
+ let SITE_LOCATIONS = [];
+
+ // Ambil data site labeling dari API
+ function loadSiteLocations() {
+ return $.ajax({
+ url: "{{ route('api_list_trips_label') }}",
+ type: 'GET',
+ dataType: 'json',
+ }).then(function(json) {
+ const list = (json && json.data) ? json.data : [];
+ // hanya ambil yang belum dihapus (isdeleted = 0), lalu normalisasi field yang dipakai
+ SITE_LOCATIONS = list
+ .filter(site => Number(site.isdeleted) === 0)
+ .map(site => ({
+ id: site.id,
+ address: site.address,
+ lat: parseFloat(site.lat),
+ lng: parseFloat(site.lng),
+ // radius dari API sudah dalam meter
+ radius: parseFloat(site.radius),
+ }));
+ }).catch(function(err) {
+ console.error('Failed to load site locations:', err);
+ SITE_LOCATIONS = [];
+ });
+ }
// Helper untuk parse string "lat, long" menjadi { lat, lng }
function parseLatLong(latLongStr) {
@@ -361,6 +277,7 @@
}
// Cari site terdekat dari koordinat yang diberikan; null jika tidak ada yang cukup dekat
+ // menggunakan radius masing-masing site (bukan radius global)
function findNearestSite(lat, lng) {
if (lat === undefined || lng === undefined || lat === null || lng === null || lat === '' || lng === '') {
return null;
@@ -369,7 +286,7 @@
let minDist = Infinity;
SITE_LOCATIONS.forEach(site => {
const dist = getDistanceMeters(parseFloat(lat), parseFloat(lng), site.lat, site.lng);
- if (dist <= SITE_PROXIMITY_RADIUS_METERS && dist < minDist) {
+ if (dist <= site.radius && dist < minDist) {
minDist = dist;
nearest = site;
}
@@ -378,10 +295,15 @@
}
// Format label sesuai output yang diinginkan
+ // address dari API sudah lengkap (mis. "Bitterlaun, Hera, Cristo Rei, Dili")
function formatSiteLabel(site) {
- return `Site ${site.name}, ${site.village}, ${site.subdistrict}, ${site.district}, Timor-Leste`;
+ return `Site ${site.address}, Timor-Leste`;
}
+ // ================================
+ // END SITE LABELING
+ // ================================
+
const DTable = {
table: null,
lastAjax: null, // keep track of the last ajax request
@@ -704,7 +626,6 @@
// Convert canvas to ImageState.
let imageData = ctx.getImageData(0, 0, imgWidth, imgHeight)
- // console.log(imageState.data.byteLength + ' bytes.')
// Convert canvas to Blob
canvas.toBlob((blob) => {
@@ -712,13 +633,6 @@
newReader.addEventListener('loadend', () => {
// Convert canvas to ArrayBuffer
let arrayBuffer = newReader.result
- // console.log(arrayBuffer.byteLength + ' bytes.')
-
- // Convert ArrayBuffer to Blob
- // let blob = new Blob([arrayBuffer], {type: mimeType})
-
- // Dispay Blob content in an Image.
- // console.log(URL.createObjectURL(blob))
// Generate as file
let newFile = new File([arrayBuffer], fileName, {
@@ -736,6 +650,10 @@
});
}
- Wrapper.activate();
+ // Pastikan data site sudah ter-load SEBELUM tabel trip dirender,
+ // supaya findNearestSite() punya data yang benar saat kolom start/finish di-render.
+ loadSiteLocations().always(function() {
+ Wrapper.activate();
+ });
@endsection
diff --git a/resources/views/menu_v1/trips_label.blade.php b/resources/views/menu_v1/trips_label.blade.php
new file mode 100755
index 0000000..c04595d
--- /dev/null
+++ b/resources/views/menu_v1/trips_label.blade.php
@@ -0,0 +1,656 @@
+@extends('app.app')
+
+@section('title')
+ Trips Label
+@endsection
+
+@section('customcss')
+
+@endsection
+
+@section('content')
+
+
+
+
+
+
+
+
+
+ | # |
+ Action |
+ Address |
+ Latitude |
+ Longitude |
+ Radius (m) |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Are you sure want to delete this trips label
+
+
+
+
+
+
+
+
+
+
+@endsection
+
+@section('customjs')
+
+
+@endsection
diff --git a/routes/web.php b/routes/web.php
index c5e0238..f025227 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -145,6 +145,10 @@ Route::middleware(["auth", "auth.user"])->group(function () {
->name("view_vehicle_maintenance_type")
->middleware("permission:vehicle_maintenance_type.view");
+ Route::get("/trips_label", "TripsLabelingController@view_trips_label")
+ ->name("view_trips_label")
+ ->middleware("permission:trips_label.view");
+
Route::get("/config/devices", "DevicesController@view_devices")
->name("view_config_devices")
->middleware("permission:config_master_device.view");
@@ -636,6 +640,24 @@ Route::middleware(["auth", "auth.user"])->group(function () {
"api_del_vehicle_maintenance_type"
);
+ Route::get("/api/trips_label/{id}", "TripsLabelingController@api_show_trips_label")->name(
+ "api_show_trips_label"
+ );
+
+ Route::get("/api/trips_label", "TripsLabelingController@api_list_trips_label")->name(
+ "api_list_trips_label"
+ );
+
+ Route::post("/api/trips_label", "TripsLabelingController@api_add_trips_label")->name(
+ "api_add_trips_label"
+ );
+ Route::put("/api/trips_label/{id}", "TripsLabelingController@api_edit_trips_label")->name(
+ "api_edit_trips_label"
+ );
+ Route::delete("/api/trips_label/{id}", "TripsLabelingController@api_del_trips_label")->name(
+ "api_del_trips_label"
+ );
+
Route::get("/api/devices", "DevicesController@api_list_devices")->name("api_list_devices");
Route::get("/api/devices/{id}", "DevicesController@api_show_device")->name("api_show_device");
Route::post("/api/devices", "DevicesController@api_add_device")->name("api_add_device");