Files
gps-frontend/resources/views/menu_v2/Checker_bak/_view.blade.php
meusinfirmary b9891d2f81 Initial commit
2025-04-22 14:33:37 +07:00

894 lines
48 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 = Auth::user();
@endphp
@extends('app.app')
@section('title')
User Checker
@endsection
@section('customcss')
<style>
.square-photo {
max-height: max(21vh, 210px);
max-width: max(21vh, 210px);
}
</style>
@endsection
@section('content')
<div class="container-fluid">
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="card">
<div class="card-header">
<div class="row d-flex align-items-top">
<div class="col-8">
{{-- <p class="card-title text-bold mb-0">#BKS00928887210001</p> --}}
<p class="card-title text-bold mb-0">#{{ $order->ord_code }}</p>
<p class="mb-0">Please make sure the data is in accordance with the goods
carried by our fleet</p>
</div>
<div class="col text-end">
<button class="btn btn-secondary btn-sm"
onclick="location.href='{{ route('view_user_checker') }}'">Back</button>
</div>
</div>
</div>
<div class="card-body">
{{-- @if ($order->status == \App\Models\Orders::STTS_WAIT || $order->status == \App\Models\Orders::STTS_CONFIRM || $order->status == \App\Models\Orders::STTS_CLIENT_PAY || $order->status == \App\Models\Orders::STTS_VENDOR_PAYED || $order->status == \App\Models\Orders::STTS_CLOSE || $order->status == \App\Models\Orders::STTS_CANCEL) --}}
@if (($user->chk_type == App\Models\Users::CHK_TYPE_PICKUP && $order->pck_chk_stts == \App\Models\OrdersPickups::CHK_STTS_SUBMIT) || ($user->chk_type == App\Models\Users::CHK_TYPE_DROP && $order->drop_chk_stts == \App\Models\OrdersDrops::CHK_STTS_SUBMIT))
@else
<div class="align-items-end d-flex justify-content-between">
<div class="d-none">
<label for="type_check" class="form-label">Location Type</label>
<select id="type_check" class="form-control form-control-sm select2">
<option value="" selected disabled>No type selected</option>
@if ($user->chk_type === App\Models\Users::CHK_TYPE_PICKUP)
<option value="{{ App\Models\Users::CHK_TYPE_PICKUP }}" selected>Pickup
</option>
@elseif ($user->chk_type === App\Models\Users::CHK_TYPE_DROP)
<option value="{{ App\Models\Users::CHK_TYPE_DROP }}" selected>Drop
</option>
@endif
</select>
</div>
</div>
<div class="align-items-end d-flex justify-content-between mb-3">
<div class="row">
<div class="col-sm-12 col-md-6">
<label for="add-general-img" class="form-label">Upload image Delivery
Order</label>
<br>
<img id="add-general-img" class="img-fluid square-photo d-none" src="#"
alt="add-general-img">
<div id="add-group_general_spinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="add-group_rotate_general" 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-general-file" class="form-control form-control-sm">
<input type="text" id="add-general-base64" class="form-control" hidden>
<div>
<span id="add-general-status"></span>
<span id="add-general-filesize"></span>
</div>
</div>
<div class="col-sm-12 col-md-6">
<label for="add-goods-img" class="form-label">Upload image Goods</label>
<br>
<img id="add-goods-img" class="img-fluid square-photo d-none" src="#"
alt="add-goods-img">
<div id="add-group_goods_spinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="add-group_rotate_goods" 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-goods-file" class="form-control form-control-sm">
<input type="text" id="add-goods-base64" class="form-control" hidden>
<div>
<span id="add-goods-status"></span>
<span id="add-goods-filesize"></span>
</div>
</div>
</div>
</div>
<div class="align-items-end d-flex justify-content-between">
<div class="">
<button class="btn btn-secondary btn-sm text-nowrap me-1 d-none" id="btnSave">
Save
</button>
<button class="btn btn-warning btn-sm text-nowrap me-1" id="btnEdt">
Edit Data
</button>
<button class="btn btn-warning btn-sm text-nowrap me-1" id="btnAdd">
Add Data
</button>
<button class="btn btn-danger btn-sm text-nowrap" id="btnSubmit">
Submit
</button>
<div id="btnSubmitSpinner" class="d-none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
</div>
<hr>
@endif
<div class="table-responsive">
<table class="table" id="tItems">
<thead>
<tr class="">
<th class="text-nowrap">#</th>
<th class="text-nowrap text-end"></th>
<th class="text-nowrap">Item Code</th>
<th class="text-wrap">Description</th>
{{-- <th class="text-nowrap text-center">Qty</th> --}}
<th class="text-nowrap text-center">Weight (Kg)</th>
{{-- <th class="text-nowrap text-center">Total Weight</th> --}}
<th class="text-nowrap text-center">Length (cm)</th>
<th class="text-nowrap text-center">Wide (cm)</th>
<th class="text-nowrap text-center">Height (cm)</th>
<th class="text-nowrap text-center">Volume (m&sup3;)</th>
{{-- <th class="text-nowrap text-center">Total Volume</th> --}}
</tr>
</thead>
<tbody>
@foreach ($items as $k => $v)
<tr class="">
<td class="text-nowrap">
{{ $k + 1 }}
<input type="number" name="" value="{{ $v->id }}"
class="input-table-id border-0 w-100 bg-white d-none" disabled>
</td>
<td class="text-nowrap text-end">
<a href="#" title="delete" class="text-secondary disabled btnDelete">
<span class="ion-close-circled fz-16"></span>
</a>
</td>
<td class="text-nowrap">
<span class="hide-table-item_code d-none">{{ $v->item_code }}</span>
<input type="text" name="" value="{{ $v->item_code }}"
class="input-table input-table-item_code border-0 w-100 bg-white"
disabled>
</td>
<td class="text-nowrap">
<span class="hide-table-desc d-none">{{ $v->desc }}</span>
<input type="text" name="" value="{{ $v->desc }}"
class="input-table input-table-desc border-0 w-100 bg-white"
disabled>
</td>
{{-- <td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->qty }}"
class="input-table input-table-qty border-0 text-end w-100 bg-white"
disabled>
</td> --}}
<td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->weight }}"
class="input-table input-table-weight border-0 text-end w-100 bg-white"
disabled>
</td>
{{-- <td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->weight * $v->qty }}"
class="input-table input-table-weight_total border-0 text-end w-100 bg-white" disabled>
</td> --}}
<td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->length }}"
class="input-table input-table-length border-0 text-end w-100 bg-white"
disabled>
</td>
<td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->wide }}"
class="input-table input-table-wide border-0 text-end w-100 bg-white"
disabled>
</td>
<td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->height }}"
class="input-table input-table-height border-0 text-end w-100 bg-white"
disabled>
</td>
<td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->volume }}"
class="input-table input-table-cbm border-0 text-end w-100 bg-white"
disabled>
</td>
{{-- <td class="text-nowrap text-end">
<input type="number" name="" value="{{ $v->volume * $v->qty }}"
class="input-table input-table-cbm_total border-0 text-end w-100 bg-white" disabled>
</td> --}}
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('customcss')
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.2.2/css/buttons.dataTables.min.css">
<link rel="stylesheet" href="https://editor.datatables.net/extensions/Editor/css/editor.dataTables.min.css">
@endsection
@section('customjs')
<script src="https://cdn.datatables.net/buttons/2.2.2/js/dataTables.buttons.min.js"></script>
<script src="https://editor.datatables.net/extensions/Editor/js/dataTables.editor.min.js"></script>
<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') }}/",
chk_pck_stts: {
no: "{{ App\Models\OrdersPickups::CHK_STTS_NO }}",
submit: "{{ App\Models\OrdersPickups::CHK_STTS_SUBMIT }}",
},
chk_drop_stts: {
no: "{{ App\Models\OrdersDrops::CHK_STTS_NO }}",
submit: "{{ App\Models\OrdersDrops::CHK_STTS_SUBMIT }}",
},
url_list: "{{ route('view_user_checker') }}",
ord_id: "{{ $order->ord_id }}",
isOnEdt: 0, // 0:no, 1:yes
tItems: null,
items_deleted: [],
};
const Wrapper = {
activate: function() {
Wrapper.event();
OrdView.activate();
// new images
ChkUpload.activate('general');
ChkUpload.activate('goods');
},
event: function() {
State.tItems = $('#tItems').DataTable({
"pageLength": 50
});
$('#btnEdt').on('click', function() {
$('#btnSave').removeClass('d-none');
$('#dataTable').addClass('table-hover');
OrdView.enableEdtInput();
State.isOnEdt = 1;
});
$('#btnAdd').on('click', function() {
let lastIndex = (State.tItems.rows()[0].length) + 1;
State.tItems.row.add([
`<td class="text-nowrap">
${lastIndex}
<input type="number" name="" value="0"
class="input-table-id border-0 w-100 bg-white d-none" disabled>
</td>`, // #
`<td class="text-nowrap text-end">
<a href="#" title="delete" class="text-secondary disabled btnDelete">
<span class="ion-close-circled fz-16"></span>
</a>
</td>`, // act_delete
`<td class="text-nowrap">
<span class="hide-table-item_code d-none">-</span>
<input type="text" name="" value="-"
class="input-table input-table-item_code border-0 w-100 bg-white"
disabled>
</td>`, // item_code
`<td class="text-nowrap">
<span class="hide-table-desc d-none">-</span>
<input type="text" name="" value="-"
class="input-table input-table-desc border-0 w-100 bg-white"
disabled>
</td>`, // desc
// `<td class="text-nowrap text-end">
// <input type="number" name="" value="0"
// class="input-table input-table-qty border-0 text-end w-100 bg-white"
// disabled>
// </td>`, // qty
`<td class="text-nowrap text-end">
<input type="number" name="" value="0"
class="input-table input-table-weight border-0 text-end w-100 bg-white"
disabled>
</td>`, // weight
// `<td class="text-nowrap text-end">
// <input type="number" name="" value="0"
// class="input-table input-table-weight_total border-0 text-end w-100 bg-white" disabled>
// </td>`, // weight_total
`<td class="text-nowrap text-end">
<input type="number" name="" value="0"
class="input-table input-table-length border-0 text-end w-100 bg-white"
disabled>
</td>`, // length
`<td class="text-nowrap text-end">
<input type="number" name="" value="0"
class="input-table input-table-wide border-0 text-end w-100 bg-white"
disabled>
</td>`, // wide
`<td class="text-nowrap text-end">
<input type="number" name="" value="0"
class="input-table input-table-height border-0 text-end w-100 bg-white"
disabled>
</td>`, // height
`<td class="text-nowrap text-end">
<input type="number" name="" value="0"
class="input-table input-table-cbm border-0 text-end w-100 bg-white"
disabled>
</td>`, // cbm
// `<td class="text-nowrap text-end">
// <input type="number" name="" value="0" class="input-table input-table-cbm_total border-0 text-end w-100 bg-white" disabled>
// </td>`, // cbm_total
]).draw(false);
State.tItems.page('last').draw(false);
});
$('#btnSave').on('click', function() {
$(this).addClass('d-none');
$('#dataTable').removeClass('table-hover');
OrdView.disableEdtInput();
State.isOnEdt = 0;
Wrapper.reChangeText();
});
$('#tItems').on('click', '.btnDelete', function(e) {
let tr = $(e.target).closest('tr');
let td = tr.find('td');
let item = {};
item.id = Number($(td.find('.input-table-id')).val());
item.item_code = $(td.find('.input-table-item_code')).val();
item.desc = $(td.find('.input-table-desc')).val();
item.qty = Number($(td.find('.input-table-qty')).val());
item.weight = Number($(td.find('.input-table-weight')).val());
// item.weight_total = Number($(td.find('.input-table-weight_total')).val());
item.length = Number($(td.find('.input-table-length')).val());
item.wide = Number($(td.find('.input-table-wide')).val());
item.height = Number($(td.find('.input-table-height')).val());
item.cbm = Number($(td.find('.input-table-cbm')).val());
State.items_deleted.push(item);
State.tItems.row(tr).remove().draw(true);
// tr.remove(); // not work on dataTable
});
// every change
$('#tItems').on('draw.dt', function(e, settings) {
if (State.isOnEdt) {
OrdView.enableEdtInput();
} else {
OrdView.disableEdtInput();
}
});
// pagination event
// $('#tItems').on('page.dt', function(e, settings) {
// });
},
reChangeText: function() {
State.tItems.rows().iterator('row', function(context, index) {
let tr = $(this.row(index).node());
let td = tr.find('td');
let item = {};
item.item_code = $(td.find('.input-table-item_code')).val()
$(td.find('.hide-table-item_code')).text(item.item_code);
item.desc = $(td.find('.input-table-desc')).val();
$(td.find('.hide-table-desc')).text(item.desc);
});
},
};
const OrdView = {
activate: function() {
OrdView.event();
},
event: function() {
$('#btnSubmit').on('click', async function(e) {
let data = OrdView.getData();
if (!data.items_isvalid) {
return false;
}
let isValid = await OrdView.checkData(data, true);
if (!isValid) {
return false;
}
let submitItems = await OrdView.submitItems(data);
});
},
getData: function() {
let data = {};
data.ord_id = State.ord_id;
data.type_check = $('#type_check').val();
data.weight = 0;
data.cbm = 0;
// data.qty_total = 0;
data.koli = 0;
data.items = [];
data.items_isvalid = true;
// let index = 0;
State.tItems.rows().iterator('row', function(context, index) {
let tr = $(this.row(index).node());
let td = tr.find('td');
let item = {};
item.index = index + 1;
item.id = Number($(td.find('.input-table-id')).val());
item.item_code = $(td.find('.input-table-item_code')).val();
item.desc = $(td.find('.input-table-desc')).val();
item.qty = Number($(td.find('.input-table-qty')).val());
item.weight = Number($(td.find('.input-table-weight')).val());
// item.weight_total = Number($(td.find('.input-table-weight_total')).val());
item.length = Number($(td.find('.input-table-length')).val());
item.wide = Number($(td.find('.input-table-wide')).val());
item.height = Number($(td.find('.input-table-height')).val());
item.cbm = Number($(td.find('.input-table-cbm')).val());
// item.cbm_total = Number($(td.find('.input-table-cbm_total')).val());
if (!isNaN(item.length) && !isNaN(item.wide) && !isNaN(item.height)) {
let calc_cbm = item.length * item.wide * item.height;
if (calc_cbm > item.cbm) {
item.cbm = calc_cbm;
}
}
// item.weight += (item.weight * item.qty);
// item.cbm += (item.cbm * item.qty);
// data.qty_total += item.qty;
data.koli++;
let isValid = OrdView.checkDataPerItem(item, true);
if (!isValid) {
data.items_isvalid = false;
return false;
}
for (let uniq_item of data.items) {
if (item.item_code.trim() == uniq_item.item_code.trim()) {
Helper.toast('Warning', 'just now', 'Item code ' + item.item_code + ' not uniq');
data.items_isvalid = false;
return false;
}
}
data.weight += item.weight;
data.cbm += item.cbm;
data.items.push(item);
// index++;
});
data.items_deleted = State.items_deleted;
data.general_base64 = $('#add-general-base64').val().replace(/^data:image\/(png|jpg|jpeg);base64,/,
'');
data.goods_base64 = $('#add-goods-base64').val().replace(/^data:image\/(png|jpg|jpeg);base64,/,
'');
return data;
},
checkData: function(data, isAlert = false) {
if (!data.items_isvalid) {
if (isAlert) Helper.toast('Warning', 'just now', 'Items not valid');
return false;
}
if (data.type_check == 1 || data.type_check == 2) {} else {
if (isAlert) Helper.toast('Warning', 'just now', 'Location type not selected');
return false;
}
if (State.isOnEdt == 1) {
if (isAlert) Helper.toast('Warning', 'just now', 'You are in edit mode');
return false;
}
// if (isNaN(data.qty_total)) {
// if (isAlert) Helper.toast('Warning', 'just now', 'qty not numeric');
// return false;
// }
// if (data.qty_total <= 0) {
// if (isAlert) Helper.toast('Warning', 'just now', 'qty cannot be zero 0');
// return false;
// }
if (data.koli <= 0) {
if (isAlert) Helper.toast('Warning', 'just now', 'at least there 1 package');
return false;
}
if (isNaN(data.weight) && isNaN(data.cbm)) {
if (isAlert) Helper.toast('Warning', 'just now',
'weight / volume must be provided at least 1 of them');
return false;
}
if (data.weight <= 0 && data.cbm <= 0) {
if (isAlert) Helper.toast('Warning', 'just now',
'weight / volume must be provided at least 1 of them');
return false;
}
if (data.general_base64.trim() == '') {
if (isAlert) Helper.toast('Warning', 'just now', 'Upload Image Delivery Order');
return false;
}
if (data.goods_base64.trim() == '') {
if (isAlert) Helper.toast('Warning', 'just now', 'Upload Image Goods');
return false;
}
return true;
},
checkDataPerItem: function(item, isAlert = false) {
if (State.isOnEdt == 1) {
if (isAlert) Helper.toast('Warning', 'just now', 'You are in edit mode');
return false;
}
// if (isNaN(item.qty)) {
// if (isAlert) Helper.toast('Warning', 'just now', 'qty not numeric on item code ' + item
// .item_code);
// return false;
// }
// if (item.qty <= 0) {
// if (isAlert) Helper.toast('Warning', 'just now', 'qty cannot be zero 0 on item code ' + item
// .item_code);
// return false;
// }
if (item.desc?.trim() == '' || item.desc == '-') {
if (isAlert) Helper.toast('Warning', 'just now', 'description cannot be empty on item code ' + item.item_code);
return false;
}
if (isNaN(item.weight) || isNaN(item.cbm)) {
if (isAlert) Helper.toast('Warning', 'just now',
'weight / volume must be numeric on item code ' + item.item_code);
return false;
}
if (item.weight <= 0 && item.cbm <= 0) {
if (isAlert) Helper.toast('Warning', 'just now',
'weight / volume must be provided at least 1 of them on item code ' + item.item_code);
return false;
}
return true;
},
enableEdtInput: function() {
$('.input-table').prop("disabled", false);
$('.btnDelete').removeClass('disabled text-secondary')
$('.btnDelete').addClass('text-danger');
},
disableEdtInput: function() {
$('.input-table').prop("disabled", true);
$('.btnDelete').addClass('disabled text-secondary');
$('.btnDelete').removeClass('text-danger');
},
submitItems: function(data) {
return new Promise((resolve, reject) => {
if (typeof $('#btnSubmit').attr('disabed') != 'undefined') {
resolve({
type: 'fail'
});
return false;
}
$('#btnSubmit').attr('disabed', true);
$('#btnSubmitSpinner').removeClass('d-none');
$('#btnSubmit').addClass('d-none');
$.ajax({
url: "{{ route('api_user_checker_submit_items', '') }}",
method: 'POST',
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) => {
$('#btnSubmitSpinner').addClass('d-none');
$('#btnSubmit').removeClass('d-none');
$('#btnSubmit').removeAttr('disabed');
if (data.meta.type != 'success') {
resolve({
type: 'fail'
});
Helper.toast('Warning', 'just now', data.meta.message);
return false;
}
resolve({
type: 'success',
resp: data,
});
window.location.href = State.url_list;
},
error: (jqXHR, textStatus, error) => {
$('#btnSubmitSpinner').addClass('d-none');
$('#btnSubmit').removeClass('d-none');
$('#btnSubmit').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'
});
}
})
});
},
};
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
const JimpWorkerAdd = {
worker_general: null,
worker_goods: 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').removeClass('d-none')
$('#add-' + x + '-img').attr('src', res.data)
$('#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');
if (x == 'general') {
this.worker_general.postMessage(dataURL)
} else if (x == 'goods') {
this.worker_goods.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 == 'general') {
this.worker_general = worker
} else if (x == 'goods') {
this.worker_goods = worker
}
}
}
const ChkUpload = {
activate: function(x) {
this.initReader(x)
JimpWorkerAdd.activate(x)
this.event(x)
ChkRotateImg.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)
ChkUpload.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)
ChkRotateImg.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 ChkRotateImg = {
activate: function(id) {
this.event(id)
},
event: function(id) {
$('#add-group_rotate_' + id).on('click', '.btnRotateRight', function(e) {
ChkRotateImg.rotateBase64Image($('#add-' + id + '-base64').val(), 90).then(
function(base64) {
ChkRotateImg.updateImg(id, base64)
})
})
$('#add-group_rotate_' + id).on('click', '.btnRotateLeft', function(e) {
ChkRotateImg.rotateBase64Image($('#add-' + id + '-base64').val(), -90).then(
function(base64) {
ChkRotateImg.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 == 'general') {
// JimpWorkerAdd.worker_general.postMessage(base64)
// } else if (id == 'goods') {
// JimpWorkerAdd.worker_goods.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;
},
}
Wrapper.activate();
</script>
@endsection