add filter date for dashboard
This commit is contained in:
@@ -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();
|
||||||
if(!$big_data_resume){
|
} else {
|
||||||
return response()->json(['message' => 'No Big Data resume found']);
|
// Filter by specific date
|
||||||
|
$big_data_resume = BigdataResume::whereDate('created_at', $filterDate)
|
||||||
|
->orderBy('id', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$big_data_resume) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
34
resources/js/utils/InitDatePicker.js
Normal file
34
resources/js/utils/InitDatePicker.js
Normal 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;
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user