From 7a32a7e55113eb85348e489d5aef8730108d1ec3 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Wed, 10 Aug 2022 12:41:43 +0800 Subject: [PATCH 01/15] Add additional feature for registering customers with mykad reader --- config/mykad-reader.php | 8 ++ public/js/mykad-reader.js | 98 +++++++++++++++++++++++ resources/views/customers/index.blade.php | 7 ++ 3 files changed, 113 insertions(+) create mode 100644 config/mykad-reader.php create mode 100644 public/js/mykad-reader.js diff --git a/config/mykad-reader.php b/config/mykad-reader.php new file mode 100644 index 0000000..66eba30 --- /dev/null +++ b/config/mykad-reader.php @@ -0,0 +1,8 @@ + 'http://localhost:' . $x . '/?MYKADJSON'; + +return[ + 'endpoint' => env('MYKAD_SCANNER_endpoint', $getScannerEndpoint(env('MYKAD_SCANNER_PORT', $default_port))), +]; \ No newline at end of file diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js new file mode 100644 index 0000000..89548d0 --- /dev/null +++ b/public/js/mykad-reader.js @@ -0,0 +1,98 @@ + +let button_check_mykad = document.getElementById("button_check_mykad"); + +let getMyKadDetail = () => { + return fetch(mykad_reader_endpoint).then((response) => response.json()); +}; + +let checkIfMyKadExist = (myKadNumber) => { + const url = wakil_caricustomer_endpoint + '/?icno=' + myKadNumber; + + return fetch(url).then((response) => response.json()); +}; + + +let handleMyKadReader = () => { + + let myKadDetail; + + getMyKadDetail() + .then(response => myKadDetail = response[0]) + .then(() => checkIfMyKadExist(myKadDetail.IdNo)) + .then(response => response[0]) + .then(response => { + if (response === 'no-data') { + populateDaftarPelangganModal(myKadDetail); + } else { + let input_search_noic = document.getElementById("noic"); + let form_search_noic = document.querySelector("form[name='frmsearch']"); + input_search_noic.value = myKadDetail.IdNo; + form_search_noic.submit(); + } + }) + + +}; + +let populateDaftarPelangganModal = (data) => { + let modal_form = document.querySelector(".modal-body .row.form-group"); + + const religions = [ + ['01', 'Islam'], + ['02', 'Hindu'], + ['03', 'Buddha'], + ['04', 'Kristian'], + ['05', 'Lain-lain'], + ]; + + const ethnicities = [ + ['M', 'Melayu'], + ['C', 'Cina'], + ['I', 'India'], + ['L', 'Lain-lain'], + ]; + + let getCodeFromValue = (needle, haystack) => { + let title_cased_text = needle.split(' ') + .map(w => w[0].toUpperCase() + w.substring(1).toLowerCase()) + .join(' '); + + return haystack.filter(x => x[1] == title_cased_text)[0][0]; + }; + + let getFormattedDateOfBirth = (date_of_birth) => { + const [year, month, day] = date_of_birth.split('-'); + return day + '/' + month + '/' + year; + }; + + let getAgeFromDateOfBirth = (date_of_birth) => { + + const [birth_year, birth_month, birth_day] = date_of_birth.split('-'); + const count_leap_year = countLeapYears(birth_year, birth_month, birth_day) - 1; + + const start = new Date(date_of_birth), + end = new Date(), + diff = new Date(end - start), + days = ((diff / 1000 / 60 / 60 / 24) - count_leap_year) / 365; + + return parseInt(days); + }; + + modal_form.querySelector("input[name='name']").value = data.Name; + modal_form.querySelector("input[name='noic']").value = data.IdNo; + modal_form.querySelector("input[name='tarikh_lahir']").value = getFormattedDateOfBirth(data.DateOfBirth); + modal_form.querySelector("input[name='negeri_lahir']").value = data.State; + modal_form.querySelector("input[name='jantina']").value = data.Gender == 'L' ? 'Lelaki' : 'Perempuan'; + modal_form.querySelector("select[name='agama']").value = getCodeFromValue(data.Religion, religions); + modal_form.querySelector("textarea[name='alamat']").value = [data.Address1, data.Address2, data.Address3].join(", "); + modal_form.querySelector("input[name='poskod']").value = data.Postcode; + modal_form.querySelector("input[name='daerah']").value = data.Town; + modal_form.querySelector("input[name='negeri']").value = data.State; + modal_form.querySelector("input[name='age']").value = getAgeFromDateOfBirth(data.DateOfBirth); + modal_form.querySelector("select[name='bangsa']").value = getCodeFromValue(data.Ethnicity, ethnicities); + + calculatePassportAge(); + $('#daftar_pelanggan').modal('show'); +}; + +button_check_mykad.addEventListener("click", handleMyKadReader); diff --git a/resources/views/customers/index.blade.php b/resources/views/customers/index.blade.php index c6a3d0c..30830f5 100644 --- a/resources/views/customers/index.blade.php +++ b/resources/views/customers/index.blade.php @@ -894,4 +894,11 @@ } } + + @endsection From cc144c3e8587590ef7cd16b32a448c93d89651a9 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Wed, 10 Aug 2022 12:43:42 +0800 Subject: [PATCH 02/15] Add json wrapper to route's response so that it can be called via ajax --- app/Http/Controllers/CustomersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/CustomersController.php b/app/Http/Controllers/CustomersController.php index 5f7e35a..07169dd 100644 --- a/app/Http/Controllers/CustomersController.php +++ b/app/Http/Controllers/CustomersController.php @@ -115,7 +115,7 @@ class CustomersController extends Controller if(sizeof($customers_info) > 0) return $customers_info; else - return "no-data"; + return response(["no-data"], 200); } /** From 35d556c95abb77e5a5a7fa2bbfd237bca2416805 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Wed, 10 Aug 2022 12:52:50 +0800 Subject: [PATCH 03/15] Fix system missing controller error by renaming the controller in api route file --- routes/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/api.php b/routes/api.php index b4cc1cb..aa00183 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,7 +18,7 @@ Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); -Route::post('/chat-bot', 'CustomerController@listenToReplies'); +Route::post('/chat-bot', 'CustomersController@listenToReplies'); Route::group(['prefix' => 'dashboard'], function () { Route::post('/login', 'Auth\LoginController@loginDashboard'); From d08acfd2d2db4f1b8b111a40fbc65d31187baacd Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Wed, 10 Aug 2022 13:04:26 +0800 Subject: [PATCH 04/15] Fix variables, files term --- public/js/mykad-reader.js | 4 ++-- resources/views/customers/index.blade.php | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js index 89548d0..aa3be33 100644 --- a/public/js/mykad-reader.js +++ b/public/js/mykad-reader.js @@ -1,5 +1,5 @@ -let button_check_mykad = document.getElementById("button_check_mykad"); +let button_read_mykad = document.getElementById("button_read_mykad"); let getMyKadDetail = () => { return fetch(mykad_reader_endpoint).then((response) => response.json()); @@ -95,4 +95,4 @@ let populateDaftarPelangganModal = (data) => { $('#daftar_pelanggan').modal('show'); }; -button_check_mykad.addEventListener("click", handleMyKadReader); +button_read_mykad.addEventListener("click", handleMyKadReader); diff --git a/resources/views/customers/index.blade.php b/resources/views/customers/index.blade.php index 30830f5..5f0a1b5 100644 --- a/resources/views/customers/index.blade.php +++ b/resources/views/customers/index.blade.php @@ -37,6 +37,7 @@ + Baca MyKad @@ -895,10 +896,10 @@ } - + @endsection From 723f6954cda488c17451166b7aa97b92a0025701 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Wed, 10 Aug 2022 16:42:29 +0800 Subject: [PATCH 05/15] Add feature to detect citizenship and bumpitera right through mykad --- public/js/mykad-reader.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js index aa3be33..7f3fd91 100644 --- a/public/js/mykad-reader.js +++ b/public/js/mykad-reader.js @@ -18,6 +18,11 @@ let handleMyKadReader = () => { getMyKadDetail() .then(response => myKadDetail = response[0]) + .then(() => { + if (myKadDetail.ReadStatus === 'ERROR') { + throw new Error('Sila sambungkan pembaca MyKad dengan betul'); + } + }) .then(() => checkIfMyKadExist(myKadDetail.IdNo)) .then(response => response[0]) .then(response => { @@ -26,10 +31,11 @@ let handleMyKadReader = () => { } else { let input_search_noic = document.getElementById("noic"); let form_search_noic = document.querySelector("form[name='frmsearch']"); - input_search_noic.value = myKadDetail.IdNo; + input_search_noic.value = myKadDetail.IdNo; form_search_noic.submit(); } }) + .catch(error => alert(error)); }; @@ -78,11 +84,22 @@ let populateDaftarPelangganModal = (data) => { return parseInt(days); }; + let getBumiputeraStatus = (ethnicity) => { + + const non_bumiputera_ethnicity = ['INDIA', 'CINA']; + + let isBumiputera = !non_bumiputera_ethnicity.includes(ethnicity); + + return isBumiputera; + }; + modal_form.querySelector("input[name='name']").value = data.Name; modal_form.querySelector("input[name='noic']").value = data.IdNo; modal_form.querySelector("input[name='tarikh_lahir']").value = getFormattedDateOfBirth(data.DateOfBirth); modal_form.querySelector("input[name='negeri_lahir']").value = data.State; modal_form.querySelector("input[name='jantina']").value = data.Gender == 'L' ? 'Lelaki' : 'Perempuan'; + modal_form.querySelector("input[name='warganegara']").checked = data.Citizenship === 'WARGANEGARA' ? true : false; + modal_form.querySelector("input[name='bumiputera']").checked = getBumiputeraStatus(data.Ethnicity); modal_form.querySelector("select[name='agama']").value = getCodeFromValue(data.Religion, religions); modal_form.querySelector("textarea[name='alamat']").value = [data.Address1, data.Address2, data.Address3].join(", "); modal_form.querySelector("input[name='poskod']").value = data.Postcode; From a86b40c8bdbee13d28fa8b42e087815afb42ce8a Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Sun, 14 Aug 2022 15:10:59 +0800 Subject: [PATCH 06/15] Add display MyKad image --- public/js/mykad-reader.js | 33 +++++++++++++++++++++-- resources/views/customers/index.blade.php | 3 +++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js index 7f3fd91..7b111c7 100644 --- a/public/js/mykad-reader.js +++ b/public/js/mykad-reader.js @@ -1,8 +1,17 @@ let button_read_mykad = document.getElementById("button_read_mykad"); +let button_close_modal = document.querySelector("#daftar_pelanggan button.btn.btn-danger"); + +let removeCRLFfromString = (response_text) => { + return response_text.replace(/[\n\r]+/g, '').replace(/\s{2,10}/g, ' '); +}; + let getMyKadDetail = () => { - return fetch(mykad_reader_endpoint).then((response) => response.json()); + return fetch(mykad_reader_endpoint) + .then(response => response.text()) + .then(response => removeCRLFfromString(response)) + .then(response => JSON.parse(response)) }; let checkIfMyKadExist = (myKadNumber) => { @@ -35,7 +44,7 @@ let handleMyKadReader = () => { form_search_noic.submit(); } }) - .catch(error => alert(error)); + .catch(error => console.log(error)); }; @@ -93,6 +102,10 @@ let populateDaftarPelangganModal = (data) => { return isBumiputera; }; + let photo_container = document.getElementById("photo-mykad-container"); + let photo = document.getElementById("photo-mykad"); + photo.src = 'data:image/png;base64, ' + data.Photo; + modal_form.querySelector("input[name='name']").value = data.Name; modal_form.querySelector("input[name='noic']").value = data.IdNo; modal_form.querySelector("input[name='tarikh_lahir']").value = getFormattedDateOfBirth(data.DateOfBirth); @@ -109,7 +122,23 @@ let populateDaftarPelangganModal = (data) => { modal_form.querySelector("select[name='bangsa']").value = getCodeFromValue(data.Ethnicity, ethnicities); calculatePassportAge(); + + photo_container.classList.remove('d-none'); + photo_container.classList.add('d-flex'); + $('#daftar_pelanggan').modal('show'); }; + +let hideMykadPhoto = () => { + let photo = document.getElementById("photo-mykad"); + let photo_container = document.getElementById("photo-mykad-container"); + + photo.src = ''; + + photo_container.classList.add('d-none'); + photo_container.classList.remove('d-flex'); +}; + button_read_mykad.addEventListener("click", handleMyKadReader); +button_close_modal.addEventListener("click", hideMykadPhoto); diff --git a/resources/views/customers/index.blade.php b/resources/views/customers/index.blade.php index 5f0a1b5..bcd790b 100644 --- a/resources/views/customers/index.blade.php +++ b/resources/views/customers/index.blade.php @@ -62,6 +62,9 @@
@csrf
+
+ +
Nama
From 6d98730f4a9560abdac46bccbfc4572cd6280cd6 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Sun, 14 Aug 2022 15:48:28 +0800 Subject: [PATCH 07/15] Use sweet alert to show error message on card reader. not correctly enter the card --- public/js/mykad-reader.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js index 7b111c7..d357e2b 100644 --- a/public/js/mykad-reader.js +++ b/public/js/mykad-reader.js @@ -44,7 +44,12 @@ let handleMyKadReader = () => { form_search_noic.submit(); } }) - .catch(error => console.log(error)); + .catch(error => { + Swal.fire({ + icon: 'error', + title: error, + }); + }); }; From 8148c668f45a5485993b9f617bad804d71d8656a Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Mon, 29 Aug 2022 10:30:13 +0800 Subject: [PATCH 08/15] Throw additional error on fetch connection to card reader --- public/js/mykad-reader.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js index d357e2b..9141984 100644 --- a/public/js/mykad-reader.js +++ b/public/js/mykad-reader.js @@ -6,12 +6,16 @@ let removeCRLFfromString = (response_text) => { return response_text.replace(/[\n\r]+/g, '').replace(/\s{2,10}/g, ' '); }; +const myKad_reader_error = new Error('Sila sambungkan pembaca MyKad dengan betul'); let getMyKadDetail = () => { return fetch(mykad_reader_endpoint) .then(response => response.text()) .then(response => removeCRLFfromString(response)) .then(response => JSON.parse(response)) + .catch(error => { + throw myKad_reader_error; + }); }; let checkIfMyKadExist = (myKadNumber) => { @@ -29,7 +33,7 @@ let handleMyKadReader = () => { .then(response => myKadDetail = response[0]) .then(() => { if (myKadDetail.ReadStatus === 'ERROR') { - throw new Error('Sila sambungkan pembaca MyKad dengan betul'); + throw myKad_reader_error; } }) .then(() => checkIfMyKadExist(myKadDetail.IdNo)) From 6fcf201d12a340da2967c0fb4a914ad8247ecca9 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Tue, 18 Oct 2022 13:50:55 +0800 Subject: [PATCH 09/15] Add null coalesce statement to handle null values of gadai and listerah in app layout navbar --- resources/views/layouts/app.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index b3473ab..ba6d9d3 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -298,8 +298,8 @@ echo '
-
G : ' . count($gadai) . '
-
T : ' . count($listserah) . '
+
G : ' . $gadai ?? count($gadai) . '
+
T : ' . $listserah ?? count($listserah) . '
'; From 34331e09fc131a8b4d8cac28ee95dfeafae545b6 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Thu, 20 Oct 2022 11:11:15 +0800 Subject: [PATCH 10/15] Add new code on change card reader to Iris MyKad reader --- public/css/loader.css | 121 +++++++++ public/js/iris-mykad-websocket-client-api.js | 258 +++++++++++++++++++ public/js/mykad-reader-customer.js | 191 ++++++++++++++ public/js/mykad-reader.js | 153 ----------- resources/views/customers/index.blade.php | 8 +- resources/views/layouts/app.blade.php | 11 +- 6 files changed, 585 insertions(+), 157 deletions(-) create mode 100644 public/css/loader.css create mode 100644 public/js/iris-mykad-websocket-client-api.js create mode 100644 public/js/mykad-reader-customer.js delete mode 100644 public/js/mykad-reader.js diff --git a/public/css/loader.css b/public/css/loader.css new file mode 100644 index 0000000..e266e71 --- /dev/null +++ b/public/css/loader.css @@ -0,0 +1,121 @@ +/* Absolute Center Spinner */ +.loading { + position: fixed; + z-index: 999; + height: 2em; + width: 2em; + overflow: show; + margin: auto; + top: 0; + left: 0; + bottom: 0; + right: 0; + } + + /* Transparent Overlay */ + .loading:before { + content: ''; + display: block; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: radial-gradient(rgba(20, 20, 20,.8), rgba(0, 0, 0, .8)); + + background: -webkit-radial-gradient(rgba(20, 20, 20,.8), rgba(0, 0, 0,.8)); + } + + /* :not(:required) hides these rules from IE9 and below */ + .loading:not(:required) { + /* hide "loading..." text */ + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; + } + + .loading:not(:required):after { + content: ''; + display: block; + font-size: 10px; + width: 1em; + height: 1em; + margin-top: -0.5em; + -webkit-animation: spinner 150ms infinite linear; + -moz-animation: spinner 150ms infinite linear; + -ms-animation: spinner 150ms infinite linear; + -o-animation: spinner 150ms infinite linear; + animation: spinner 150ms infinite linear; + border-radius: 0.5em; + -webkit-box-shadow: rgba(255,255,255, 0.75) 1.5em 0 0 0, rgba(255,255,255, 0.75) 1.1em 1.1em 0 0, rgba(255,255,255, 0.75) 0 1.5em 0 0, rgba(255,255,255, 0.75) -1.1em 1.1em 0 0, rgba(255,255,255, 0.75) -1.5em 0 0 0, rgba(255,255,255, 0.75) -1.1em -1.1em 0 0, rgba(255,255,255, 0.75) 0 -1.5em 0 0, rgba(255,255,255, 0.75) 1.1em -1.1em 0 0; + box-shadow: rgba(255,255,255, 0.75) 1.5em 0 0 0, rgba(255,255,255, 0.75) 1.1em 1.1em 0 0, rgba(255,255,255, 0.75) 0 1.5em 0 0, rgba(255,255,255, 0.75) -1.1em 1.1em 0 0, rgba(255,255,255, 0.75) -1.5em 0 0 0, rgba(255,255,255, 0.75) -1.1em -1.1em 0 0, rgba(255,255,255, 0.75) 0 -1.5em 0 0, rgba(255,255,255, 0.75) 1.1em -1.1em 0 0; + } + + /* Animation */ + + @-webkit-keyframes spinner { + 0% { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @-moz-keyframes spinner { + 0% { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @-o-keyframes spinner { + 0% { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @keyframes spinner { + 0% { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); + } + } \ No newline at end of file diff --git a/public/js/iris-mykad-websocket-client-api.js b/public/js/iris-mykad-websocket-client-api.js new file mode 100644 index 0000000..6101f3d --- /dev/null +++ b/public/js/iris-mykad-websocket-client-api.js @@ -0,0 +1,258 @@ +WebSocketManager = { + url:"", + init: function(url) { + WebSocketManager.url = url; + }, + open: function(callback, slot) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"OPEN","Slot":"'+ slot +'"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + wsocket.close(); + callback(obj); + }; + + }, + listReader: function(callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"LIST_READER"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode); + }; + + }, + close: function(callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"CLOSE"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + wsocket.close(); + callback(obj); + }; + }, + verifyFPTemplate: function(callback, ThumbCode, Bas64FPLeft, Bas64FPRight) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"VERIFY_FP_TEMPLATE","ThumbCode":"'+ ThumbCode +'","Bas64FPLeft":"'+ Bas64FPLeft +'","Bas64FPRight":"'+ Bas64FPRight +'"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + wsocket.close(); + callback(obj.RespCode, obj.RespMessage); + }; + + }, + readMyKad: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"READ_MYKAD"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + readAllText: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"READ_ALL_TEXT"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + readPhoto: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"READ_PHOTO"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + readBio: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"READ_BIO"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + readMyKid: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"READ_MYKID"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioEnrol: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_ENROL"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + //var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(obj); + }; + }, + getThumbImage: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"GET_MYKAD_THUMB_IMAGE"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + getThumbBin1: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"GET_THUMB_BIN1"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + getThumbBin2: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"GET_THUMB_BIN2"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioEnrolBin1: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_ENROL_BIN1"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + //var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(obj); + }; + }, + FPBioEnrolBin2: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_ENROL_BIN2"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + //var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(obj); + }; + }, + FPBioVerify: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_VERIFY"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioVerifyBin: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_VERIFY_BIN"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioVerifyLeft: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_VERIFY_LEFT"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioVerifyBinLeft: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_VERIFY_BIN_LEFT"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioVerifyRight: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_VERIFY_RIGHT"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + }, + FPBioVerifyBinRight: function (callback) { + wsocket = new WebSocket(WebSocketManager.url); + wsocket.onopen = function () { + wsocket.send('{"Cmd":"FP_BIO_VERIFY_BIN_RIGHT"}'); + }; + wsocket.onmessage = function (evt) { + var obj = JSON.parse(evt.data); + var data = JSON.parse(obj.RespMessage); + wsocket.close(); + callback(data, obj.RespCode, obj.RespSW12AndApiName); + }; + } +} diff --git a/public/js/mykad-reader-customer.js b/public/js/mykad-reader-customer.js new file mode 100644 index 0000000..300a5b6 --- /dev/null +++ b/public/js/mykad-reader-customer.js @@ -0,0 +1,191 @@ + + +let button_read_mykad = document.getElementById("button_read_mykad"); +let button_close_modal = document.querySelector("#daftar_pelanggan button.btn.btn-danger"); + + let showLoader = () => { + let pageLoader = document.getElementById('page_loader'); + pageLoader.removeAttribute('class'); + pageLoader.classList.add('loading'); + }; + + let hideLoader = () => { + let pageLoader = document.getElementById('page_loader'); + pageLoader.removeAttribute('class'); + }; + + function handleMyKadReader() + { + showLoader(); + WebSocketManager.init("wss://localhost:5963/mykadwebsocket"); + WebSocketManager.listReader(callbackDoneGetListCardReader); + } + + function callbackDoneGetListCardReader(data, respcode) + { + if(respcode === -1){ + console.log({'location': 'callbackDoneGetListCardReader', 'data' : data} ); + } + + let slots = data.toString().split(','); + WebSocketManager.open(doneOpenReaderConnection, slots[0]); + } + + function doneOpenReaderConnection(data) + { + WebSocketManager.readMyKad(callBackAfterReadMykad); + } + + function callBackAfterReadMykad(data, respcode, sw12AndApiName) + { + if(respcode !== 0){ + hideLoader(); + Swal.fire({icon: 'error', title: sw12AndApiName,}); + return; + } + + checkIfMyKadExists(data.IDNum) + .then(response => response[0]) + .then(response => { + if (response === 'no-data') { + populateDaftarPelangganModal(data); + } else { + let input_search_noic = document.getElementById("noic"); + let form_search_noic = document.querySelector("form[name='frmsearch']"); + + let getMyKadNumberWithoutHypens = myKadNumber => myKadNumber.replace(/-/g, ''); + input_search_noic.value = getMyKadNumberWithoutHypens(data.IDNum); + form_search_noic.submit(); + } + }) + .catch(error => { + Swal.fire({ + icon: 'error', + title: error, + }); + }); + + hideLoader(); + } + + function checkIfMyKadExists(myKadNumber){ + let myKadNumberWithoutHyphens = myKadNumber.replace(/-/g, ''); + + const url = wakil_caricustomer_endpoint + '/?icno=' + myKadNumberWithoutHyphens; + return fetch(url).then((response) => response.json()); + } + + let populateDaftarPelangganModal = (data) => { + $('#daftar_pelanggan').modal('show'); + let modal_form = document.querySelector(".modal-body .row.form-group"); + + const religions = [ + ['01', 'Islam'], + ['02', 'Hindu'], + ['03', 'Buddha'], + ['04', 'Kristian'], + ['05', 'Lain-lain'], + ]; + + const races = [ + ['M', 'Melayu'], + ['C', 'Cina'], + ['I', 'India'], + ['L', 'Lain-lain'], + ]; + + let getCodeFromValue = (needle, haystack) => { + let title_cased_text = needle.split(' ') + .map(w => w[0].toUpperCase() + w.substring(1).toLowerCase()) + .join(' '); + + return haystack.filter(x => x[1] == title_cased_text)[0][0]; + }; + + let getMyKadNumberWithoutHypens = (IDNum) => { + return IDNum.replace(/-/g, ''); + } + + let getFormattedDateOfBirth = (date_of_birth) => { + + let date_of_birth_hyphenated = date_of_birth.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3"); + + const [year, month, day] = date_of_birth_hyphenated.split('-'); + return day + '/' + month + '/' + year; + }; + + let getAgeFromDateOfBirth = (date_of_birth) => { + + let date_of_birth_hyphenated = date_of_birth.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3"); + + const [birth_year, birth_month, birth_day] = date_of_birth_hyphenated.split('-'); + + let formatBirthMonth = (birth_month) => { + let newbirthMonth = birth_month < 9 ? birth_month[1] : birth_month; + return newbirthMonth; + }; + + const count_leap_year = countLeapYears(birth_year, formatBirthMonth(birth_month), birth_day) - 1; + + const start = new Date(date_of_birth_hyphenated), + end = new Date(), + diff = new Date(end - start), + days = ((diff / 1000 / 60 / 60 / 24) - count_leap_year) / 365; + + return parseInt(days); + }; + + let getBumiputeraStatus = (race) => { + + const non_bumiputera_ethnicity = ['INDIA', 'CINA']; + + let isBumiputera = !non_bumiputera_ethnicity.includes(race); + + return isBumiputera; + }; + + let photo_container = document.getElementById("photo-mykad-container"); + let photo = document.getElementById("photo-mykad"); + photo.src = 'data:image/jpeg;base64, ' + data.Base64Photo; + + modal_form.querySelector("input[name='name']").value = data.Name; + modal_form.querySelector("input[name='noic']").value = getMyKadNumberWithoutHypens(data.IDNum); + modal_form.querySelector("input[name='tarikh_lahir']").value = getFormattedDateOfBirth(data.BirthDate); + modal_form.querySelector("input[name='negeri_lahir']").value = data.BirthPlace; + modal_form.querySelector("input[name='jantina']").value = data.Gender == 'LELAKI' ? 'Lelaki' : 'Perempuan'; + modal_form.querySelector("input[name='warganegara']").checked = data.Citizenship === 'WARGANEGARA' ? true : false; + modal_form.querySelector("input[name='bumiputera']").checked = getBumiputeraStatus(data.Race); + modal_form.querySelector("select[name='agama']").value = getCodeFromValue(data.Religion, religions); + modal_form.querySelector("textarea[name='alamat']").value = [data.Address1, data.Address2, data.Address3].join(", "); + + let getPostCode = (postCodeCity) => postCodeCity.replace(/\D/g, ''); + modal_form.querySelector("input[name='poskod']").value = getPostCode(data.PostcodeCity); + + let getCityName = (postCodeCity) => postCodeCity.replace(/\d/g, ''); + modal_form.querySelector("input[name='daerah']").value = getCityName(data.PostcodeCity); + + modal_form.querySelector("input[name='negeri']").value = data.State; + modal_form.querySelector("input[name='age']").value = getAgeFromDateOfBirth(data.BirthDate); + modal_form.querySelector("select[name='bangsa']").value = getCodeFromValue(data.Race, races); + + calculatePassportAge(); + + photo_container.classList.remove('d-none'); + photo_container.classList.add('d-flex'); + + $('#daftar_pelanggan').modal('show'); +} + + +let hideMykadPhoto = () => { + let photo = document.getElementById("photo-mykad"); + let photo_container = document.getElementById("photo-mykad-container"); + + photo.src = ''; + + photo_container.classList.add('d-none'); + photo_container.classList.remove('d-flex'); +}; + +button_read_mykad.addEventListener("click", handleMyKadReader); +button_close_modal.addEventListener("click", hideMykadPhoto); diff --git a/public/js/mykad-reader.js b/public/js/mykad-reader.js deleted file mode 100644 index 9141984..0000000 --- a/public/js/mykad-reader.js +++ /dev/null @@ -1,153 +0,0 @@ - -let button_read_mykad = document.getElementById("button_read_mykad"); -let button_close_modal = document.querySelector("#daftar_pelanggan button.btn.btn-danger"); - -let removeCRLFfromString = (response_text) => { - return response_text.replace(/[\n\r]+/g, '').replace(/\s{2,10}/g, ' '); -}; - -const myKad_reader_error = new Error('Sila sambungkan pembaca MyKad dengan betul'); - -let getMyKadDetail = () => { - return fetch(mykad_reader_endpoint) - .then(response => response.text()) - .then(response => removeCRLFfromString(response)) - .then(response => JSON.parse(response)) - .catch(error => { - throw myKad_reader_error; - }); -}; - -let checkIfMyKadExist = (myKadNumber) => { - const url = wakil_caricustomer_endpoint + '/?icno=' + myKadNumber; - - return fetch(url).then((response) => response.json()); -}; - - -let handleMyKadReader = () => { - - let myKadDetail; - - getMyKadDetail() - .then(response => myKadDetail = response[0]) - .then(() => { - if (myKadDetail.ReadStatus === 'ERROR') { - throw myKad_reader_error; - } - }) - .then(() => checkIfMyKadExist(myKadDetail.IdNo)) - .then(response => response[0]) - .then(response => { - if (response === 'no-data') { - populateDaftarPelangganModal(myKadDetail); - } else { - let input_search_noic = document.getElementById("noic"); - let form_search_noic = document.querySelector("form[name='frmsearch']"); - input_search_noic.value = myKadDetail.IdNo; - form_search_noic.submit(); - } - }) - .catch(error => { - Swal.fire({ - icon: 'error', - title: error, - }); - }); - - -}; - -let populateDaftarPelangganModal = (data) => { - let modal_form = document.querySelector(".modal-body .row.form-group"); - - const religions = [ - ['01', 'Islam'], - ['02', 'Hindu'], - ['03', 'Buddha'], - ['04', 'Kristian'], - ['05', 'Lain-lain'], - ]; - - const ethnicities = [ - ['M', 'Melayu'], - ['C', 'Cina'], - ['I', 'India'], - ['L', 'Lain-lain'], - ]; - - let getCodeFromValue = (needle, haystack) => { - let title_cased_text = needle.split(' ') - .map(w => w[0].toUpperCase() + w.substring(1).toLowerCase()) - .join(' '); - - return haystack.filter(x => x[1] == title_cased_text)[0][0]; - }; - - let getFormattedDateOfBirth = (date_of_birth) => { - const [year, month, day] = date_of_birth.split('-'); - return day + '/' + month + '/' + year; - }; - - let getAgeFromDateOfBirth = (date_of_birth) => { - - const [birth_year, birth_month, birth_day] = date_of_birth.split('-'); - const count_leap_year = countLeapYears(birth_year, birth_month, birth_day) - 1; - - const start = new Date(date_of_birth), - end = new Date(), - diff = new Date(end - start), - days = ((diff / 1000 / 60 / 60 / 24) - count_leap_year) / 365; - - return parseInt(days); - }; - - let getBumiputeraStatus = (ethnicity) => { - - const non_bumiputera_ethnicity = ['INDIA', 'CINA']; - - let isBumiputera = !non_bumiputera_ethnicity.includes(ethnicity); - - return isBumiputera; - }; - - let photo_container = document.getElementById("photo-mykad-container"); - let photo = document.getElementById("photo-mykad"); - photo.src = 'data:image/png;base64, ' + data.Photo; - - modal_form.querySelector("input[name='name']").value = data.Name; - modal_form.querySelector("input[name='noic']").value = data.IdNo; - modal_form.querySelector("input[name='tarikh_lahir']").value = getFormattedDateOfBirth(data.DateOfBirth); - modal_form.querySelector("input[name='negeri_lahir']").value = data.State; - modal_form.querySelector("input[name='jantina']").value = data.Gender == 'L' ? 'Lelaki' : 'Perempuan'; - modal_form.querySelector("input[name='warganegara']").checked = data.Citizenship === 'WARGANEGARA' ? true : false; - modal_form.querySelector("input[name='bumiputera']").checked = getBumiputeraStatus(data.Ethnicity); - modal_form.querySelector("select[name='agama']").value = getCodeFromValue(data.Religion, religions); - modal_form.querySelector("textarea[name='alamat']").value = [data.Address1, data.Address2, data.Address3].join(", "); - modal_form.querySelector("input[name='poskod']").value = data.Postcode; - modal_form.querySelector("input[name='daerah']").value = data.Town; - modal_form.querySelector("input[name='negeri']").value = data.State; - modal_form.querySelector("input[name='age']").value = getAgeFromDateOfBirth(data.DateOfBirth); - modal_form.querySelector("select[name='bangsa']").value = getCodeFromValue(data.Ethnicity, ethnicities); - - calculatePassportAge(); - - photo_container.classList.remove('d-none'); - photo_container.classList.add('d-flex'); - - $('#daftar_pelanggan').modal('show'); -}; - - -let hideMykadPhoto = () => { - let photo = document.getElementById("photo-mykad"); - let photo_container = document.getElementById("photo-mykad-container"); - - photo.src = ''; - - photo_container.classList.add('d-none'); - photo_container.classList.remove('d-flex'); -}; - -button_read_mykad.addEventListener("click", handleMyKadReader); -button_close_modal.addEventListener("click", hideMykadPhoto); diff --git a/resources/views/customers/index.blade.php b/resources/views/customers/index.blade.php index bcd790b..426962d 100644 --- a/resources/views/customers/index.blade.php +++ b/resources/views/customers/index.blade.php @@ -898,11 +898,15 @@ } } + +@push('additional_scripts') - + + +@endpush + @endsection diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index ba6d9d3..b0f130f 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -21,6 +21,7 @@ + @@ -91,6 +92,7 @@ } @endphp
+
@@ -456,7 +456,7 @@ // Construct URLSearchParams object instance from current URL querystring. var queryParams = new URLSearchParams(window.location.search); - + let updated_icno = document.querySelector('#daftar_pelanggan input[name="noic"]').value queryParams.set("noic", updated_icno); @@ -916,7 +916,7 @@ From 3bd2fc13958e0dd249d41cf0ad626fb95b9af455 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Thu, 23 Feb 2023 14:08:42 +0800 Subject: [PATCH 13/15] Update MyKad reader implementation - prevent teller from overriding name, religion, address, and other sensitive fields if using MyKad reader - add support for Google Chrome browser ver. 64 backward compatible with branches PC - enhance error message handling when scanning if there is no card reader connected, no card is inserted in card reader, and if card reader is entered incorrectly --- public/js/mykad-reader-customer.js | 95 ++++++-- resources/views/customers/index.blade.php | 278 +++++++++++++++++++++- 2 files changed, 352 insertions(+), 21 deletions(-) diff --git a/public/js/mykad-reader-customer.js b/public/js/mykad-reader-customer.js index 4c7efb5..caca8e5 100644 --- a/public/js/mykad-reader-customer.js +++ b/public/js/mykad-reader-customer.js @@ -1,7 +1,6 @@ - let button_read_mykad = document.getElementById("button_read_mykad"); -let button_close_modal = document.querySelector("#daftar_pelanggan button.btn.btn-danger"); +let button_close_modal = document.querySelector("#daftar_pelanggan_mykad_reader button.btn.btn-danger"); let original_photo_loader = document.querySelector("#photo-mykad").src; let showLoader = () => { @@ -25,10 +24,21 @@ let original_photo_loader = document.querySelector("#photo-mykad").src; function callbackDoneGetListCardReader(data, respcode) { console.log('done get list card reader'); + if(respcode === -1){ console.log({'location': 'callbackDoneGetListCardReader', 'data' : data} ); } + let isDevicesConnected = Object.keys(data).length > 0; + + if(! isDevicesConnected){ + hideLoader(); + + Swal.fire({ icon: 'error', title: 'Pembaca MyKad tidak dapat dikesan, sila periksa sambungan', }); + + return; + } + let slots = data.toString().split(','); WebSocketManager.open(doneOpenReaderConnection, slots[0]); } @@ -38,18 +48,44 @@ let original_photo_loader = document.querySelector("#photo-mykad").src; WebSocketManager.readAllText(callBackAfterReadMykad); } + function handleMyKadReaderError(sw12AndApiName) + { + hideLoader(); + + let error_handler_dictionary = { + '0x80100069' : 'Tiada MyKad dikesan, sila masukkan Mykad untuk dibaca', + '0x80100066' : 'MyKad mungkin dimasukkan terbalik, sila masukkan dengan betul', + 'default' : sw12AndApiName, + }; + + let error_data = sw12AndApiName.split(" "); + + let error_code = error_data.filter(x => x.startsWith('0x')).splice(-1) + + let error_message = error_handler_dictionary['default']; + + let hasDefinedError = error_handler_dictionary.hasOwnProperty(error_code); + + if(hasDefinedError){ + error_message = error_handler_dictionary[error_code]; + } + + Swal.fire({ icon: 'error', title: error_message, }); + } + function callBackAfterReadMykad(data, respcode, sw12AndApiName) { if(respcode !== 0){ - hideLoader(); - Swal.fire({icon: 'error', title: sw12AndApiName,}); - return; + handleMyKadReaderError(sw12AndApiName); + return } checkIfMyKadExists(data.IDNum) - .then(response => response[0]) .then(response => { - if (response === 'no-data') { + let isResponseArray = Array.isArray(response); + resolved_response = isResponseArray ? response.pop() : response; + + if (resolved_response === 'no-data') { populateDaftarPelangganModal(data, handleReadPhoto); } else { let input_search_noic = document.getElementById("noic"); @@ -70,16 +106,28 @@ let original_photo_loader = document.querySelector("#photo-mykad").src; hideLoader(); } - function checkIfMyKadExists(myKadNumber){ + function checkIfMyKadExists(myKadNumber) { let myKadNumberWithoutHyphens = myKadNumber.replace(/-/g, ''); const url = wakil_caricustomer_endpoint + '/?icno=' + myKadNumberWithoutHyphens; - return fetch(url).then((response) => response.json()); + + const connectionConfig = { + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + "X-Requested-With": "XMLHttpRequest", + "X-CSRF-Token": document.querySelector('input[name="_token"]').value + }, + credentials: "same-origin", + }; + + return fetch(url, connectionConfig) + .then(response => response.json()) } let populateDaftarPelangganModal = (data, callbackAfterPopulateDaftarPelanggan) => { - $('#daftar_pelanggan').modal('show'); - let modal_form = document.querySelector(".modal-body .row.form-group"); + $('#daftar_pelanggan_mykad_reader').modal('show'); + let modal_form = document.querySelector("#daftar_pelanggan_mykad_reader .modal-body .row.form-group"); const religions = [ ['01', 'Islam'], @@ -146,7 +194,16 @@ let original_photo_loader = document.querySelector("#photo-mykad").src; return isBumiputera; }; - let photo_container = document.getElementById("photo-mykad-container"); + let disablePointerEventsOnClickableInputs = () => { + modal_form.querySelector("input[name='bumiputera']").style.pointerEvents = 'none'; + modal_form.querySelector("input[name='warganegara']").style.pointerEvents = 'none'; + + modal_form.querySelector("select[name='bangsa']").style.pointerEvents = 'none'; + modal_form.querySelector("select[name='agama']").style.pointerEvents = 'none'; + } + + let mykad_modal = document.querySelector("#daftar_pelanggan_mykad_reader"); + let photo_container = mykad_modal.querySelector("#photo-mykad-container"); modal_form.querySelector("input[name='name']").value = data.OrgName; modal_form.querySelector("input[name='noic']").value = getMyKadNumberWithoutHypens(data.IDNum); @@ -158,11 +215,11 @@ let original_photo_loader = document.querySelector("#photo-mykad").src; modal_form.querySelector("select[name='agama']").value = getCodeFromValue(data.Religion, religions); modal_form.querySelector("textarea[name='alamat']").value = [data.Address1, data.Address2, data.Address3].join(", "); - let getPostCode = (postCodeCity) => postCodeCity.replace(/\D/g, ''); + let getPostCode = (postCodeCity) => postCodeCity.replace(/\D/g, ''); modal_form.querySelector("input[name='poskod']").value = getPostCode(data.PostcodeCity); - let getCityName = (postCodeCity) => postCodeCity.replace(/\d/g, ''); - modal_form.querySelector("input[name='daerah']").value = getCityName(data.PostcodeCity); + let getCityName = (postCodeCity) => postCodeCity.replace(/\d/g, ''); + modal_form.querySelector("input[name='daerah']").value = getCityName(data.PostcodeCity).trim(); modal_form.querySelector("input[name='negeri']").value = data.State; modal_form.querySelector("input[name='age']").value = getAgeFromDateOfBirth(data.BirthDate); @@ -173,9 +230,10 @@ let original_photo_loader = document.querySelector("#photo-mykad").src; photo_container.classList.remove('d-none'); photo_container.classList.add('d-flex'); - $('#daftar_pelanggan').modal('show'); + $('#daftar_pelanggan_mykad_reader').modal('show'); + disablePointerEventsOnClickableInputs(); callbackAfterPopulateDaftarPelanggan(); } @@ -203,9 +261,10 @@ function doneOpenReaderConnection2() function callbackAfterReadPhoto2(data, RespCode, RespSW12AndApiName) { - let photo = document.getElementById("photo-mykad"); + let mykad_modal = document.querySelector("#daftar_pelanggan_mykad_reader"); + let photo = mykad_modal.querySelector("#photo-mykad"); - let isDataEmpty = data + let isDataEmpty = data && Object.keys(data).length === 0 && Object.getPrototypeOf(data) === Object.prototype; diff --git a/resources/views/customers/index.blade.php b/resources/views/customers/index.blade.php index ed6e8c6..1bd7bb7 100644 --- a/resources/views/customers/index.blade.php +++ b/resources/views/customers/index.blade.php @@ -37,7 +37,7 @@
- Baca MyKad + Baca MyKad
@@ -181,6 +181,140 @@ + + + + + + - Baca MyKad + @php + $user_cawangan = strtolower(auth()->user()->cawangan_kerja->details_caw); + $enabled_cawangan = array_map(fn($x) => strtolower($x), config('mykad-reader.enabled_cawangan')); + $is_enabled_to_use_mykad_reader = function () use($user_cawangan, $enabled_cawangan){ + + if(sizeof($enabled_cawangan) == 0){ + return true; + } + + if(sizeof($enabled_cawangan) == 1 && $enabled_cawangan[0] === ''){ + return true; + } + + return in_array($user_cawangan, $enabled_cawangan); + + }; + @endphp + + @if( $is_enabled_to_use_mykad_reader() ) + Baca MyKad + @endif