diff --git a/app/Services/ServiceClient.php b/app/Services/ServiceClient.php index 3f82ac4..f209569 100644 --- a/app/Services/ServiceClient.php +++ b/app/Services/ServiceClient.php @@ -42,8 +42,14 @@ class ServiceClient } $response = $this->client->request($method, $this->baseUrl . $url, $options); + $responseBody = (string) $response->getBody(); - $resultResponse = json_decode($response->getBody(), true); + if (!str_contains($response->getHeaderLine('Content-Type'), 'application/json')) { + \Log::error('Unexpected response format: ' . $responseBody); + return $this->resError('API response is not JSON'); + } + + $resultResponse = json_decode($responseBody, true, 512, JSON_THROW_ON_ERROR); return $this->resSuccess($resultResponse); } catch (Exception $e) { \Log::error('error from client service'. $e->getMessage()); diff --git a/app/Services/ServiceSIMBG.php b/app/Services/ServiceSIMBG.php index 136adc5..11176e0 100644 --- a/app/Services/ServiceSIMBG.php +++ b/app/Services/ServiceSIMBG.php @@ -37,63 +37,66 @@ class ServiceSIMBG } public function getToken(){ - $url = "/api/user/v1/auth/login/"; - $body = [ - 'email' => $this->email, - 'password' => $this->password, - ]; - - $res = $this->service_client->post($url, $body); - if(!$res->original['success']){ - Log::error("Token not retrieved ", ['response' => $res]); - return null; + try{ + $url = "/api/user/v1/auth/login/"; + $body = [ + 'email' => $this->email, + 'password' => $this->password, + ]; + + $res = $this->service_client->post($url, $body); + if(!$res->original['success']){ + Log::error("Token not retrieved ", ['response' => $res]); + throw new Exception("Token not retrieved."); + } + return $res; + }catch(Exception $e){ + Log::error("Error on method get token ", ['response' => $e->getMessage()]); + throw $e; } - return $res; } public function syncIndexIntegration($uuid, $token) { - $url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/"; - - $headers = [ - 'Authorization' => "Bearer " . $token, - ]; + try{ + $url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/"; - $res = $this->service_client->get($url, $headers); - - if (empty($res->original['success']) || !$res->original['success']) { - // Log error - Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]); - return false; - } - - $data = $res->original['data']['data'] ?? null; - if (!$data) { - Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]); - return false; - } - - $resultData = PbgTaskIndexIntegrations::updateOrCreate( - ['pbg_task_uid' => $uuid], - [ - 'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null, - 'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null, - 'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null, - 'indeks_parameter_ketinggian' => $data['indeks_parameter_ketinggian'] ?? null, - 'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null, - 'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null, - 'total' => $data['total'] ?? null, - ] - ); - - // Log success - if ($resultData->wasRecentlyCreated) { - Log::info("integration created successfully", ['uuid' => $uuid]); - } else { - Log::info("integration updated successfully", ['uuid' => $uuid]); - } + $headers = [ + 'Authorization' => "Bearer " . $token, + ]; - return true; + $res = $this->service_client->get($url, $headers); + + if (empty($res->original['success']) || !$res->original['success']) { + // Log error + Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]); + return false; + } + + $data = $res->original['data']['data'] ?? null; + if (!$data) { + Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]); + return false; + } + + $resultData = PbgTaskIndexIntegrations::updateOrCreate( + ['pbg_task_uid' => $uuid], + [ + 'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null, + 'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null, + 'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null, + 'indeks_parameter_ketinggian' => $data['indeks_parameter_ketinggian'] ?? null, + 'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null, + 'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null, + 'total' => $data['total'] ?? null, + ] + ); + + return true; + }catch (Exception $e){ + Log::error('error when sync index integration ', ['index integration'=> $e->getMessage()]); + throw $e; + } } public function syncTaskList() @@ -182,22 +185,10 @@ class ServiceSIMBG 'created_at' => now(), ]; - $save_integration = $this->syncIndexIntegration($item['uid'], $token); - if (!$save_integration) { - $importDatasource->update([ - 'status' => ImportDatasourceStatus::Failed->value, - 'message' => "Successfully processed: $savedCount, Failed: $failedCount" - ]); - } - - $save_detail = $this->syncTaskDetailSubmit($item['uid'], $token); - if( !$save_detail ) { - $importDatasource->update([ - 'status' => ImportDatasourceStatus::Failed->value, - 'message' => "Successfully processed: $savedCount, Failed: $failedCount" - ]); - } + $this->syncIndexIntegration($item['uid'], $token); + $this->syncTaskDetailSubmit($item['uid'], $token); + $savedCount++; } catch (Exception $e) { $failedCount++; @@ -236,79 +227,83 @@ class ServiceSIMBG public function syncTaskDetailSubmit($uuid, $token) { - $url = "/api/pbg/v1/detail/" . $uuid . "/retribution/submit/"; - $headers = [ - 'Authorization' => "Bearer " . $token, - ]; - - $res = $this->service_client->get($url, $headers); - - if (empty($res->original['success']) || !$res->original['success']) { - // Log error - Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]); - return false; - } - - $data = $res->original['data']['data'] ?? []; - if (empty($data)) { - Log::error("No data returned from API", ['url' => $url, 'uuid' => $uuid]); - return false; - } - - $detailCreatedAt = isset($data['created_at']) - ? Carbon::parse($data['created_at'])->format('Y-m-d H:i:s') - : null; - - $detailUpdatedAt = isset($data['updated_at']) - ? Carbon::parse($data['updated_at'])->format('Y-m-d H:i:s') - : null; - - $pbg_task_retributions = PbgTaskRetributions::updateOrCreate( - ['detail_id' => $data['id']], - [ - 'detail_uid' => $data['uid'] ?? null, - 'detail_created_at' => $detailCreatedAt ?? null, - 'detail_updated_at' => $detailUpdatedAt ?? null, - 'luas_bangunan' => $data['luas_bangunan'] ?? null, - 'indeks_lokalitas' => $data['indeks_lokalitas'] ?? null, - 'wilayah_shst' => $data['wilayah_shst'] ?? null, - 'kegiatan_id' => $data['kegiatan']['id'] ?? null, - 'kegiatan_name' => $data['kegiatan']['name'] ?? null, - 'nilai_shst' => $data['nilai_shst'] ?? null, - 'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null, - 'indeks_bg_terbangun' => $data['indeks_bg_terbangun'] ?? null, - 'nilai_retribusi_bangunan' => $data['nilai_retribusi_bangunan'] ?? null, - 'nilai_prasarana' => $data['nilai_prasarana'] ?? null, - 'created_by' => $data['created_by'] ?? null, - 'pbg_document' => $data['pbg_document'] ?? null, - 'underpayment' => $data['underpayment'] ?? null, - 'skrd_amount' => $data['skrd_amount'] ?? null, - 'pbg_task_uid' => $uuid, - ] - ); - - $pbg_task_retribution_id = $pbg_task_retributions->id; - - $prasaranaData = $data['prasarana'] ?? []; - if (!empty($prasaranaData)) { - $insertData = array_map(fn($item) => [ - 'pbg_task_uid' => $uuid, - 'pbg_task_retribution_id' => $pbg_task_retribution_id, - 'prasarana_id' => $item['id'] ?? null, - 'prasarana_type' => $item['prasarana_type'] ?? null, - 'building_type' => $item['building_type'] ?? null, - 'total' => $item['total'] ?? null, - 'quantity' => $item['quantity'] ?? null, - 'unit' => $item['unit'] ?? null, - 'index_prasarana' => $item['index_prasarana'] ?? null, - ], $prasaranaData); + try{ + $url = "/api/pbg/v1/detail/" . $uuid . "/retribution/submit/"; + $headers = [ + 'Authorization' => "Bearer " . $token, + ]; - // Use bulk insert or upsert for faster database operation - PbgTaskPrasarana::upsert($insertData, ['prasarana_id']); - } + $res = $this->service_client->get($url, $headers); + + if (empty($res->original['success']) || !$res->original['success']) { + // Log error + Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]); + return false; + } + + $data = $res->original['data']['data'] ?? []; + if (empty($data)) { + Log::error("No data returned from API", ['url' => $url, 'uuid' => $uuid]); + return false; + } + + $detailCreatedAt = isset($data['created_at']) + ? Carbon::parse($data['created_at'])->format('Y-m-d H:i:s') + : null; + + $detailUpdatedAt = isset($data['updated_at']) + ? Carbon::parse($data['updated_at'])->format('Y-m-d H:i:s') + : null; + + $pbg_task_retributions = PbgTaskRetributions::updateOrCreate( + ['detail_id' => $data['id']], + [ + 'detail_uid' => $data['uid'] ?? null, + 'detail_created_at' => $detailCreatedAt ?? null, + 'detail_updated_at' => $detailUpdatedAt ?? null, + 'luas_bangunan' => $data['luas_bangunan'] ?? null, + 'indeks_lokalitas' => $data['indeks_lokalitas'] ?? null, + 'wilayah_shst' => $data['wilayah_shst'] ?? null, + 'kegiatan_id' => $data['kegiatan']['id'] ?? null, + 'kegiatan_name' => $data['kegiatan']['name'] ?? null, + 'nilai_shst' => $data['nilai_shst'] ?? null, + 'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null, + 'indeks_bg_terbangun' => $data['indeks_bg_terbangun'] ?? null, + 'nilai_retribusi_bangunan' => $data['nilai_retribusi_bangunan'] ?? null, + 'nilai_prasarana' => $data['nilai_prasarana'] ?? null, + 'created_by' => $data['created_by'] ?? null, + 'pbg_document' => $data['pbg_document'] ?? null, + 'underpayment' => $data['underpayment'] ?? null, + 'skrd_amount' => $data['skrd_amount'] ?? null, + 'pbg_task_uid' => $uuid, + ] + ); + + $pbg_task_retribution_id = $pbg_task_retributions->id; + + $prasaranaData = $data['prasarana'] ?? []; + if (!empty($prasaranaData)) { + $insertData = array_map(fn($item) => [ + 'pbg_task_uid' => $uuid, + 'pbg_task_retribution_id' => $pbg_task_retribution_id, + 'prasarana_id' => $item['id'] ?? null, + 'prasarana_type' => $item['prasarana_type'] ?? null, + 'building_type' => $item['building_type'] ?? null, + 'total' => $item['total'] ?? null, + 'quantity' => $item['quantity'] ?? null, + 'unit' => $item['unit'] ?? null, + 'index_prasarana' => $item['index_prasarana'] ?? null, + ], $prasaranaData); + + // Use bulk insert or upsert for faster database operation + PbgTaskPrasarana::upsert($insertData, ['prasarana_id']); + } + return true; - Log::info("retribution and prasarana successfully", ['uuid' => $uuid]); - return true; + }catch(Exception $e){ + Log::error("Failed to sync task detail submit", ['error' => $e->getMessage(), 'uuid' => $uuid]); + throw $e; + } } } diff --git a/resources/js/dashboards/bigdata.js b/resources/js/dashboards/bigdata.js index 1022297..e83c299 100644 --- a/resources/js/dashboards/bigdata.js +++ b/resources/js/dashboards/bigdata.js @@ -591,32 +591,55 @@ document.addEventListener("DOMContentLoaded", async function (e) { await new BigData().init(); }); +// function resizeDashboard() { +// //Target Width +// let targetElement = document.getElementById("dashboard-fixed-wrapper"); +// let targetWidth = targetElement.offsetWidth; +// //console.log("TARGET ",targetWidth); + +// //Real Object Width +// let dashboardElement = document.getElementById("dashboard-fixed-container"); +// let dashboardWidth = 1110; //dashboardElement.offsetWidth; +// //console.log("CURRENT ",dashboardWidth); + +// if (targetWidth > dashboardWidth) { +// targetWidth = dashboardWidth; +// } + +// dashboardElement.style.transformOrigin = "left top"; +// dashboardElement.style.transition = "transform 0.2s ease-in-out"; +// dashboardElement.style.transform = +// "scale(" + (targetWidth / dashboardWidth).toFixed(2) + ")"; +// //console.log("SCALE ", (targetWidth/dashboardWidth).toFixed(2)); +// } + +// window.addEventListener("load", function () { +// resizeDashboard(); +// }); + +// window.addEventListener("resize", function () { +// resizeDashboard(); +// }); + function resizeDashboard() { - //Target Width let targetElement = document.getElementById("dashboard-fixed-wrapper"); - let targetWidth = targetElement.offsetWidth; - //console.log("TARGET ",targetWidth); - - //Real Object Width let dashboardElement = document.getElementById("dashboard-fixed-container"); - let dashboardWidth = 1110; //dashboardElement.offsetWidth; - //console.log("CURRENT ",dashboardWidth); - if (targetWidth > dashboardWidth) { - targetWidth = dashboardWidth; - } + let targetWidth = targetElement.offsetWidth; + let dashboardWidth = 1110; + + let scaleFactor = (targetWidth / dashboardWidth).toFixed(2); + + // Prevent scaling beyond 1 (100%) to avoid overflow + scaleFactor = Math.min(scaleFactor, 1); dashboardElement.style.transformOrigin = "left top"; dashboardElement.style.transition = "transform 0.2s ease-in-out"; - dashboardElement.style.transform = - "scale(" + (targetWidth / dashboardWidth).toFixed(2) + ")"; - //console.log("SCALE ", (targetWidth/dashboardWidth).toFixed(2)); + dashboardElement.style.transform = `scale(${scaleFactor})`; + + // Ensure horizontal scrolling is allowed if necessary + document.body.style.overflowX = "auto"; } -window.addEventListener("load", function () { - resizeDashboard(); -}); - -window.addEventListener("resize", function () { - resizeDashboard(); -}); +window.addEventListener("load", resizeDashboard); +window.addEventListener("resize", resizeDashboard); diff --git a/resources/js/data-settings/index.js b/resources/js/data-settings/index.js index 0f3944e..39599eb 100644 --- a/resources/js/data-settings/index.js +++ b/resources/js/data-settings/index.js @@ -52,13 +52,16 @@ class DataSettings { name: "Actions", width: "120px", formatter: function (cell) { - console.log("cell data", cell); return gridjs.html(` -
- Update - -
- `); +
+ + + + +
+ `); }, }, ], diff --git a/resources/js/master/users/users.js b/resources/js/master/users/users.js index ade7008..15dab30 100644 --- a/resources/js/master/users/users.js +++ b/resources/js/master/users/users.js @@ -22,9 +22,12 @@ class UsersTable { name: "Action", formatter: (cell) => gridjs.html(` -
- Update - `), +
+ + + +
+ `), }, ], pagination: { diff --git a/resources/js/menus/index.js b/resources/js/menus/index.js index 67cb0a2..9a12b31 100644 --- a/resources/js/menus/index.js +++ b/resources/js/menus/index.js @@ -56,9 +56,14 @@ class Menus { name: "Action", formatter: (cell) => gridjs.html(` -
- Update - +
+ + + + +
`), }, ], diff --git a/resources/js/pbg-task/index.js b/resources/js/pbg-task/index.js index ad340a3..9b1d228 100644 --- a/resources/js/pbg-task/index.js +++ b/resources/js/pbg-task/index.js @@ -25,8 +25,8 @@ class PbgTasks { name: "Action", formatter: function (cell) { return gridjs.html(` -
- Detail + Detail `); }, diff --git a/resources/js/roles/index.js b/resources/js/roles/index.js index 63c28f6..d05e808 100644 --- a/resources/js/roles/index.js +++ b/resources/js/roles/index.js @@ -52,10 +52,16 @@ class Roles { name: "Action", formatter: (cell) => gridjs.html(` -
- Update - Role Menu - + `), }, diff --git a/resources/scss/components/_circle.scss b/resources/scss/components/_circle.scss index 44d5d63..246d598 100644 --- a/resources/scss/components/_circle.scss +++ b/resources/scss/components/_circle.scss @@ -10,6 +10,7 @@ width: 200px; /* Ukuran lingkaran */ height: 200px; display: flex; + text-align: center; align-items: center; justify-content: center; background-color: var(--circle-color); /* Warna lingkaran utama */ @@ -17,6 +18,7 @@ border: 6px solid white; /* Border putih */ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */ position: absolute; + // overflow: hidden; .circle-content { width: 180px; /* Ukuran lingkaran dalam */ @@ -39,6 +41,12 @@ font-weight: bold; margin: 0 5px; line-height: 1.5; + word-wrap: break-word; /* Break words if too long */ + white-space: normal; /* Allow multi-line text */ + text-align: center; /* Center text inside the circle */ + overflow-wrap: break-word; /* Ensures breaking in modern browsers */ + display: block; /* Ensures it respects container size */ + max-width: 100%; /* Prevents exceeding the circle size */ } .circle-content .document-total { @@ -64,8 +72,8 @@ .small-circle-container { position: absolute; - bottom: 0; - right: 0; + bottom: -10px; + right: -10px; width: 50px; /* Ukuran lingkaran kecil */ height: 50px; background-color: #2d4f90; /* Warna lingkaran kecil */ @@ -75,6 +83,7 @@ align-items: center; justify-content: center; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */ + z-index: 10; .small-circle-content { width: 45px; diff --git a/resources/scss/dashboards/_bigdata.scss b/resources/scss/dashboards/_bigdata.scss new file mode 100644 index 0000000..9d61d77 --- /dev/null +++ b/resources/scss/dashboards/_bigdata.scss @@ -0,0 +1,78 @@ +// +// bigdata.scss +// + +.square { + height: 100px; + width: 100px; + position: absolute; + z-index: -1; +} + +.dia-top-left-bottom-right:after { + content: ""; + width: 100%; + height: 100%; + position: absolute; + + top: 0; + left: 0; + background: linear-gradient( + to top right, + transparent calc(50% - 2px), + black, + transparent calc(50% + 2px) + ); +} + +.dia-top-right-bottom-left:after { + content: ""; + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + background: linear-gradient( + to top left, + transparent calc(50% - 2px), + black, + transparent calc(50% + 2px) + ); +} + +#dashboard-fixed-wrapper { + background-image: url("../../../public/images/bg-dashboard.jpg"); + background-size: cover; + background-position: center; +} + +#dashboard-fixed-wrapper::before { + content: ""; + position: absolute; + pointer-events: none; /* Prevents the overlay from blocking interaction */ + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba( + 255, + 255, + 255, + 0.7 + ); /* Black overlay with 50% opacity */ +} + +#dashboard-fixed-wrapper { + max-width: 100vw; /* Ensures it doesn't exceed viewport */ +} + +#dashboard-fixed-container { + min-width: 1110px; + max-width: unset; /* Allow it to grow if needed */ +} + +@media (max-width: 768px) { + #dashboard-fixed-container { + transform: scale(0.8); /* Adjust the scale as needed */ + } +} diff --git a/resources/scss/style.scss b/resources/scss/style.scss index cbd83c1..a0887fe 100755 --- a/resources/scss/style.scss +++ b/resources/scss/style.scss @@ -59,3 +59,5 @@ // Pages @import "pages/icon-demo"; @import "pages/authentication"; + +@import "dashboards/bigdata"; diff --git a/resources/views/dashboards/bigdata.blade.php b/resources/views/dashboards/bigdata.blade.php index 11507a5..9950aaf 100644 --- a/resources/views/dashboards/bigdata.blade.php +++ b/resources/views/dashboards/bigdata.blade.php @@ -1,72 +1,36 @@ @extends('layouts.vertical', ['subtitle' => 'Dashboards']) +@section('css') +@vite(['resources/scss/dashboards/_bigdata.scss']) +@endsection + @section('content') @include('layouts.partials/page-title', ['title' => 'Dashboards', 'subtitle' => 'Dashboard Pimpinan']) - -
-

- Terakhir di update - {{$latest_created}} - ANALISA BIG DATA PROSES PBG
- MELALUI APLIKASI SIBEDAS PBG +
+

+ Terakhir di update - {{$latest_created}} + ANALISA BIG DATA PROSES PBG
+ MELALUI APLIKASI SIBEDAS PBG + +

+
-

- -
-
- - +
+
+
+ + +
-
+
@component('components.circle', [ 'document_title' => 'Kekurangan Potensi', 'document_color' => '#911701', diff --git a/resources/views/data-settings/index.blade.php b/resources/views/data-settings/index.blade.php index d99b2b8..c584619 100644 --- a/resources/views/data-settings/index.blade.php +++ b/resources/views/data-settings/index.blade.php @@ -10,13 +10,16 @@ +
-
-
-
- Create +
+
+
+
+ Create +
+
-
diff --git a/resources/views/master/users/index.blade.php b/resources/views/master/users/index.blade.php index ea0c486..193f81f 100644 --- a/resources/views/master/users/index.blade.php +++ b/resources/views/master/users/index.blade.php @@ -9,12 +9,16 @@ @include('layouts.partials/page-title', ['title' => 'Master', 'subtitle' => 'Users'])
-
-
-
- Create +
+
+
+ +
-
diff --git a/resources/views/menus/index.blade.php b/resources/views/menus/index.blade.php index ce9eca0..5884013 100644 --- a/resources/views/menus/index.blade.php +++ b/resources/views/menus/index.blade.php @@ -10,14 +10,17 @@ +
-
-
-
- Create -
-
-
+
+
+
+
+ Create +
+
+
+
diff --git a/resources/views/pbg_task/index.blade.php b/resources/views/pbg_task/index.blade.php index 414632f..c650ea0 100644 --- a/resources/views/pbg_task/index.blade.php +++ b/resources/views/pbg_task/index.blade.php @@ -9,12 +9,14 @@ @include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'PBG'])
-
-
-
- Create +
+
+
+
+ Create +
+
-
diff --git a/resources/views/roles/index.blade.php b/resources/views/roles/index.blade.php index a8c0d4d..42d4684 100644 --- a/resources/views/roles/index.blade.php +++ b/resources/views/roles/index.blade.php @@ -12,12 +12,14 @@
-
-
-
- Create +
+
+
+
+ Create +
+
-
diff --git a/resources/views/settings/syncronize/index.blade.php b/resources/views/settings/syncronize/index.blade.php index ab83860..82e4b80 100644 --- a/resources/views/settings/syncronize/index.blade.php +++ b/resources/views/settings/syncronize/index.blade.php @@ -9,14 +9,16 @@ @include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Syncronize'])
-
-
-
- - -
-
-
+
+
+
+
+ + +
+
+
+
diff --git a/vite.config.js b/vite.config.js index 422fe6b..ccb7157 100755 --- a/vite.config.js +++ b/vite.config.js @@ -19,6 +19,7 @@ export default defineConfig({ "resources/scss/icons.scss", "resources/scss/style.scss", "resources/scss/components/_circle.scss", + "resources/scss/dashboards/_bigdata.scss", "node_modules/quill/dist/quill.snow.css", "node_modules/quill/dist/quill.bubble.css",