add filter date for dashboard

This commit is contained in:
arifal
2025-02-24 19:00:09 +07:00
parent e743b82087
commit bb4ab5c769
8 changed files with 272 additions and 159 deletions

View File

@@ -13,12 +13,23 @@ class BigDataResumeController extends Controller
/** /**
* Display a listing of the resource. * Display a listing of the resource.
*/ */
public function index() public function index(Request $request)
{ {
try{ try{
$filterDate = $request->get("filterByDate");
// If filterByDate is "latest" or empty, get the most recent record
if (!$filterDate || $filterDate === "latest") {
$big_data_resume = BigdataResume::latest()->first(); $big_data_resume = BigdataResume::latest()->first();
} else {
// Filter by specific date
$big_data_resume = BigdataResume::whereDate('created_at', $filterDate)
->orderBy('id', 'desc')
->first();
if (!$big_data_resume) { if (!$big_data_resume) {
return response()->json(['message' => 'No Big Data resume found']); return $this->response_empty_resume();
}
} }
$data_settings = DataSetting::all(); $data_settings = DataSetting::all();
@@ -168,4 +179,63 @@ class BigDataResumeController extends Controller
{ {
// //
} }
private function response_empty_resume(){
$result = [
'target_pad' => [
'sum' => 0,
'percentage' => 100,
],
'tata_ruang' => [
'sum' => 0,
'percentage' => 0,
],
'kekurangan_potensi' => [
'sum' => 0,
'percentage' => 0
],
'total_potensi' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'verified_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'non_verified_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'business_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'non_business_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'realisasi_terbit' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'menunggu_klik_dpmptsp' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'proses_dinas_teknis' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
]
];
return response()->json($result);
}
} }

View File

@@ -230,16 +230,15 @@ class ServiceSIMBG
} }
} }
$uuids = array_column($tasksCollective, 'uuid');
$this->syncIndexIntegration($uuids, $token);
PbgTask::upsert($tasksCollective, ['uuid'], [ PbgTask::upsert($tasksCollective, ['uuid'], [
'name', 'owner_name', 'application_type', 'application_type_name', 'condition', 'name', 'owner_name', 'application_type', 'application_type_name', 'condition',
'registration_number', 'document_number', 'address', 'status', 'status_name', 'registration_number', 'document_number', 'address', 'status', 'status_name',
'slf_status', 'slf_status_name', 'function_type', 'consultation_type', 'due_date', 'slf_status', 'slf_status_name', 'function_type', 'consultation_type', 'due_date',
'land_certificate_phase', 'task_created_at', 'updated_at' 'land_certificate_phase', 'task_created_at', 'updated_at'
]); ]);
$uuids = array_column($tasksCollective, 'uuid');
$this->syncIndexIntegration($uuids, $token);
} }
$importDatasource->update([ $importDatasource->update([
@@ -337,4 +336,3 @@ class ServiceSIMBG
} }
} }

View File

