update vehicles history maintenance

This commit is contained in:
wayanrivan
2026-07-13 11:52:15 +07:00
parent a0ce09cdda
commit 583ea3b9a0
4 changed files with 365 additions and 11 deletions

View File

@ -679,6 +679,41 @@
</div>
</div>
</div>
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlHistoryMaintenance"
aria-labelledby="mdlHistoryMaintenanceLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mdlHistoryMaintenanceLabel">Maintenance History</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-sm align-middle" id="tHistoryMaintenance">
<thead>
<tr>
<th style="width:35%">Service Type</th>
<th style="width:15%">Odometer</th>
<th style="width:15%">Date</th>
<th style="width:15%" class="text-center">Maintenance?</th>
<th style="width:20%" class="text-center">Action</th>
</tr>
</thead>
<tbody id="tHistoryMaintenanceBody">
<tr>
<td colspan="4" class="text-center">No data</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
@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 = `
<a href="#" class="text-decoration-none me-1 btnEdtVhc" data-vid="${data}">
<span class="icon ion-eye fz-16"></span>
</a>
`;
// <a href="#" class="text-decoration-none text-danger btnDelVhc">
// <span class="icon ion-trash-b fz-16"></span>
// </a>
return action;
<a href="#" class="text-decoration-none me-1 btnEdtVhc" data-vid="${data}">
<span class="icon ion-eye fz-16"></span>
</a>
<a href="#" class="text-decoration-none me-1 btnHistoryVhc" data-vid="${data}" data-catid="${row.cat_id}" title="Maintenance History">
<span class="icon ion-clipboard fz-16"></span>
</a>
`;
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('<tr><td colspan="5" class="text-center">Loading...</td></tr>');
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('<tr><td colspan="5" class="text-center">Failed to load data</td></tr>');
return;
}
VHistory.render(res.data);
},
error: (jqXHR) => {
$('#tHistoryMaintenanceBody').html('<tr><td colspan="5" class="text-center">Failed to load data</td></tr>');
Helper.toast('Error', 'just now', jqXHR.responseJSON?.meta?.message || 'Failed to load history');
},
});
} catch (e) {
$('#tHistoryMaintenanceBody').html('<tr><td colspan="5" class="text-center">Failed to load data</td></tr>');
}
},
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('<tr><td colspan="5" class="text-center">No data</td></tr>');
return;
}
let html = '';
rows.forEach((row) => {
const selectedIds = (row.idservice || '').split(',').map((v) => v.trim());
const options = VHistory.options_service
.map((opt) => `<option value="${opt.id}" ${selectedIds.includes(String(opt.id)) ? 'selected' : ''}>${opt.service_type}</option>`)
.join('');
const isChecked = Number(row.ismaintenance) === 1 ? 'checked' : '';
html += `
<tr data-hid="${row.id}">
<td>
<select class="form-select form-select-sm history-service" multiple disabled style="width:100%;">
${options}
</select>
</td>
<td>
<input type="number" class="form-control form-control-sm history-odometer" value="${row.odometer ?? ''}" disabled>
</td>
<td>
<input type="text" class="form-control form-control-sm history-date" value="${row.dates ?? ''}" disabled autocomplete="off">
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input history-ismaintenance" type="checkbox" role="switch" ${isChecked} disabled>
</div>
</td>
<td class="text-center">
<button type="button" class="btn btn-sm btn-outline-primary btnEditRow">Edit</button>
</td>
</tr>
`;
});
$('#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();
</script>
@endsection
@endsection