diff --git a/app/Http/Controllers/MaintenanceHistoryController.php b/app/Http/Controllers/MaintenanceHistoryController.php
new file mode 100644
index 0000000..fe06c6a
--- /dev/null
+++ b/app/Http/Controllers/MaintenanceHistoryController.php
@@ -0,0 +1,102 @@
+leftJoin('t_maintenance_vhc_type as t', function ($join) {
+ $join->whereRaw('FIND_IN_SET(t.id, h.idservice)');
+ })
+ ->select(
+ 'h.*',
+ DB::raw('GROUP_CONCAT(t.service_type SEPARATOR ", ") as service_names')
+ )
+ ->where('h.vhc_id', $vehicleid)
+ ->groupBy('h.id')
+ ->get();
+
+ $apiResp = Responses::success("success list maintenance vehicles");
+ $apiResp["data"] = $data;
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ } catch (\Exception $e) {
+ $apiResp = Responses::error($e->getMessage());
+ return new Response($apiResp, $apiResp["meta"]["code"]);
+ }
+ }
+
+ /**
+ * API Update data history maintenance
+ */
+ public function api_update_data_maintenance(Request $req, $vehicleid, $id)
+ {
+ try {
+ $now = time();
+
+ $input = [
+ "idservice" => $req->idservice,
+ "odometer" => $req->odometer,
+ "dates" => $req->dates,
+ "ismaintenance"=> $req->ismaintenance
+ ];
+ $rulesInput = [
+ "idservice" => "required|string",
+ "odometer" => "required|numeric",
+ "dates" => "required|string",
+ "ismaintenance" => "required|numeric"
+ ];
+
+ // 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 = [
+ "idservice" => $req->idservice,
+ "vhc_id" => $vehicleid,
+ "odometer" => $req->odometer,
+ "dates" => $req->dates,
+ "ismaintenance" => $req->ismaintenance,
+ // "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_vehicles_maintenance_history')->where('id', $id)->update($update);
+ $apiResp = Responses::created("success update maintenance vehicles");
+
+ DB::commit();
+
+
+ $log = [
+ "module" => "Vehicle Type",
+ "action" => "Create",
+ "desc" => "Add new vehicle maintenance type: " . $req->service_type,
+ ];
+ 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/VehiclesController.php b/app/Http/Controllers/VehiclesController.php
index 5b781e4..90882e4 100755
--- a/app/Http/Controllers/VehiclesController.php
+++ b/app/Http/Controllers/VehiclesController.php
@@ -72,7 +72,7 @@ class VehiclesController extends Controller
$filter["company"] = $req->cptid;
}
$list = DB::select("SELECT
- v.id, v.name, v.device_id, nopol1, nopol2, nopol3, v.sum_milleage,
+ v.id, v.name, v.device_id, nopol1, nopol2, nopol3, v.sum_milleage,
fvhc_img, vyear, t.`desc` type_name, c_name company_name, rltm.crt_d, rltm.crt crt_rltm,
dvc.crt, dvc.simcard, fuel_curr, dvc.protocol, v.cat_id, vc.name cat_name
FROM t_vehicles as v
@@ -84,7 +84,7 @@ class VehiclesController extends Controller
left join t_gps_tracks_rltm rltm on rltm.vhc_id = v.id
LEFT JOIN t_vehicles_cats AS vc ON v.cat_id = vc.id
WHERE v.dlt is null
- ORDER BY v.id ASC
+ ORDER BY v.id ASC
");
foreach ($list as $key => $row) {
diff --git a/resources/views/menu_v1/vehicles.blade.php b/resources/views/menu_v1/vehicles.blade.php
index 3663efa..45d34fb 100755
--- a/resources/views/menu_v1/vehicles.blade.php
+++ b/resources/views/menu_v1/vehicles.blade.php
@@ -679,6 +679,41 @@
+
+
@endsection
@section('customjs')
@@ -705,6 +740,7 @@
VNew.activate();
VEdt.activate();
VDel.activate();
+ VHistory.activate();
Filter.activate();
// images
DUploadAdd.activate('fvhc');
@@ -805,14 +841,14 @@
searchable: true,
render: function (data, type, row, meta) {
let action = `
-
-
-
- `;
- //
- //
- //
- return action;
+
+
+
+
+
+
+ `;
+ return action;
}
},
{
@@ -2003,6 +2039,219 @@
},
}
+ const VHistory = {
+ options_service: [],
+ activate: function () {
+ this.event();
+ },
+ event: function () {
+ // buka modal
+ $('#tVehicles').on('click', '.btnHistoryVhc', function (e) {
+ e.preventDefault();
+ const vid = $(this).data('vid');
+ const catid = $(this).data('catid');
+ $('#mdlHistoryMaintenance').data('vid', vid);
+ VHistory.load(vid, catid);
+ $('#mdlHistoryMaintenance').modal('show');
+ });
+
+ // toggle Edit -> enable row
+ $('#tHistoryMaintenanceBody').on('click', '.btnEditRow', function () {
+ const $row = $(this).closest('tr');
+ VHistory.enableRow($row);
+ $(this)
+ .text('Save')
+ .removeClass('btn-outline-primary btnEditRow')
+ .addClass('btn-success btnSaveRow');
+ });
+
+ // Save row
+ $('#tHistoryMaintenanceBody').on('click', '.btnSaveRow', function () {
+ const $row = $(this).closest('tr');
+ VHistory.saveRow($row, $(this));
+ });
+ },
+ load: async function (vid, catid) {
+ $('#tHistoryMaintenanceBody').html('| Loading... |
');
+ try {
+ const respTypes = await VHistory.loadServiceTypes(catid);
+ VHistory.options_service = respTypes || [];
+
+ $.ajax({
+ url: "{{ route('api_get_data_maintenance', '') }}/" + vid,
+ method: 'GET',
+ headers: { 'x-api-key': Helper.getCookie('_trtk') },
+ success: (res) => {
+ if (res.meta.type != 'success') {
+ Helper.toast('Warning', 'just now', res.meta.message);
+ $('#tHistoryMaintenanceBody').html('| Failed to load data |
');
+ return;
+ }
+ VHistory.render(res.data);
+ },
+ error: (jqXHR) => {
+ $('#tHistoryMaintenanceBody').html('| Failed to load data |
');
+ Helper.toast('Error', 'just now', jqXHR.responseJSON?.meta?.message || 'Failed to load history');
+ },
+ });
+ } catch (e) {
+ $('#tHistoryMaintenanceBody').html('| Failed to load data |
');
+ }
+ },
+ loadServiceTypes: function (catid) {
+ return new Promise((resolve) => {
+ $.ajax({
+ url: "{{ route('api_list_vehicle_maintenance_type') }}",
+ method: 'GET',
+ headers: { 'x-api-key': Helper.getCookie('_trtk') },
+ success: (res) => resolve(res.data || []),
+ error: () => resolve([]),
+ });
+ });
+ },
+ render: function (rows) {
+ if (!rows || rows.length < 1) {
+ $('#tHistoryMaintenanceBody').html('| No data |
');
+ return;
+ }
+
+ let html = '';
+ rows.forEach((row) => {
+ const selectedIds = (row.idservice || '').split(',').map((v) => v.trim());
+ const options = VHistory.options_service
+ .map((opt) => ``)
+ .join('');
+
+ const isChecked = Number(row.ismaintenance) === 1 ? 'checked' : '';
+
+ html += `
+
+ |
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+ `;
+ });
+
+ $('#tHistoryMaintenanceBody').html(html);
+
+ // init select2 tiap row (tetap disabled dulu)
+ $('#tHistoryMaintenanceBody .history-service').each(function () {
+ $(this).select2({
+ dropdownParent: $('#mdlHistoryMaintenance'),
+ width: '100%',
+ });
+ });
+
+ // init datepicker tiap row
+ $('#tHistoryMaintenanceBody .history-date').datepicker({
+ format: 'yyyy-mm-dd',
+ });
+ },
+ enableRow: function ($row) {
+ $row.find('.history-odometer').prop('disabled', false);
+ $row.find('.history-date').prop('disabled', false);
+ $row.find('.history-ismaintenance').prop('disabled', false);
+
+ const $select = $row.find('.history-service');
+ $select.prop('disabled', false);
+ $select.select2('destroy');
+ $select.select2({
+ dropdownParent: $('#mdlHistoryMaintenance'),
+ width: '100%',
+ });
+ },
+ disableRow: function ($row) {
+ $row.find('.history-odometer').prop('disabled', true);
+ $row.find('.history-date').prop('disabled', true);
+ $row.find('.history-ismaintenance').prop('disabled', true);
+
+ const $select = $row.find('.history-service');
+ $select.prop('disabled', true);
+ $select.select2('destroy');
+ $select.select2({
+ dropdownParent: $('#mdlHistoryMaintenance'),
+ width: '100%',
+ });
+ },
+ saveRow: function ($row, $btn) {
+ const vid = $('#mdlHistoryMaintenance').data('vid');
+ const hid = $row.data('hid');
+ const idservice = $row.find('.history-service').val(); // array
+ const odometer = $row.find('.history-odometer').val();
+ const dates = $row.find('.history-date').val();
+ const ismaintenance = $row.find('.history-ismaintenance').is(':checked') ? 1 : 0;
+
+ if (!idservice || idservice.length < 1) {
+ Helper.toast('Validasi', 'just now', 'Service type wajib diisi');
+ return;
+ }
+ if (!odometer) {
+ Helper.toast('Validasi', 'just now', 'Odometer wajib diisi');
+ return;
+ }
+ if (!dates) {
+ Helper.toast('Validasi', 'just now', 'Tanggal wajib diisi');
+ return;
+ }
+
+ $btn.prop('disabled', true).text('Saving...');
+
+ $.ajax({
+ url: "{{ route('api_update_data_maintenance', ['vehicleid' => '__VID__', 'id' => '__ID__']) }}"
+ .replace('__VID__', vid)
+ .replace('__ID__', hid),
+ method: 'PUT',
+ headers: {
+ 'x-api-key': Helper.getCookie('_trtk'),
+ 'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
+ },
+ data: {
+ idservice: idservice.join(','),
+ odometer: odometer,
+ dates: dates,
+ ismaintenance: ismaintenance,
+ },
+ success: (res) => {
+ $btn.prop('disabled', false);
+ if (res.meta.type != 'success') {
+ Helper.toast('Warning', 'just now', res.meta.message);
+ $btn.text('Save');
+ return;
+ }
+ Helper.toast('Success', 'just now', 'Berhasil update maintenance history');
+ VHistory.disableRow($row);
+ $btn.text('Edit')
+ .removeClass('btn-success btnSaveRow')
+ .addClass('btn-outline-primary btnEditRow');
+ },
+ error: (jqXHR) => {
+ $btn.prop('disabled', false).text('Save');
+ if (jqXHR.status >= 500) {
+ Helper.toast('Error', 'just now', 'Please try again');
+ } else {
+ Helper.toast('Error', 'just now', jqXHR.responseJSON?.meta?.message || 'Gagal menyimpan');
+ }
+ },
+ });
+ },
+ };
Wrapper.activate();
-@endsection
\ No newline at end of file
+@endsection
diff --git a/routes/web.php b/routes/web.php
index 4cd369b..c5e0238 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -334,6 +334,9 @@ Route::middleware(["auth", "auth.user"])->group(function () {
"api_search_nopol"
);
+ Route::get("/api/maintenances/{vid}", "MaintenanceHistoryController@api_get_data_maintenance")->name("api_get_data_maintenance");
+ Route::put("/api/maintenances/{vehicleid}/{id}", "MaintenanceHistoryController@api_update_data_maintenance")->name("api_update_data_maintenance");
+
Route::get("/api/zones", "ZoneController@api_list_zones")->name("api_list_zones");
Route::get("/api/zones/{zid}", "ZoneController@api_show_zone")->name("api_show_zone");
Route::post("/api/zones", "ZoneController@api_add_zone")->name("api_add_zone");