@@ -2,6 +2,30 @@ import bootstrap from "bootstrap/dist/js/bootstrap";
window.bootstrap = bootstrap; window.bootstrap = bootstrap;
import "iconify-icon"; import "iconify-icon";
import "simplebar/dist/simplebar"; import "simplebar/dist/simplebar";
// import flatpickr from "flatpickr";
// import "flatpickr/dist/flatpickr.min.css";
// class InitDatePicker {
// constructor(selector = ".datepicker") {
// this.selector = selector;
// }
// init() {
// const elements = document.querySelectorAll(this.selector);
// if (elements.length === 0) return; // Skip if no elements found
// const today = new Date();
// const minYear = today.getFullYear() - 5;
// elements.forEach((element) => {
// flatpickr(element, {
// enableTime: false,
// dateFormat: "Y-m-d",
// minDate: `${minYear}-01-01`,
// maxDate: today,
// });
// });
// }
// }
class Components { class Components {
initBootstrapComponents() { initBootstrapComponents() {
@@ -107,6 +131,7 @@ class FormValidation {
} }
document.addEventListener("DOMContentLoaded", function (e) { document.addEventListener("DOMContentLoaded", function (e) {
new Components().init(), new FormValidation().init(); new Components().init(), new FormValidation().init();
// new InitDatePicker().init();
}); });
class ThemeLayout { class ThemeLayout {
constructor() { constructor() {

View File

@@ -1,55 +1,30 @@
import Big from "big.js"; import Big from "big.js";
import GlobalConfig, { addThousandSeparators } from "../global-config.js"; import GlobalConfig, { addThousandSeparators } from "../global-config.js";
import flatpickr from "flatpickr"; import InitDatePicker from "../utils/InitDatePicker.js";
import "flatpickr/dist/flatpickr.min.css";
class BigData { class BigData {
async init() { async init() {
try { try {
this.filterYear = new Date().getFullYear(); // Set initial year new InitDatePicker(
"#datepicker-dashboard-bigdata",
let yearSelect = document.querySelector("#yearPicker"); this.handleChangeDate.bind(this)
let filterButton = document.querySelector("#btnFilterYear"); ).init();
if (!yearSelect || !filterButton) {
console.error(
"Element #yearPicker or #btnFilterYear not found."
);
return;
}
// Set default value for input
yearSelect.value = this.filterYear;
yearSelect.addEventListener("change", () => {
this.updateYear(yearSelect.value);
});
// Handle button click
filterButton.addEventListener("click", () => {
this.updateYear(yearSelect.value);
});
console.log("init filter this year", this.filterYear);
// Load initial data // Load initial data
await this.updateData(this.filterYear); this.updateData("latest");
} catch (error) { } catch (error) {
console.error("Error initializing data:", error); console.error("Error initializing data:", error);
} }
} }
updateYear(value) {
let inputYear = parseInt(value, 10); handleChangeDate(filterDate) {
if (!isNaN(inputYear)) { if (!filterDate) return;
this.filterYear = inputYear; this.updateData(filterDate);
this.updateData(this.filterYear);
} else {
console.error("Invalid year input");
} }
} async updateData(filterDate) {
async updateData(year) {
try { try {
this.resumeBigData = await this.getBigDataResume(); console.log("Filtering data for date:", filterDate);
this.resumeBigData = await this.getBigDataResume(filterDate);
// this.totalTargetPAD = await this.getDataSettings("TARGET_PAD"); // this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
// this.resultDataTotal = await this.getDataTotalPotensi(year); // this.resultDataTotal = await this.getDataTotalPotensi(year);
// this.dataVerification = await this.getDataVerfication(year); // this.dataVerification = await this.getDataVerfication(year);
@@ -178,10 +153,10 @@ class BigData {
} }
} }
async getBigDataResume() { async getBigDataResume(filterByDate) {
try { try {
const response = await fetch( const response = await fetch(
`${GlobalConfig.apiHost}/api/bigdata-resume`, `${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterByDate}`,
{ {
credentials: "include", credentials: "include",
headers: { headers: {
@@ -199,8 +174,6 @@ class BigData {
} }
const data = await response.json(); const data = await response.json();
console.log("big data resume", JSON.stringify(data));
console.log("big data resume", data);
return data; return data;
} catch (error) { } catch (error) {
console.error("Error fetching chart data:", error); console.error("Error fetching chart data:", error);

View File

@@ -1,10 +1,15 @@
import Big from "big.js"; import Big from "big.js";
import GlobalConfig, { addThousandSeparators } from "../global-config.js"; import GlobalConfig, { addThousandSeparators } from "../global-config.js";
import InitDatePicker from "../utils/InitDatePicker.js";
class LackOfPotential { class LackOfPotential {
async init() { async init() {
new InitDatePicker(
"#datepicker-lack-of-potential",
this.handleChangedDate.bind(this)
).init();
this.bigTotalLackPotential = 0; this.bigTotalLackPotential = 0;
this.totalPotensi = await this.getDataTotalPotensi(2025); this.totalPotensi = await this.getDataTotalPotensi("latest");
this.totalTargetPAD = await this.getDataSettings("TARGET_PAD"); this.totalTargetPAD = await this.getDataSettings("TARGET_PAD");
this.allCountData = await this.getValueDashboard(); this.allCountData = await this.getValueDashboard();
this.reklameCount = this.allCountData.total_reklame ?? 0; this.reklameCount = this.allCountData.total_reklame ?? 0;
@@ -12,15 +17,26 @@ class LackOfPotential {
this.tataRuangCount = this.allCountData.total_tata_ruang ?? 0; this.tataRuangCount = this.allCountData.total_tata_ruang ?? 0;
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0); this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
this.bigTotalPotensi = new Big(this.totalPotensi.totalData ?? 0); this.bigTotalPotensi = new Big(this.totalPotensi.total ?? 0);
this.bigTotalLackPotential = this.bigTargetPAD - this.bigTotalPotensi; this.bigTotalLackPotential = this.bigTargetPAD.minus(
this.bigTotalPotensi
);
this.initChartKekuranganPotensi(); this.initChartKekuranganPotensi();
this.initDataValueDashboard(); this.initDataValueDashboard();
} }
async getDataTotalPotensi(year) { async handleChangedDate(filterDate) {
const totalPotensi = await this.getDataTotalPotensi(filterDate);
this.bigTotalPotensi = new Big(totalPotensi.total ?? 0);
this.bigTotalLackPotential = this.bigTargetPAD.minus(
this.bigTotalPotensi
);
this.initChartKekuranganPotensi();
}
async getDataTotalPotensi(filterDate) {
try { try {
const response = await fetch( const response = await fetch(
`${GlobalConfig.apiHost}/api/all-task-documents?year=${year}`, `${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterDate}`,
{ {
credentials: "include", credentials: "include",
headers: { headers: {
@@ -39,8 +55,7 @@ class LackOfPotential {
const data = await response.json(); const data = await response.json();
return { return {
countData: data.data.count, total: data.total_potensi.sum,
totalData: data.data.total,
}; };
} catch (error) { } catch (error) {
console.error("Error fetching chart data:", error); console.error("Error fetching chart data:", error);
@@ -50,7 +65,7 @@ class LackOfPotential {
async getDataSettings(string_key) { async getDataSettings(string_key) {
try { try {
const response = await fetch( const response = await fetch(
`${GlobalConfig.apiHost}/api/api-data-settings?search=${string_key}`, `${GlobalConfig.apiHost}/api/data-settings?search=${string_key}`,
{ {
credentials: "include", credentials: "include",
headers: { headers: {

View File

@@ -0,0 +1,34 @@
import flatpickr from "flatpickr";
import "flatpickr/dist/flatpickr.min.css";
class InitDatePicker {
constructor(selector = ".datepicker", onChangeCallback = null) {
this.selector = selector;
this.onChangeCallback = onChangeCallback;
}
init() {
const today = new Date();
document.querySelectorAll(this.selector).forEach((element) => {
flatpickr(element, {
enableTime: false,
dateFormat: "Y-m-d",
maxDate: today,
onChange: (selectedDates, dateStr) => {
if (this.onChangeCallback) {
this.onChangeCallback(dateStr); // Call callback with selected date
}
},
onReady: (selectedDates, dateStr, instance) => {
// Call the callback with the default date when initialized
if (this.onChangeCallback && dateStr) {
this.onChangeCallback(dateStr);
}
},
});
});
}
}
export default InitDatePicker;

View File

@@ -20,13 +20,8 @@
<div class="row d-flex justify-content-end"> <div class="row d-flex justify-content-end">
<div class="col-12 col-sm-6 col-md-3"> <div class="col-12 col-sm-6 col-md-3">
<div class="d-flex flex-sm-nowrap flex-wrap justify-content-end gap-2"> <div class="d-flex flex-sm-nowrap flex-wrap justify-content-end">
<select class="form-select w-auto" id="yearPicker" name="year" style="min-width: 100px;"> <input type="text" class="form-control" style="max-width: 125px;" id="datepicker-dashboard-bigdata" placeholder="Filter Date" />
@for ($i = date('Y'); $i > date('Y') - 5; $i--)
<option value="{{ $i }}" {{ $i == date('Y') ? 'selected' : '' }}>{{ $i }}</option>
@endfor
</select>
<button class="btn btn-sm btn-primary" id="btnFilterYear">Filter</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -15,8 +15,14 @@
</h3> </h3>
</div> </div>
</div> </div>
<div class=""> <div class="wrapper">
<div class=""> <div class="row d-flex justify-content-end">
<div class="col-12 col-sm-6 col-md-3">
<div class="d-flex flex-sm-nowrap flex-wrap justify-content-end">
<input type="text" class="form-control me-3" style="max-width: 125px;" id="datepicker-lack-of-potential" placeholder="Filter Date" />
</div>
</div>
</div>
<div id="lack-of-potential-fixed-container" class="" style="width:1400px;height:770px;position:relative;margin:auto;z-index:1;"> <div id="lack-of-potential-fixed-container" class="" style="width:1400px;height:770px;position:relative;margin:auto;z-index:1;">
<div style="position: absolute; top: 200px; left: 50px;"> <div style="position: absolute; top: 200px; left: 50px;">
<x-custom-circle title="Restoran" size="small" style="background-color: #0e4753;" /> <x-custom-circle title="Restoran" size="small" style="background-color: #0e4753;" />
@@ -107,9 +113,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
@endsection @endsection