Files
gps-frontend/resources/views/menu_v1/vehicles.blade.php
meusinfirmary 3486855fff update
2025-06-17 00:09:48 +09:00

1974 lines
105 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@php
$user_role = Auth::user()->role;
@endphp
@extends('app.app')
@section('title')
Vehicles
@endsection
@section('customcss')
<style>
/* .select2-container {
z-index: 99999;
} */
/* .landscape-photo {
max-height: max(21vh, 210px);
} */
/* .thumb-img-table {
width: max(4vw, 75px);
height: max(4vh, 55px);
object-fit: cover;
} */
</style>
@endsection
@section('content')
<div class="container-fluid">
<div class="content">
<div class="card">
<div class="card-header">
<div class="row d-flex align-items-center">
<div class="col-3">
<p class="card-title text-bold mb-0">Fleet Manager</p>
</div>
@if ($user_role == \App\Models\Users::ROLE_VENDOR || $user_role == \App\Models\Users::ROLE_ADMIN)
<div class="col text-end">
<button id="btnMdlNewVhc" class="btn btn-sm btn-danger">Add New Vehicle</button>
</div>
{{-- <div class="col-auto text-end ps-0">
<button class="btn btn-sm btn-danger">Upload</button>
</div> --}}
@endif
<div class="col-auto text-end ps-0">
{{-- <button class="btn btn-sm btn-danger">Download</button> --}}
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="tVehicles" class="table table-hover dataTable">
<thead>
<tr class="">
<th class="">#</th>
<th class="text-center">Action</th>
<th class="">Vehicle</th>
<th class="">Tax Exp</th>
{{-- <th class="">Kir Exp</th> --}}
<th class="">Service Start</th>
@if ($user_role != \App\Models\Users::ROLE_VENDOR)
<th class="">Device ID</th>
@endif
<th class="">Type</th>
<th class="">Manufacture Year</th>
<th class=""><span class="text-nowrap">Mileage <span class="text-lowercase">(km)</span></span></th>
<th class="">Company</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlNewVhc" aria-labelledby="mdlNewVhcLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mdlNewVhcLabel">Add New Vehicle</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{{-- <form> --}}
<form id="vehicleForm" method="POST" enctype="multipart/form-data">
{{-- Vehicle Data --}}
<div class="mb-3">
<div class="border-bottom">
<h6>Vehicle Data</h6>
</div>
<div class="row mb-3">
<div class="col-5">
<label for="add-fvhc-img" class="col-form-label">Front Vehicle Photo:</label>
<br>
<img id="add-fvhc-img" class="img-fluid landscape-photo" style="max-height: 19.6vh" src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png" alt="add-fvhc-img">
<div id="add-group_fvhc_spinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="add-group_rotate_fvhc" class="pt-2 d-flex justify-content-start d-none">
<button type="button" class="btnRotateLeft btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-left"></i></button>
<button type="button" class="btnRotateRight btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-right"></i></button>
</div>
<input type="file" id="add-fvhc-file" class="form-control mt-3">
<input type="text" id="add-fvhc-base64" class="form-control" hidden>
<div>
<span id="add-fvhc-status"></span>
<span id="add-fvhc-filesize"></span>
</div>
</div>
<div class="col-7">
{{-- <div class="mb-3">
<label for="add-deviceid" class="col-form-label">Device ID:</label>
<select id="add-deviceid" class="form-control" style="width:100%;">
<option value="">Tidak dipilih</option>
@foreach ($devices as $device)
<option value="{{ $device->id }}" data-device_id="{{ $device->device_id }}" data-simcard="{{ $device->simcard }}" data-type="{{ $device->type }}">{{ $device->name . ' (' . implode(' ', str_split($device->device_id, 4)) . ')' }}</option>
@endforeach
</select>
</div> --}}
<div class="mb-0">
<label for="add-vhcname" class="col-form-label">Vehicle Name:</label>
<input type="text" id="add-vhcname" class="form-control" placeholder="">
</div>
<div class="mb-0">
<label for="add-brand" class="col-form-label">Brand:</label>
<select id="add-brand" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($brands as $brand)
<option value="{{ $brand->id }}">{{ $brand->name }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label for="add-type" class="col-form-label">Type:</label>
<select id="add-type" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($types as $type)
<option value="{{ $type->id }}">{{ $type->name }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label for="add-speedlimit" class="col-form-label">Speed Limit (kph):</label>
<input type="number" id="add-speedlimit" class="form-control">
</div>
</div>
</div>
</div>
{{-- Job Data --}}
{{-- <div class="mb-3">
<div class="border-bottom">
<h6>Job Data</h6>
</div>
<div class="row">
<div class="col-6">
<label for="add-dcurrent" class="col-form-label">Current Driver:</label>
<select id="add-dcurrent" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($drivers as $driver)
<option value="{{ $driver->id }}">
{{ $driver->fullname . ' (+' . $driver->phone_code . implode(' ', str_split($driver->phone, 4)) . ')' }}
</option>
@endforeach
</select>
</div>
<div class="col-6">
<label for="add-dassign" class="col-form-label">Assign Driver:</label>
<select id="add-dassign" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($drivers as $driver)
<option value="{{ $driver->id }}">
{{ $driver->fullname . ' (+' . $driver->phone_code . implode(' ', str_split($driver->phone, 4)) . ')' }}
</option>
@endforeach
</select>
</div>
</div>
</div> --}}
{{-- STNK Data --}}
<div class="mb-3">
<div class="border-bottom">
<h6>Certificate of Vehicle (CoV)</h6>
</div>
<div class="row">
<div class="col-5">
<label for="add-stnk-img" class="col-form-label">CoV Photo:</label>
<br>
<img id="add-stnk-img" class="img-fluid landscape-photo" src="https://cdn-2.tstatic.net/kaltim/foto/bank/images/ilustrasi-surat-tanda-nomor-kendaraan-bermotor-stnk.jpg" alt="add-stnk-img">
<div id="add-group_stnk_spinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="add-group_rotate_stnk" class="pt-2 d-flex justify-content-start d-none">
<button type="button" class="btnRotateLeft btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-left"></i></button>
<button type="button" class="btnRotateRight btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-right"></i></button>
</div>
<input type="file" id="add-stnk-file" class="form-control mt-3">
<input type="text" id="add-stnk-base64" class="form-control" hidden>
<div>
<span id="add-stnk-status"></span>
<span id="add-stnk-filesize"></span>
</div>
</div>
<div class="col-7">
<div class="mb-2">
<label for="add-stnk-exp" class="col-form-label">CoV Expired Date</label>
<input type="text" id="add-stnk-exp" class="form-control" readonly>
</div>
<div class="mb-3">
<label for="add-stnk-taxexp" class="col-form-label">Tax Expired Date</label>
<input type="string" id="add-stnk-taxexp" class="form-control" readonly>
</div>
<div class="mb-0">
<label for="add-nopol1" class="colr-form-label">License Plate Number</label>
<div class="row">
<div class="col">
<input type="text" id="add-nopol1" class="form-control" placeholder="ex: A-25-391">
</div>
<div class="col d-none">
<input type="number" id="add-nopol2" class="form-control" placeholder="ex: 3633">
</div>
<div class="col d-none">
<input type="text" id="add-nopol3" class="form-control" placeholder="ex: EEV">
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="add-stnk-vyear" class="col-form-label">Manufacture Year:</label>
<input type="number" id="add-stnk-vyear" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-cc" class="col-form-label">Cyclinder Capacity:</label>
<input type="number" id="add-stnk-cc" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-vin" class="col-form-label">Vehicle Identity Number:</label>
<input type="string" id="add-stnk-vin" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-en" class="col-form-label">Engine Number:</label>
<input type="string" id="add-stnk-en" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-color" class="col-form-label">Vehicle Color:</label>
<input type="string" id="add-stnk-color" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-fueltype" class="col-form-label">Type Fuel:</label>
<input type="string" id="add-stnk-fueltype" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-tnkbcolor" class="col-form-label">License Plat Color:</label>
<input type="string" id="add-stnk-tnkbcolor" class="form-control">
</div>
<div class="col-6">
<label for="add-stnk-regisyear" class="col-form-label">Registration Year:</label>
<input type="number" id="add-stnk-regisyear" class="form-control">
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Close</button>
<button id="btnSubmitNewVhc" type="button" class="btn btn-sm btn-danger">Submit data</button>
<div id="add-btnSubmitNewVhc" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlEdtVhc" aria-labelledby="mdlEdtVhcLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mdlEdtVhcLabel">Edit Vehicle</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
{{-- Vehicle Data --}}
<div class="mb-3">
<div class="border-bottom">
<h6>Vehicle Data</h6>
</div>
<div class="row mb-3">
<div class="col-5">
<label for="edt-fvhc-img" class="col-form-label">Front Vehicle Photo:</label>
<br>
<img id="edt-fvhc-img" class="img-fluid landscape-photo" style="max-height: 19.6vh" src="https://products.unitedtractors.com/wp-content/uploads/2021/03/udtruck-GWE370.png" alt="edt-fvhc-img">
<div id="edt-group_fvhc_spinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="edt-group_rotate_fvhc" class="pt-2 d-flex justify-content-start d-none">
<button type="button" class="btnRotateLeft btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-left"></i></button>
<button type="button" class="btnRotateRight btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-right"></i></button>
</div>
<input type="file" id="edt-fvhc-file" class="form-control mt-3">
<input type="text" id="edt-fvhc-base64" class="form-control" hidden>
<div>
<span id="edt-fvhc-status"></span>
<span id="edt-fvhc-filesize"></span>
</div>
</div>
<div class="col-7">
<div class="mb-3 d-none">
<label for="edt-deviceid" class="col-form-label">Device ID:</label>
<select id="edt-deviceid" class="form-control" style="width:100%;">
<option value="">Tidak dipilih</option>
@foreach ($devices as $device)
<option value="{{ $device->id }}" data-device_id="{{ $device->device_id }}" data-simcard="{{ $device->simcard }}" data-type="{{ $device->type }}">{{ $device->name . ' (' . implode(' ', str_split($device->device_id, 4)) . ')' }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label for="edt-vhcname" class="col-form-label">Vehicle Name:</label>
<input type="text" id="edt-vhcname" class="form-control" placeholder="">
</div>
<div class="mb-0">
<label for="edt-brand" class="col-form-label">Brand:</label>
<select id="edt-brand" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($brands as $brand)
<option value="{{ $brand->id }}">{{ $brand->name }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label for="edt-type" class="col-form-label">Type:</label>
<select id="edt-type" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($types as $type)
<option value="{{ $type->id }}">{{ $type->name }}</option>
@endforeach
</select>
</div>
<div class="mb-0">
<label for="edt-speedlimit" class="col-form-label">Speed Limit (kph):</label>
<input type="number" id="edt-speedlimit" class="form-control">
</div>
</div>
</div>
</div>
{{-- Job Data --}}
{{-- <div class="mb-3">
<div class="border-bottom">
<h6>Job Data</h6>
</div>
<div class="row">
<div class="col-6">
<label for="edt-dcurrent" class="col-form-label">Current Driver:</label>
<select id="edt-dcurrent" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($drivers as $driver)
<option value="{{ $driver->id }}">
{{ $driver->fullname . ' (+' . $driver->phone_code . implode(' ', str_split($driver->phone, 4)) . ')' }}
</option>
@endforeach
</select>
</div>
<div class="col-6">
<label for="edt-dassign" class="col-form-label">Assign Driver:</label>
<select id="edt-dassign" class="form-control" style="width:100%;">
<option value="">Choose</option>
@foreach ($drivers as $driver)
<option value="{{ $driver->id }}">
{{ $driver->fullname . ' (+' . $driver->phone_code . implode(' ', str_split($driver->phone, 4)) . ')' }}
</option>
@endforeach
</select>
</div>
</div>
</div> --}}
{{-- STNK Data --}}
<div class="mb-3">
<div class="border-bottom">
<h6>Certificate of Vehicle (CoV)</h6>
</div>
<div class="row">
<div class="col-5">
<label for="edt-stnk-img" class="col-form-label">CoV Photo:</label>
<br>
<img id="edt-stnk-img" class="img-fluid landscape-photo" src="https://cdn-2.tstatic.net/kaltim/foto/bank/images/ilustrasi-surat-tanda-nomor-kendaraan-bermotor-stnk.jpg" alt="edt-stnk-img">
<div id="edt-group_stnk_spinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="edt-group_rotate_stnk" class="pt-2 d-flex justify-content-start d-none">
<button type="button" class="btnRotateLeft btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-left"></i></button>
<button type="button" class="btnRotateRight btn btn-sm btn-outline-primary ml-1" style="padding:0.25rem 0.5rem;border-radius:0.25rem;"><i class="icon ion-arrow-return-right"></i></button>
</div>
<input type="file" id="edt-stnk-file" class="form-control mt-3">
<input type="text" id="edt-stnk-base64" class="form-control" hidden>
<div>
<span id="edt-stnk-status"></span>
<span id="edt-stnk-filesize"></span>
</div>
</div>
<div class="col-7">
<div class="mb-2">
<label for="add-stnk-exp" class="col-form-label">CoV Expired Date</label>
<input type="text" id="edt-stnk-exp" class="form-control" readonly>
</div>
<div class="mb-3">
<label for="edt-stnk-taxexp" class="col-form-label">Tax Expired:</label>
<input type="string" id="edt-stnk-taxexp" class="form-control" readonly>
</div>
<div class="mb-0">
<label for="add-nopol1" class="colr-form-label">License Plate Number</label>
<div class="row">
<div class="col">
<input type="text" id="edt-nopol1" class="form-control" placeholder="ex: B">
</div>
<div class="col d-none">
<input type="number" id="edt-nopol2" class="form-control" placeholder="ex: 3633">
</div>
<div class="col d-none">
<input type="text" id="edt-nopol3" class="form-control" placeholder="ex: EEV">
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="edt-stnk-vyear" class="col-form-label">Manufacture Year:</label>
<input type="number" id="edt-stnk-vyear" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-cc" class="col-form-label">Cyclinder Capacity:</label>
<input type="number" id="edt-stnk-cc" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-vin" class="col-form-label">Vehicle Identity Number:</label>
<input type="string" id="edt-stnk-vin" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-en" class="col-form-label">Engine Number:</label>
<input type="string" id="edt-stnk-en" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-color" class="col-form-label">Vehicle Color:</label>
<input type="string" id="edt-stnk-color" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-fueltype" class="col-form-label">Type Fuel:</label>
<input type="string" id="edt-stnk-fueltype" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-tnkbcolor" class="col-form-label">License Plat Color:</label>
<input type="string" id="edt-stnk-tnkbcolor" class="form-control">
</div>
<div class="col-6">
<label for="edt-stnk-regisyear" class="col-form-label">Registration Year:</label>
<input type="number" id="edt-stnk-regisyear" class="form-control">
</div>
</div>
</div>
</div>
</div>
{{-- Other Data --}}
{{-- @if ($user_role != \App\Models\Users::ROLE_VENDOR)
<div class="mb-3">
<div class="border-bottom">
<h6>Other Data</h6>
</div>
<div class="row">
<div class="col-6">
<label for="edt-vendor_id" class="col-form-label">Vendor:</label>
<select id="edt-vendor_id" class="form-control" style="width:100%;">
<option value="0">Vendor belum dipilih</option>
@foreach ($vendors as $vendor)
<option value="{{ $vendor->id }}">
{{ $vendor->first_name . ' (+' . $vendor->phone_code . implode(' ', str_split($vendor->phone, 4)) . ')' }}
</option>
@endforeach
</select>
</div>
</div>
</div>
@endif --}}
</form>
</div>
<div class="modal-footer">
<button type="button" id="btnDelVhc_updt" class="btn btn-sm btn-warning">Delete ?</button>
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Close</button>
<button id="btnSubmitEdtVhc" type="button" class="btn btn-sm btn-danger">Update data</button>
<div id="edt-btnSubmitEdtVhc" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlDelVhc" aria-labelledby="mdlDelVhcLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mdlDelVhcLabel">Delete Vehicle</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="d-flex justify-content-center">
<p class="mb-0">
Are you sure want to delete this vehicle
<a href="#" class="text-danger">
<span id="del-name"></span>
(<span id="del-nopol"></span>)
</a>
</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal">Close</button>
<button id="btnSubmitDelVhc" type="button" class="btn btn-sm btn-secondary">Yes, delete</button>
</div>
</div>
</div>
</div>
@endsection
@section('customjs')
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
<script>
'use strict';
const State = {
file_jimp_worker: "{{ asset('assets/js/worker/jimp.js') }}",
storage_lara: "{{ asset('storage') }}/",
dvc_type: {
built_in: "{{ \App\Models\Devices::TYPE_BUILT_IN }}",
portable: "{{ \App\Models\Devices::TYPE_PORTABLE }}",
},
};
const Wrapper = {
activate: function() {
Wrapper.event();
DTable.activate();
VNew.activate();
VEdt.activate();
VDel.activate();
Filter.activate();
// images
DUploadAdd.activate('fvhc');
DUploadAdd.activate('stnk');
DUploadEdt.activate('fvhc');
DUploadEdt.activate('stnk');
},
event: function() {
$('#add-device_id').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#add-brand').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#add-type').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#add-model').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#add-dcurrent').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#add-dassign').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#add-vendor_id').select2({
dropdownParent: $('#mdlNewVhc'),
});
$('#edt-device_id').select2({
dropdownParent: $('#mdlEdtVhc'),
});
$('#edt-brand').select2({
dropdownParent: $('#mdlEdtVhc'),
});
$('#edt-type').select2({
dropdownParent: $('#mdlEdtVhc'),
});
$('#edt-model').select2({
dropdownParent: $('#mdlEdtVhc'),
});
$('#edt-dcurrent').select2({
dropdownParent: $('#mdlEdtVhc'),
});
$('#edt-dassign').select2({
dropdownParent: $('#mdlEdtVhc'),
});
$('#edt-vendor_id').select2({
dropdownParent: $('#mdlEdtVhc'),
});
},
};
const DTable = {
activate: function() {
DTable.reload();
},
reload: function() {
// $('#tVehicles').DataTable();
// if (Driver.Table.firstInitDataTable == 1) { loadTableSkeletonLoading() } else { Driver.Table.firstInitDataTable = 1; }
$('#tVehicles').DataTable({
processing: true,
serverSide: false,
bLengthChange: true,
deferRender: true,
destroy: true,
ajax: {
url: "{{ route('api_list_vehicles') }}?cptid=" + AppState.current_company,
type: 'GET',
complete: function() {
// removeTableSkeletonLoading()
},
},
deferRender: true,
columns: [{
data: 'DT_RowIndex',
className: 'text-end',
visible: true,
orderable: true,
searchable: true,
},
{
data: 'action',
className: 'text-center',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
let action = `
<a href="#" class="text-decoration-none me-1 btnEdtVhc">
<span class="icon ion-edit fz-16"></span>
</a>
`;
// <a href="#" class="text-decoration-none text-danger btnDelVhc">
// <span class="icon ion-trash-b fz-16"></span>
// </a>
return action;
}
},
{
data: 'name',
className: 'text-start text-nowrap',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
return `
<img src="${State.storage_lara}${row.fvhc_img}" class="img-fluid thumb-img-table" /><br>
${row.nopol1} ${row.nopol2} ${row.nopol3}
`;
},
createdCell: function(td, cellData, rowData, row, col) {
$(td).attr('data-vid', rowData.vid);
$(td).attr('data-name', rowData.name);
$(td).attr('data-nopol1', rowData.nopol1);
$(td).attr('data-nopol2', rowData.nopol2);
$(td).attr('data-nopol3', rowData.nopol3);
},
},
// {
// data: 'stnk_img',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// // exp: ${row.stnk_exp?.split('-').reverse().join('-') || ''}
// return `
// <img src="${State.storage_lara}${data}" class="img-fluid thumb-img-table" /><br>
// ${row.nopol1} ${row.nopol2} ${row.nopol3}<br>
// exp: ${moment(row.stnk_exp).format('DD MMM YYYY') || '-'}
// `;
// },
// },
{
data: 'tax_exp',
className: 'text-end text-nowrap',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
// return (`${data?.split('-').reverse().join('-') || '-'}`);
return (`${moment(data).format('DD MMM YYYY') || '-'}`);
},
},
// {
// data: 'kir_exp',
// className: 'text-end text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${moment(data).format('DD MMM YYYY') || '-'}`);
// },
// },
{
data: 'crt',
className: 'text-end text-nowrap',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
return moment.unix(data).format('DD MMM YYYY');
},
},
@if ($user_role != \App\Models\Users::ROLE_VENDOR)
{
data: 'device_id',
className: 'text-end text-nowrap',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
return `<span class="d-none">${data}</span>` + Helper.splitEvery4Char(`${data}`);
},
},
@endif
// {
// data: 'dc_fullname',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (
// `${data}<br>` +
// `<a href="tel:0${row.dc_phone}">${Helper.splitEvery4Char('0'+row.dc_phone)}</a>` +
// ` || ` +
// `<a href="https://api.whatsapp.com/send/?phone=62${row.dc_phone}&text=Halo&app_absent=0" class="bg-light" target="_blank"><i class="text-success ion-social-whatsapp"></i></a>`
// );
// },
// },
// {
// data: 'da_fullname',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (
// `${data}<br>` +
// `<a href="tel:0${row.da_phone}">${Helper.splitEvery4Char('0'+row.da_phone)}</a>` +
// ` || ` +
// `<a href="https://api.whatsapp.com/send/?phone=62${row.da_phone}&text=Halo&app_absent=0" class="bg-light" target="_blank"><i class="text-success ion-social-whatsapp"></i></a>`
// );
// },
// },
{
data: 'type_name',
className: 'text-start text-nowrap',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
// return (`${row.brand_name}<br>-<br>${data}`);
return data;
},
},
{
data: 'vyear',
className: 'text-end',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
return (`${(data || '-')}`);
},
},
// {
// data: 'cc',
// className: 'text-start',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${(data || '0')} CC`);
// },
// },
// {
// data: 'vin',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${Helper.splitEvery4Char(data || '-')}`);
// },
// },
// {
// data: 'en',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${Helper.splitEvery4Char(data || '-')}`);
// },
// },
// {
// data: 'vcolor',
// className: 'text-start',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${(data || '-')}`);
// },
// },
// {
// data: 'fuel_type',
// className: 'text-start',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${(data || '-')}`);
// },
// },
// {
// data: 'tnkb_color',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${(data || '-')}`);
// },
// },
// {
// data: 'regis_year',
// className: 'text-end',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return (`${(data || '-')}`);
// },
// },
// {
// data: 'speed_limit',
// className: 'text-end',
// visible: true,
// orderable: true,
// searchable: true,
// },
// {
// data: 'fuel_capacity',
// className: 'text-end',
// visible: true,
// orderable: true,
// searchable: true,
// },
// {
// data: 'fuel_drop_treshold',
// className: 'text-end',
// visible: true,
// orderable: true,
// searchable: true,
// },
// {
// data: 'max_pressure',
// className: 'text-end',
// visible: true,
// orderable: true,
// searchable: true,
// },
// {
// data: 'alert_zones',
// className: 'text-start',
// visible: true,
// orderable: true,
// searchable: true,
// },
// {
// data: 'is_track_holiday_text',
// className: 'text-start',
// visible: true,
// orderable: true,
// searchable: true,
// },
// {
// data: 'track_schedule',
// className: 'text-end',
// visible: true,
// orderable: true,
// searchable: true,
// },
{
data: 'sum_milleage',
className: 'text-end',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
return Number(data).toFixed(2);
}
},
// {
// data: 'cameras',
// className: 'text-start',
// visible: true,
// orderable: true,
// searchable: true,
// },
{
data: 'company_name',
className: 'text-start text-nowrap',
visible: true,
orderable: true,
searchable: true,
render: function(data, type, row, meta) {
return data || '-';
}
},
// {
// data: 'group_name',
// className: 'text-start text-nowrap',
// visible: true,
// orderable: true,
// searchable: true,
// render: function(data, type, row, meta) {
// return data || 'All Group';
// }
// },
],
});
},
};
function safeVal(selector) {
const val = $(selector).val();
return (val === undefined || val === null || val === '') ? null : val;
}
const VNew = {
activate: function() {
VNew.event();
},
event: function() {
// Tampilkan modal saat tombol diklik
$('#btnMdlNewVhc').on('click', function() {
$('#mdlNewVhc').modal('show');
});
// Datepicker untuk tanggal
$('#add-stnk-exp').datepicker({
format: 'dd-mm-yyyy',
startDate: moment().add(1, 'days').toDate(),
});
$('#add-stnk-taxexp').datepicker({
format: 'dd-mm-yyyy',
startDate: moment().add(1, 'days').toDate(),
endDate: moment().add(6, 'month').toDate(),
});
// Reset input file saat diklik
$('#add-fvhc-file').on('click', function() {
$(this).val('');
});
$('#add-stnk-file').on('click', function() {
$(this).val('');
});
// Submit form
$('#btnSubmitNewVhc').on('click', function() {
let data = VNew.getData();
VNew.submitData(data);
});
},
getData: function() {
let data = new FormData();
data.append('vhc_name', safeVal('#add-vhcname'));
let selected_device = $('#add-deviceid :selected');
data.append('dvc_id', safeVal('#add-deviceid') ?? 0);
data.append('device_id', selected_device.data('device_id') ?? 0);
data.append('simcard', selected_device.data('simcard') ?? 0);
data.append('brand_id', safeVal('#add-brand'));
data.append('type_id', safeVal('#add-type'));
data.append('model_id', safeVal('#add-model') ?? 0);
data.append('speed_limit', safeVal('#add-speedlimit'));
data.append('fuel_capacity', safeVal('#add-fuelcapacity') ?? 0);
data.append('fuel_drop_treshold', safeVal('#add-fueldroptreshold') ?? 0);
data.append('max_pressure', safeVal('#add-maxpressure') ?? 0);
data.append('d_current', safeVal('#add-dcurrent') ?? 0);
data.append('d_assign', safeVal('#add-dassign') ?? 0);
// tanggal juga sama, pakai safeVal dan cek dulu
const stnkExp = safeVal('#add-stnk-exp');
if (stnkExp) data.append('stnk_exp', stnkExp.split('-').reverse().join('-'));
else data.append('stnk_exp', null);
data.append('nopol1', safeVal('#add-nopol1'));
data.append('stnk_vyear', safeVal('#add-stnk-vyear'));
data.append('cc', safeVal('#add-stnk-cc'));
data.append('vin', safeVal('#add-stnk-vin'));
data.append('en', safeVal('#add-stnk-en'));
data.append('color', safeVal('#add-stnk-color'));
data.append('fuel_type', safeVal('#add-stnk-fueltype'));
data.append('tnkb_color', safeVal('#add-stnk-tnkbcolor'));
data.append('regis_year', safeVal('#add-stnk-regisyear'));
const taxExp = safeVal('#add-stnk-taxexp');
if (taxExp) data.append('tax_exp', taxExp.split('-').reverse().join('-'));
else data.append('tax_exp', null);
data.append('vendor_id', safeVal('#add-vendor_id'));
// File input (cek ada file atau tidak)
const fvhcFile = $('#add-fvhc-file')[0].files[0];
if (fvhcFile) data.append('fvhc_file', fvhcFile);
const stnkFile = $('#add-stnk-file')[0].files[0];
if (stnkFile) data.append('stnk_file', stnkFile);
return data;
},
submitData: function(data) {
return new Promise((resolve, reject) => {
if ($('#btnSubmitNewVhc').is('[disabled]')) {
resolve({
type: 'fail'
});
return false;
}
$('#btnSubmitNewVhc').attr('disabled', true).addClass('d-none');
$('#add-btnSubmitNewVhc').removeClass('d-none');
$.ajax({
url: "{{ route('api_add_vehicle') }}",
method: 'POST',
crossDomain: true,
processData: false,
contentType: false,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
},
data: data,
success: (res) => {
$('#btnSubmitNewVhc').removeAttr('disabled').removeClass('d-none');
$('#add-btnSubmitNewVhc').addClass('d-none');
if (res.meta?.type !== 'success') {
Helper.toast('Warning', 'just now', res.meta?.message || 'Failed to add vehicle');
resolve({
type: 'fail'
});
return;
}
Helper.toast('Success', 'just now', 'Successfully added vehicle');
$('#mdlNewVhc').modal('hide');
DTable.reload();
resolve({
type: 'success'
});
},
error: (jqXHR) => {
$('#btnSubmitNewVhc').removeAttr('disabled').removeClass('d-none');
$('#add-btnSubmitNewVhc').addClass('d-none');
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Server error occurred, please try again');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON?.meta?.message || 'Error during submission');
}
resolve({
type: 'error'
});
}
});
});
}
};
$(function() {
VNew.activate();
});
const VEdt = {
activate: function() {
VEdt.event();
},
event: function() {
// modal
$('#tVehicles').on('click', '.btnEdtVhc', async function(e) {
let vid = $(e.target).closest('tr').find('td[data-vid]').data('vid');
VEdt.removeOptionDevice(State.dvc_type.portable);
let resp = await VEdt.reqData({
vid
});
if (resp.type != 'success') {
Helper.toast('Vehicle Not Found', 'just now', 'please try again');
return false;
}
VEdt.passDataToView(resp.data);
});
$('#mdlEdtVhc').on('shown.bs.modal', function() {
});
$('#btnSubmitEdtVhc').on('click', function() {
let data = VEdt.getData();
VEdt.submitData(data);
});
// datepicker
$('#edt-stnk-exp').datepicker({
format: 'dd-mm-yyyy',
startDate: moment().add(1, 'days').toDate(),
});
$('#edt-stnk-taxexp').datepicker({
format: 'dd-mm-yyyy',
startDate: moment().add(1, 'days').toDate(),
endDate: moment().add(6, 'month').toDate(),
});
$('#edt-kirexp').datepicker({
format: 'dd-mm-yyyy',
startDate: moment().add(1, 'days').toDate(),
endDate: moment().add(1, 'year').toDate(),
});
$('#edt-fvhc-file').on('click', function() {
$('#edt-fvhc-file').val('');
});
$('#edt-stnk-file').on('click', function() {
$('#edt-stnk-file').val('');
});
},
reqData: function(params) {
return new Promise((resolve, reject) => {
$.ajax({
url: "{{ route('api_show_vehicle', '') }}/" + params.vid,
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'
});
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', 'please try again');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error'
});
}
})
});
},
passDataToView: function(data) {
$('#edt-fvhc-filesize').html('');
$('#edt-fvhc-status').html('');
$('#edt-fvhc-base64').val('');
$('#edt-fvhc-file').val('');
$('#edt-fvhc-img').attr('src', State.storage_lara + data?.fvhc_img);
$('#edt-vhcname').val(data?.name);
let dvc_id = (data?.dvc_id) ? data?.dvc_id : '';
if (dvc_id == 0 || dvc_id == '') {} else {
if ($(`#edt-deviceid option[value='${dvc_id}']`).length < 1) {
$('#edt-deviceid').append(`<option value="${data?.dvc_id}" data-device_id="${data?.device_id}" data-simcard="${data?.simcard}" data-type="${data?.dvc_type}">${data?.dvc_name} (${Helper.splitEvery4Char(data?.device_id)})</option>`);
$('#edt-device_id').select2({
dropdownParent: $('#mdlEdtVhc'),
});
}
}
$('#edt-deviceid').val(dvc_id).trigger('change');
// $('#edt-deviceid').val(data?.device_id);
// $('#edt-simcard').val(data?.simcard);
$('#edt-brand').val(data?.brand_id).trigger('change');
$('#edt-type').val(data?.type_id).trigger('change');
$('#edt-model').val(data?.model_id).trigger('change');
$('#edt-speedlimit').val(data?.speed_limit);
$('#edt-fuelcapacity').val(data?.fuel_capacity);
$('#edt-fueldroptreshold').val(data?.fuel_drop_treshold);
$('#edt-maxpressure').val(data?.max_pressure);
$('#edt-dcurrent').val(data?.c_did).trigger('change');
$('#edt-dassign').val(data?.a_did).trigger('change');
$('#edt-stnk-filesize').html('');
$('#edt-stnk-status').html('');
$('#edt-stnk-base64').val('');
$('#edt-stnk-file').val('');
$('#edt-stnk-img').attr('src', State.storage_lara + data?.stnk_img);
$('#edt-stnk-exp').val(data?.stnk_exp?.split('-').reverse().join('-'));
$('#edt-nopol1').val(data?.nopol1);
$('#edt-nopol2').val(data?.nopol2);
$('#edt-nopol3').val(data?.nopol3);
$('#edt-stnk-vyear').val(data?.vyear);
$('#edt-stnk-cc').val(data?.cc);
$('#edt-stnk-vin').val(data?.vin);
$('#edt-stnk-en').val(data?.en);
$('#edt-stnk-color').val(data?.vcolor);
$('#edt-stnk-fueltype').val(data?.fuel_type);
$('#edt-stnk-tnkbcolor').val(data?.tnkb_color);
$('#edt-stnk-regisyear').val(data?.regis_year);
$('#edt-stnk-taxexp').val(data?.tax_exp?.split('-').reverse().join('-'));
$('#edt-kirexp').val(data?.kir_exp?.split('-').reverse().join('-'));
$('#edt-vendor_id').val(data?.vendor_id).trigger('change');
$('#mdlEdtVhc').data('id', data.vid);
$('#mdlEdtVhc').modal('show');
},
removeOptionDevice: function(type) {
$(`#edt-deviceid option[data-type='${type}']`).remove();
$('#edt-device_id').select2({
dropdownParent: $('#mdlEdtVhc'),
});
},
getData: function() {
let data = {};
data.vid = $('#mdlEdtVhc').data('id');
data.fvhc_base64 = $('#edt-fvhc-base64').val().replace(/^data:image\/(png|jpg|jpeg);base64,/, '');
data.vhc_name = $('#edt-vhcname').val();
// data.device_id = $('#edt-deviceid').val();
// data.simcard = $('#edt-simcard').val();
let selected_device = $('#edt-deviceid :selected');
data.dvc_id = selected_device.val();
data.device_id = selected_device.data('device_id');
data.simcard = selected_device.attr('simcard');
data.brand_id = $('#edt-brand').val();
data.type_id = $('#edt-type').val();
data.model_id = $('#edt-model').val();
data.speed_limit = $('#edt-speedlimit').val();
data.fuel_capacity = $('#edt-fuelcapacity').val();
data.fuel_drop_treshold = $('#edt-fueldroptreshold').val();
data.max_pressure = $('#edt-maxpressure').val();
data.d_current = $('#edt-dcurrent').val();
data.d_assign = $('#edt-dassign').val();
data.stnk_base64 = $('#edt-stnk-base64').val().replace(/^data:image\/(png|jpg|jpeg);base64,/, '');
data.stnk_exp = $('#edt-stnk-exp').val().split('-').reverse().join('-');
data.nopol1 = $('#edt-nopol1').val();
data.nopol2 = $('#edt-nopol2').val();
data.nopol3 = $('#edt-nopol3').val();
data.stnk_vyear = $('#edt-stnk-vyear').val();
data.cc = $('#edt-stnk-cc').val();
data.vin = $('#edt-stnk-vin').val();
data.en = $('#edt-stnk-en').val();
data.color = $('#edt-stnk-color').val();
data.fuel_type = $('#edt-stnk-fueltype').val();
data.tnkb_color = $('#edt-stnk-tnkbcolor').val();
data.regis_year = $('#edt-stnk-regisyear').val();
data.tax_exp = $('#edt-stnk-taxexp').val().split('-').reverse().join('-');
// data.kir_exp = $('#edt-kirexp').val().split('-').reverse().join('-');
data.vendor_id = $('#edt-vendor_id').val();
return data;
},
submitData: async function(data) {
return new Promise((resolve, reject) => {
if (typeof $('#btnSubmitEdtVhc').attr('disabed') != 'undefined') {
resolve({
type: 'fail'
});
return false;
}
$('#btnSubmitEdtVhc').attr('disabed', true);
$('#btnSubmitEdtVhc').addClass('d-none');
$('#edt-btnSubmitEdtVhc').removeClass('d-none');
$.ajax({
url: "{{ route('api_edit_vehicle', '') }}/" + data.vid,
method: 'PUT',
crossDomain: true,
processData: true,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
},
data: data,
success: (data, textStatus, jqXHR) => {
$('#btnSubmitEdtVhc').removeAttr('disabed');
$('#btnSubmitEdtVhc').removeClass('d-none');
$('#edt-btnSubmitEdtVhc').addClass('d-none');
if (data.meta.type != 'success') {
resolve({
type: 'fail'
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
Helper.toast('Success', 'just now', 'success update vehicle');
$('#mdlEdtVhc').modal('hide');
DTable.reload();
resolve({
type: 'success'
});
},
error: (jqXHR, textStatus, error) => {
$('#btnSubmitEdtVhc').removeAttr('disabed');
$('#btnSubmitEdtVhc').removeClass('d-none');
$('#edt-btnSubmitEdtVhc').addClass('d-none');
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Please try again');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error'
});
}
})
})
},
}
const VDel = {
activate: function() {
VDel.event();
},
event: function() {
// on table
$('#tVehicles').on('click', '.btnDelVhc', function(e) {
let row = $(e.target).closest('tr');
let vid = row.find('td[data-vid]').data('vid');
let name = row.find('td[data-name]').data('name');
let nopol1 = row.find('td[data-nopol1]').data('nopol1');
let nopol2 = row.find('td[data-nopol2]').data('nopol2');
let nopol3 = row.find('td[data-nopol3]').data('nopol3');
VDel.passDataToView({
vid,
name,
nopol1,
nopol2,
nopol3,
});
$('#mdlDelVhc').data('id', vid);
$('#mdlDelVhc').modal('show');
});
$('#btnSubmitDelVhc').on('click', function() {
let data = {
vid: $('#mdlDelVhc').data('id'),
};
VDel.submitData(data);
});
// on modal update
$('#btnDelVhc_updt').on('click', function(e) {
let data = VEdt.getData();
VDel.passDataToView({
vid: data.vid,
name: data.vhc_name,
nopol1: data.nopol1,
nopol2: data.nopol2,
nopol3: data.nopol3,
});
$('#mdlDelVhc').data('id', data.vid);
$('#mdlDelVhc').modal('show');
});
},
passDataToView: function(data) {
$('#del-name').text(data.name);
$('#del-nopol').text(`${data.nopol1} ${data.nopol2} ${data.nopol3}`);
},
submitData: async function(data) {
return new Promise((resolve, reject) => {
if (typeof $('#btnSubmitDelVhc').attr('disabed') != 'undefined') {
resolve({
type: 'fail'
});
return false;
}
$('#btnSubmitDelVhc').attr('disabed', true);
$.ajax({
url: "{{ route('api_del_vehicle', '') }}/" + data.vid,
method: 'DELETE',
crossDomain: true,
processData: true,
headers: {
'x-api-key': Helper.getCookie('_trtk'),
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
},
data: data,
success: (data, textStatus, jqXHR) => {
$('#btnSubmitDelVhc').removeAttr('disabed');
if (data.meta.type != 'success') {
resolve({
type: 'fail'
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
Helper.toast('Success', 'just now', 'success delete vehicle');
$('#mdlDelVhc').modal('hide');
$('#mdlEdtVhc').modal('hide');
DTable.reload();
resolve({
type: 'success'
});
},
error: (jqXHR, textStatus, error) => {
$('#btnSubmitDelVhc').removeAttr('disabed');
if (jqXHR.status >= 500) {
Helper.toast('Error', 'just now', 'Please try again');
} else {
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
.message);
}
resolve({
type: 'error'
});
}
})
})
},
}
const Filter = {
activate: function() {
Filter.event();
},
event: function() {},
triggerFilterCompany: function() {
DTable.reload();
},
}
async function convertImgHtmlToFile(imgHtml, imgWidth, imgHeight, mimeType, fileName) {
return new Promise((resolve, reject) => {
try {
let canvas = document.createElement("canvas")
// Draw image to canvas.
canvas.width = imgWidth
canvas.height = imgHeight
let ctx = canvas.getContext('2d')
ctx.drawImage(imgHtml, 0, 0)
// Convert canvas to ImageState.
let imageData = ctx.getImageData(0, 0, imgWidth, imgHeight)
// console.log(imageState.data.byteLength + ' bytes.')
// Convert canvas to Blob
canvas.toBlob((blob) => {
let newReader = new FileReader();
newReader.addEventListener('loadend', () => {
// Convert canvas to ArrayBuffer
let arrayBuffer = newReader.result
// console.log(arrayBuffer.byteLength + ' bytes.')
// Convert ArrayBuffer to Blob
// let blob = new Blob([arrayBuffer], {type: mimeType})
// Dispay Blob content in an Image.
// console.log(URL.createObjectURL(blob))
// Generate as file
let newFile = new File([arrayBuffer], fileName, {
type: mimeType,
lastModified: new Date(),
size: arrayBuffer.byteLength,
})
resolve(newFile)
});
newReader.readAsArrayBuffer(blob);
}, mimeType);
} catch (e) {
reject(e.message)
}
});
}
// Compress image: fvhc, stnk
const JimpWorkerAdd = {
worker_fvhc: null,
worker_stnk: null,
activate: function(x) {
let linkWorker = State.file_jimp_worker
this.setWorker(linkWorker, x, function(res) {
if (res.stts) {
let pureDataURL = res.data.replace(/^data:image\/(png|jpg|jpeg);base64,/, '')
let fileSize = window.atob(pureDataURL).length // in Byte
// (fileSize/1000) + ' Kb'
$('#add-group_' + x + '_spinner').addClass('d-none');
$('#add-' + x + '-status').html('Compressed')
$('#add-' + x + '-filesize').html('<samp>(' + fileSize / 1000 + ' Kb)</samp>')
$('#add-' + x + '-img').attr('src', res.data)
$('#add-' + x + '-img').removeClass('d-none');
$('#add-' + x + '-base64').val(res.data)
} else {
console.error(res.data)
}
$('.page-loader-wrapper').fadeOut()
});
},
runWorker: function(dataURL, x) {
$('#add-group_' + x + '_spinner').removeClass('d-none');
$('#add-' + x + '-img').addClass('d-none');
if (x == 'fvhc') {
this.worker_fvhc.postMessage(dataURL)
} else if (x == 'stnk') {
this.worker_stnk.postMessage(dataURL)
}
},
setWorker: function(urlFileJs, x, cbFinish) {
let worker = new Worker(urlFileJs);
worker.onmessage = function(e) {
// e = {status:(true,false), data:(dataURL)}
// append a new img element using the base 64 image
// let img = document.createElement('img');
// img.setAttribute('src', e.data);
// document.body.appendChild(img);
cbFinish(e.data);
};
if (x == 'fvhc') {
this.worker_fvhc = worker
} else if (x == 'stnk') {
this.worker_stnk = worker
}
}
}
const DUploadAdd = {
activate: function(x) {
this.initReader(x)
JimpWorkerAdd.activate(x)
this.event(x)
DRotateImgAdd.activate(x)
},
event: function(x) {
$('#add-' + x + '-choose').on('click', function(e) {
$('#add-' + x + '-file').trigger('click')
})
},
initReader: function(x) {
let reader = new FileReader();
reader = this.setEventFile(reader, x);
$('#add-' + x + '-file').on('change', async function(e) {
try {
if (browserBack()) return false;
let file = e.target.files[0];
let type = file.type.split('/');
if (type[1] == 'jpeg' || type[1] == 'png' || type[1] == 'jpg') {
$('.page-loader-wrapper').fadeIn()
// fix auto rotate when select file
let newImg = await loadImage(file, {
orientation: true
})
let newFile = await convertImgHtmlToFile(newImg.image, newImg
.originalWidth, newImg.originalHeight, file.type, file
.name)
DUploadAdd.readFile(reader, newFile);
$('#add-' + x + '-filesize').html('')
$('#add-' + x + '-status').html('Loading on compressing...')
// $('#add-' + x + '-img').attr('src', '')
$('#add-' + x + '-base64').val('')
} else {
Helper.toast('Validasi', 'just-now', 'Gambar tidak valid');
}
} catch (e) {
console.error(e.message)
}
})
},
setEventFile: function(reader, x) {
reader.onload = function(e) {
let data = e.target.result;
$('#add-' + x + '-img-old').attr('src',
data) // preview, -old mungkin kedepannya bakal diganti jadi -new
// $('#add-'+x+'-img-base64').val(data) // real-data
console.log('Compressing ' + x);
JimpWorkerAdd.runWorker(data, x)
DRotateImgAdd.toggleBtnRotate(x, 'show');
};
reader.onerror = function(err) {
$('.page-loader-wrapper').fadeOut()
$('#' + x).attr('hidden', true)
console.error(err);
};
reader.onabort = function(err) {
console.log(err);
}
return reader;
},
readFile: function(reader, file) {
// reader.readAsArrayBuffer(file);
reader.readAsDataURL(file);
},
}
const DRotateImgAdd = {
activate: function(id) {
this.event(id)
},
event: function(id) {
$('#add-group_rotate_' + id).on('click', '.btnRotateRight', function(e) {
DRotateImgAdd.rotateBase64Image($('#add-' + id + '-base64').val(), 90).then(
function(base64) {
DRotateImgAdd.updateImg(id, base64)
})
})
$('#add-group_rotate_' + id).on('click', '.btnRotateLeft', function(e) {
DRotateImgAdd.rotateBase64Image($('#add-' + id + '-base64').val(), -90).then(
function(base64) {
DRotateImgAdd.updateImg(id, base64)
})
})
},
rotateBase64Image: function(base64data, degrees) {
return new Promise((resolve, reject) => {
try {
let x = 0,
y = 0,
w = 0,
h = 0;
let canvas = document.createElement("canvas");
let image = document.createElement("img"); // new Image();
image.src = base64data; // image.src = 'data:image/jpg;base64,' + base64data;
image.onload = function() {
// current image size for processing rotate
w = image.width;
h = image.height;
let angle = degrees * Math.PI / 180.0; // angle/rads
let ctx = canvas.getContext("2d");
// new image size for after cropped
let c = Math.cos(angle);
let s = Math.sin(angle);
if (s < 0) {
s = -s;
}
if (c < 0) {
c = -c;
}
let rw = h * s + w * c;
let rh = h * c + w * s;
// set canvas size
canvas.width = rw;
canvas.height = rh;
// save the unrotated context of the canvas so we can restore it later
// the alternative is to untranslate & unrotate after drawing
ctx.save();
// draw the rect in the center of the newly sized canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// move to the center of the canvas
// ctx.translate(x+w/2, y+h/2); // ctx.translate(x, h);
// move to the upper left corner when rotating in 90deg increments
ctx.translate(Math.abs(w / 2 * Math.cos(angle) + h / 2 * Math.sin(angle)),
Math.abs(h / 2 * Math.cos(angle) + w / 2 * Math.sin(angle)));
// rotate the canvas to the specified degrees
ctx.rotate(angle); // ctx.rotate(180 * Math.PI / 180);
// move to the center of the canvas (origin)
ctx.translate(-x - w / 2, -y - h / 2);
// since the context is rotated, the image will be rotated also
ctx.drawImage(image, 0, 0, w, h);
// were done with the rotating so restore the unrotated context
ctx.restore();
// convert to base64
resolve(canvas.toDataURL('image/jpeg', 1.0));
};
} catch (err) {
reject(err);
}
});
},
updateImg: function(id, base64) {
// update data
let pureDataURL = base64.replace(/^data:image\/(png|jpg|jpeg);base64,/, '')
let fileSize = window.atob(pureDataURL).length // in Byte
// (fileSize/1000) + ' Kb'
$('#add-' + id + '-status').html('Compressing...')
$('#add-' + id + '-filesize').html('<samp>(' + fileSize / 1000 + ' Kb)</samp>')
$('#add-' + id + '-img').attr('src', base64)
$('#add-' + id + '-base64').val(base64) // real-data
// compress again because base64 from rotate is rather bigger in range 200kb than compress 50kb
JimpWorkerAdd.runWorker(base64, id);
// if (id == 'fvhc') {
// JimpWorkerAdd.worker_fvhc.postMessage(base64)
// } else if (id == 'stnk') {
// JimpWorkerAdd.worker_stnk.postMessage(base64)
// }
},
toggleBtnRotate: function(id, hide = 'hidden') {
if (hide == 'show') {
$('#add-group_rotate_' + id).removeClass('d-none')
return true;
}
$('#add-group_rotate_' + id).addClass('d-none')
return true;
},
}
const JimpWorkerEdt = {
worker_fvhc: null,
worker_stnk: null,
activate: function(x) {
let linkWorker = State.file_jimp_worker
this.setWorker(linkWorker, x, function(res) {
if (res.stts) {
let pureDataURL = res.data.replace(/^data:image\/(png|jpg|jpeg);base64,/, '')
let fileSize = window.atob(pureDataURL).length // in Byte
// (fileSize/1000) + ' Kb'
$('#edt-group_' + x + '_spinner').addClass('d-none');
$('#edt-' + x + '-status').html('Compressed')
$('#edt-' + x + '-filesize').html('<samp>(' + fileSize / 1000 + ' Kb)</samp>')
$('#edt-' + x + '-img').attr('src', res.data)
$('#edt-' + x + '-img').removeClass('d-none');
$('#edt-' + x + '-base64').val(res.data)
} else {
console.error(res.data)
}
$('.page-loader-wrapper').fadeOut()
});
},
runWorker: function(dataURL, x) {
$('#edt-group_' + x + '_spinner').removeClass('d-none');
$('#edt-' + x + '-img').addClass('d-none');
if (x == 'fvhc') {
this.worker_fvhc.postMessage(dataURL)
} else if (x == 'stnk') {
this.worker_stnk.postMessage(dataURL)
}
},
setWorker: function(urlFileJs, x, cbFinish) {
let worker = new Worker(urlFileJs);
worker.onmessage = function(e) {
// e = {status:(true,false), data:(dataURL)}
// append a new img element using the base 64 image
// let img = document.createElement('img');
// img.setAttribute('src', e.data);
// document.body.appendChild(img);
cbFinish(e.data);
};
if (x == 'fvhc') {
this.worker_fvhc = worker
} else if (x == 'stnk') {
this.worker_stnk = worker
}
}
}
const DUploadEdt = {
activate: function(x) {
this.initReader(x)
JimpWorkerEdt.activate(x)
this.event(x)
DRotateImgEdt.activate(x)
},
event: function(x) {
$('#edt-' + x + '-choose').on('click', function(e) {
$('#edt-' + x + '-file').trigger('click')
})
},
initReader: function(x) {
let reader = new FileReader();
reader = this.setEventFile(reader, x);
$('#edt-' + x + '-file').on('change', async function(e) {
try {
if (browserBack()) return false;
let file = e.target.files[0];
let type = file.type.split('/');
if (type[1] == 'jpeg' || type[1] == 'png' || type[1] == 'jpg') {
$('.page-loader-wrapper').fadeIn()
// fix auto rotate when select file
let newImg = await loadImage(file, {
orientation: true
})
let newFile = await convertImgHtmlToFile(newImg.image, newImg
.originalWidth, newImg.originalHeight, file.type, file
.name)
DUploadEdt.readFile(reader, newFile);
$('#edt-' + x + '-filesize').html('')
$('#edt-' + x + '-status').html('Loading on compressing...')
// $('#edt-' + x + '-img').attr('src', '')
$('#edt-' + x + '-base64').val('')
} else {
Helper.toast('Validasi', 'just-now', 'Gambar tidak valid');
}
} catch (e) {
console.error(e.message)
}
})
},
setEventFile: function(reader, x) {
reader.onload = function(e) {
let data = e.target.result;
$('#edt-' + x + '-img-old').attr('src',
data) // preview, -old mungkin kedepannya bakal diganti jadi -new
// $('#edt-'+x+'-img-base64').val(data) // real-data
console.log('Compressing ' + x);
JimpWorkerEdt.runWorker(data, x)
DRotateImgEdt.toggleBtnRotate(x, 'show');
};
reader.onerror = function(err) {
$('.page-loader-wrapper').fadeOut()
$('#' + x).attr('hidden', true)
console.error(err);
};
reader.onabort = function(err) {
console.log(err);
}
return reader;
},
readFile: function(reader, file) {
// reader.readAsArrayBuffer(file);
reader.readAsDataURL(file);
},
}
const DRotateImgEdt = {
activate: function(id) {
this.event(id)
},
event: function(id) {
$('#edt-group_rotate_' + id).on('click', '.btnRotateRight', function(e) {
DRotateImgEdt.rotateBase64Image($('#edt-' + id + '-base64').val(), 90).then(
function(base64) {
DRotateImgEdt.updateImg(id, base64)
})
})
$('#edt-group_rotate_' + id).on('click', '.btnRotateLeft', function(e) {
DRotateImgEdt.rotateBase64Image($('#edt-' + id + '-base64').val(), -90).then(
function(base64) {
DRotateImgEdt.updateImg(id, base64)
})
})
},
rotateBase64Image: function(base64data, degrees) {
return new Promise((resolve, reject) => {
try {
let x = 0,
y = 0,
w = 0,
h = 0;
let canvas = document.createElement("canvas");
let image = document.createElement("img"); // new Image();
image.src = base64data; // image.src = 'data:image/jpg;base64,' + base64data;
image.onload = function() {
// current image size for processing rotate
w = image.width;
h = image.height;
let angle = degrees * Math.PI / 180.0; // angle/rads
let ctx = canvas.getContext("2d");
// new image size for after cropped
let c = Math.cos(angle);
let s = Math.sin(angle);
if (s < 0) {
s = -s;
}
if (c < 0) {
c = -c;
}
let rw = h * s + w * c;
let rh = h * c + w * s;
// set canvas size
canvas.width = rw;
canvas.height = rh;
// save the unrotated context of the canvas so we can restore it later
// the alternative is to untranslate & unrotate after drawing
ctx.save();
// draw the rect in the center of the newly sized canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// move to the center of the canvas
// ctx.translate(x+w/2, y+h/2); // ctx.translate(x, h);
// move to the upper left corner when rotating in 90deg increments
ctx.translate(Math.abs(w / 2 * Math.cos(angle) + h / 2 * Math.sin(angle)),
Math.abs(h / 2 * Math.cos(angle) + w / 2 * Math.sin(angle)));
// rotate the canvas to the specified degrees
ctx.rotate(angle); // ctx.rotate(180 * Math.PI / 180);
// move to the center of the canvas (origin)
ctx.translate(-x - w / 2, -y - h / 2);
// since the context is rotated, the image will be rotated also
ctx.drawImage(image, 0, 0, w, h);
// were done with the rotating so restore the unrotated context
ctx.restore();
// convert to base64
resolve(canvas.toDataURL('image/jpeg', 1.0));
};
} catch (err) {
reject(err);
}
});
},
updateImg: function(id, base64) {
// update data
let pureDataURL = base64.replace(/^data:image\/(png|jpg|jpeg);base64,/, '')
let fileSize = window.atob(pureDataURL).length // in Byte
// (fileSize/1000) + ' Kb'
$('#edt-' + id + '-status').html('Compressing...')
$('#edt-' + id + '-filesize').html('<samp>(' + fileSize / 1000 + ' Kb)</samp>')
$('#edt-' + id + '-img').attr('src', base64)
$('#edt-' + id + '-base64').val(base64) // real-data
// compress again because base64 from rotate is rather bigger in range 200kb than compress 50kb
JimpWorkerEdt.runWorker(base64, id);
// if (id == 'fvhc') {
// JimpWorkerEdt.worker_fvhc.postMessage(base64)
// } else if (id == 'stnk') {
// JimpWorkerEdt.worker_stnk.postMessage(base64)
// }
},
toggleBtnRotate: function(id, hide = 'hidden') {
if (hide == 'show') {
$('#edt-group_rotate_' + id).removeClass('d-none')
return true;
}
$('#edt-group_rotate_' + id).edt - Class('d-none')
return true;
},
}
Wrapper.activate();
</script>
@endsection