diff --git a/app/Http/Controllers/Api/GrowthReportAPIController.php b/app/Http/Controllers/Api/GrowthReportAPIController.php new file mode 100644 index 0000000..abf50df --- /dev/null +++ b/app/Http/Controllers/Api/GrowthReportAPIController.php @@ -0,0 +1,85 @@ +copy()->subMonth(); + $defaultEnd = $today; + + // Use request values if provided, else use defaults + $startDate = $request->input('start_date', $defaultStart->toDateString()); + $endDate = $request->input('end_date', $defaultEnd->toDateString()); + + // Optional year filter (used if specified) + $year = $request->input('year', now()->year); + + $query = BigdataResume::selectRaw(" + DATE(created_at) as date, + SUM(potention_sum) as potention_sum, + SUM(verified_sum) as verified_sum, + SUM(non_verified_sum) as non_verified_sum + ") + ->whereBetween('created_at', [$startDate, $endDate]); + + $query->whereNotNull('year') + ->where('year', '!=', 'all'); + + $data = $query->groupBy(DB::raw('DATE(created_at)')) + ->orderBy(DB::raw('DATE(created_at)')) + ->get() + ->map(function ($item) { + $item->date = Carbon::parse($item->date)->format('d M Y'); + return $item; + }); + + return response()->json($data); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, string $id) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $id) + { + // + } +} diff --git a/app/Http/Controllers/Report/GrowthReportsController.php b/app/Http/Controllers/Report/GrowthReportsController.php new file mode 100644 index 0000000..a8c6bb7 --- /dev/null +++ b/app/Http/Controllers/Report/GrowthReportsController.php @@ -0,0 +1,14 @@ + null, "sort_order" => 2, ], + [ + "name" => "Lap Pertumbuhan", + "url" => "growths", + "icon" => null, + "sort_order" => 3, + ], [ "name" => "Rekap Pembayaran", "url" => "payment-recaps", "icon" => null, - "sort_order" => 3, + "sort_order" => 4, ], [ "name" => "Lap Rekap Data Pembayaran", "url" => "report-payment-recaps", "icon" => null, - "sort_order" => 4, + "sort_order" => 5, ], [ "name" => "Lap PBG (PTSP)", "url" => "report-pbg-ptsp", "icon" => null, - "sort_order" => 5, + "sort_order" => 6, ], ] ], diff --git a/database/seeders/UsersRoleMenuSeeder.php b/database/seeders/UsersRoleMenuSeeder.php index fd823d1..5cb891d 100644 --- a/database/seeders/UsersRoleMenuSeeder.php +++ b/database/seeders/UsersRoleMenuSeeder.php @@ -25,7 +25,7 @@ class UsersRoleMenuSeeder extends Seeder 'Menu', 'Role', 'Setting Dashboard', 'PBG', 'Reklame', 'Usaha atau Industri', 'Pariwisata', 'Lap Pariwisata', 'UMKM', 'Dashboard Potensi', 'Tata Ruang', 'PDAM', 'PETA', 'Lap Pimpinan', 'Dalam Sistem', 'Luar Sistem', 'Google Sheets', 'TPA TPT', - 'Approval Pejabat', 'Undangan', 'Rekap Pembayaran', 'Lap Rekap Data Pembayaran', 'Lap PBG (PTSP)' + 'Approval Pejabat', 'Undangan', 'Rekap Pembayaran', 'Lap Rekap Data Pembayaran', 'Lap PBG (PTSP)', 'Lap Pertumbuhan' ])->get()->keyBy('name'); // Define access levels for each role @@ -36,7 +36,7 @@ class UsersRoleMenuSeeder extends Seeder 'Menu', 'Role', 'Setting Dashboard', 'PBG', 'Reklame', 'Usaha atau Industri', 'Pariwisata', 'Lap Pariwisata', 'UMKM', 'Dashboard Potensi', 'Tata Ruang', 'PDAM', 'Dalam Sistem', 'Luar Sistem', 'Lap Pimpinan', 'Google Sheets', 'TPA TPT', 'Approval Pejabat', - 'Undangan', 'Rekap Pembayaran', 'Lap Rekap Data Pembayaran', 'Lap PBG (PTSP)' + 'Undangan', 'Rekap Pembayaran', 'Lap Rekap Data Pembayaran', 'Lap PBG (PTSP)', 'Lap Pertumbuhan' ], 'user' => ['Dashboard', 'Data', 'Laporan', 'Neng Bedas', 'Approval', 'Tools', 'Dashboard Pimpinan', 'Dashboard PBG', 'Users', 'Syncronize', diff --git a/resources/js/report/growth-report/index.js b/resources/js/report/growth-report/index.js new file mode 100644 index 0000000..2fc1bc8 --- /dev/null +++ b/resources/js/report/growth-report/index.js @@ -0,0 +1,94 @@ +import ApexCharts from "apexcharts"; + +class GrowthReport { + init() { + this.loadChart(); + } + + async loadChart() { + try { + const chartElement = document.getElementById("chart-growth-report"); + const apiUrl = chartElement.dataset.url; + + const token = document + .querySelector('meta[name="api-token"]') + .getAttribute("content"); + + const response = await fetch(apiUrl, { + headers: { + Authorization: `Bearer ${token}`, + Accept: "application/json", + }, + }); + + const data = await response.json(); + + console.log("data", data); + + const categories = data.map((item) => item.date); + + const potentionSeries = { + name: "Potensi Berkas", + data: data.map((item) => item.potention_sum), + }; + + const verifiedSeries = { + name: "Terverifikasi", + data: data.map((item) => item.verified_sum), + }; + + const nonVerifiedSeries = { + name: "Belum Terverifikasi", + data: data.map((item) => item.non_verified_sum), + }; + + const options = { + chart: { + type: "bar", + height: 350, + }, + title: { + text: "Grafik Pertumbuhan", + }, + dataLabels: { + enabled: false, + }, + legend: { + show: true, + }, + xaxis: { + categories: categories, + }, + yaxis: { + title: { + text: "Total SUM Per Date", + }, + labels: { + formatter: function (value) { + return "Rp. " + value.toLocaleString("id-ID"); + }, + }, + }, + noData: { + text: "Data tidak tersedia", + align: "center", + verticalAlign: "middle", + style: { + color: "#999", + fontSize: "16px", + }, + }, + series: [potentionSeries, verifiedSeries, nonVerifiedSeries], + }; + + const chart = new ApexCharts(chartElement, options); + chart.render(); + } catch (error) { + console.error("Failed to load growth report data:", error); + } + } +} + +document.addEventListener("DOMContentLoaded", function () { + new GrowthReport().init(); +}); diff --git a/resources/views/report/growth-report/index.blade.php b/resources/views/report/growth-report/index.blade.php new file mode 100644 index 0000000..c6358ef --- /dev/null +++ b/resources/views/report/growth-report/index.blade.php @@ -0,0 +1,21 @@ +@extends('layouts.vertical', ['subtitle' => 'Laporan Pertumbuhan']) + +@section('css') +@endsection + +@section('content') +@include('layouts.partials/page-title', ['title' => 'Laporan', 'subtitle' => 'Laporan Pertumbuhan']) + +