diff --git a/app/Http/Controllers/Api/BigDataResumeController.php b/app/Http/Controllers/Api/BigDataResumeController.php
index 89b4d7f..72446df 100644
--- a/app/Http/Controllers/Api/BigDataResumeController.php
+++ b/app/Http/Controllers/Api/BigDataResumeController.php
@@ -173,6 +173,53 @@ class BigDataResumeController extends Controller
}
}
+ public function payment_recaps(Request $request)
+ {
+ try {
+ $query = BigdataResume::query()->orderBy('id', 'desc');
+
+ if ($request->filled('date')) {
+ $query->where('year', 'LIKE', '%' . $request->input('search') . '%');
+ }
+
+ $data = $query->paginate(10);
+
+ // Restructure response
+ $transformedData = [];
+
+ foreach ($data as $item) {
+ $createdAt = $item->created_at;
+ $id = $item->id;
+
+ foreach ($item->toArray() as $key => $value) {
+ // Only include columns with "sum" in their names
+ if (strpos($key, 'sum') !== false) {
+ $transformedData[] = [
+ 'id' => $id,
+ 'category' => $key,
+ 'nominal' => $value,
+ 'created_at' => $createdAt,
+ ];
+ }
+ }
+ }
+
+ return response()->json([
+ 'data' => $transformedData, // Flat array
+ 'pagination' => [
+ 'total' => $data->total(),
+ 'per_page' => $data->perPage(),
+ 'current_page' => $data->currentPage(),
+ 'last_page' => $data->lastPage(),
+ ]
+ ]);
+ } catch (\Exception $e) {
+ Log::error($e->getMessage());
+ return response()->json(['message' => 'Error when fetching data'], 500);
+ }
+ }
+
+
private function response_empty_resume(){
$result = [
'target_pad' => [
diff --git a/app/Http/Controllers/Api/RequestAssignmentController.php b/app/Http/Controllers/Api/RequestAssignmentController.php
index 3474fe5..d7962a6 100644
--- a/app/Http/Controllers/Api/RequestAssignmentController.php
+++ b/app/Http/Controllers/Api/RequestAssignmentController.php
@@ -5,7 +5,11 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\RequestAssignmentResouce;
use App\Models\PbgTask;
+use App\Models\PbgTaskGoogleSheet;
+use DB;
+use Exception;
use Illuminate\Http\Request;
+use Log;
class RequestAssignmentController extends Controller
{
@@ -23,6 +27,51 @@ class RequestAssignmentController extends Controller
return RequestAssignmentResouce::collection($query->paginate());
}
+ public function report_payment_recaps(Request $request)
+ {
+ try {
+ // Query dengan group by kecamatan dan sum nilai_retribusi_keseluruhan_simbg
+ $query = PbgTaskGoogleSheet::select(
+ 'kecamatan',
+ DB::raw('SUM(nilai_retribusi_keseluruhan_simbg) as total')
+ )
+ ->groupBy('kecamatan')
+ ->paginate(10);
+
+ // Return hasil dalam JSON format
+ return response()->json([
+ 'success' => true,
+ 'data' => $query
+ ]);
+
+ } catch (Exception $e) {
+ Log::error($e->getMessage());
+ return response()->json(['message' => 'Terjadi kesalahan: ' . $e->getMessage()], 500);
+ }
+ }
+ public function report_pbg_ptsp()
+ {
+ try {
+ // Query dengan group by status dan count total per status
+ $query = PbgTask::select(
+ 'status',
+ 'status_name',
+ DB::raw('COUNT(*) as total')
+ )
+ ->groupBy('status', 'status_name')
+ ->paginate(10);
+
+ // Return hasil dalam JSON format
+ return response()->json([
+ 'success' => true,
+ 'data' => $query
+ ]);
+
+ } catch (Exception $e) {
+ Log::error($e->getMessage());
+ return response()->json(['message' => 'Terjadi kesalahan: ' . $e->getMessage()], 500);
+ }
+ }
/**
* Store a newly created resource in storage.
*/
diff --git a/app/Http/Controllers/Approval/ApprovalController.php b/app/Http/Controllers/Approval/ApprovalController.php
new file mode 100644
index 0000000..2addfab
--- /dev/null
+++ b/app/Http/Controllers/Approval/ApprovalController.php
@@ -0,0 +1,65 @@
+ "mingcute:wechat-line",
"parent_id" => null,
"sort_order" => 7,
- ]
+ ],
+ [
+ "name" => "Approval",
+ "url" => "/approval",
+ "icon" => "mingcute:user-follow-2-line",
+ "parent_id" => null,
+ "sort_order" => 8,
+ ],
+ [
+ "name" => "Tools",
+ "url" => "/tools",
+ "icon" => "mingcute:tool-line",
+ "parent_id" => null,
+ "sort_order" => 9,
+ ],
];
foreach ($parent_menus as $parent_menu) {
@@ -100,6 +114,8 @@ class UsersRoleMenuSeeder extends Seeder
$data = Menu::where('name', 'Data')->first();
$laporan = Menu::where('name', 'Laporan')->first();
$chat_bedas = Menu::where('name', 'Neng Bedas')->first();
+ $approval = Menu::where('name', 'Approval')->first();
+ $tools = Menu::where('name', 'Tools')->first();
// create children menu
$children_menus = [
@@ -138,6 +154,13 @@ class UsersRoleMenuSeeder extends Seeder
"parent_id" => $master->id,
"sort_order" => 1,
],
+ [
+ "name" => "Approval Pejabat",
+ "url" => "approval-list",
+ "icon" => null,
+ "parent_id" => $approval->id,
+ "sort_order" => 1,
+ ],
[
"name" => "Syncronize",
"url" => "settings.syncronize",
@@ -222,6 +245,13 @@ class UsersRoleMenuSeeder extends Seeder
"parent_id" => $data->id,
"sort_order" => 8,
],
+ [
+ "name" => "TPA TPT",
+ "url" => "tpa-tpt",
+ "icon" => null,
+ "parent_id" => $data->id,
+ "sort_order" => 9,
+ ],
[
"name" => "Lap Pariwisata",
"url" => "tourisms-report.index",
@@ -236,6 +266,27 @@ class UsersRoleMenuSeeder extends Seeder
"parent_id" => $laporan->id,
"sort_order" => 2,
],
+ [
+ "name" => "Rekap Pembayaran",
+ "url" => "payment-recaps",
+ "icon" => null,
+ "parent_id" => $laporan->id,
+ "sort_order" => 3,
+ ],
+ [
+ "name" => "Lap Rekap Data Pembayaran",
+ "url" => "report-payment-recap",
+ "icon" => null,
+ "parent_id" => $laporan->id,
+ "sort_order" => 4,
+ ],
+ [
+ "name" => "Lap PBG (PTSP)",
+ "url" => "report-pbg-ptsp",
+ "icon" => null,
+ "parent_id" => $laporan->id,
+ "sort_order" => 5,
+ ],
[
"name" => "Chat",
"url" => "main-chatbot.index",
@@ -257,6 +308,13 @@ class UsersRoleMenuSeeder extends Seeder
"parent_id" => Menu::where('name', 'Dashboard Potensi')->first()->id,
"sort_order" => 2,
],
+ [
+ "name" => "Undangan",
+ "url" => "invitations",
+ "icon" => null,
+ "parent_id" => $tools->id,
+ "sort_order" => 1,
+ ],
];
foreach ($children_menus as $child_menu) {
@@ -285,6 +343,12 @@ class UsersRoleMenuSeeder extends Seeder
$dalam_sistem = Menu::where('name', 'Dalam Sistem')->first();
$luar_sistem = Menu::where('name', 'Luar Sistem')->first();
$google_sheets = Menu::where('name', 'Google Sheets')->first();
+ $tpa_tpt = Menu::where('name', 'TPA TPT')->first();
+ $approval_pejabat = Menu::where('name', 'Approval Pejabat')->first();
+ $intivations = Menu::where('name', 'Undangan')->first();
+ $payment_recap = Menu::where('name', 'Rekap Pembayaran')->first();
+ $report_payment_recap = Menu::where('name', 'Lap Rekap Data Pembayaran')->first();
+ $report_pbg_ptsp = Menu::where('name', 'Lap PBG (PTSP)')->first();
// Superadmin gets all menus
$superadmin->menus()->sync([
@@ -296,6 +360,8 @@ class UsersRoleMenuSeeder extends Seeder
$data->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$laporan->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
$chat_bedas->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
+ $approval->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
+ $tools->id => ["allow_show" => true, "allow_create" => false, "allow_update" => false, "allow_destroy" => false],
// children
$dashboard_pimpinan->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$dashboard_pbg->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
@@ -319,6 +385,12 @@ class UsersRoleMenuSeeder extends Seeder
$bigdata_resume->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$chatbot->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
$google_sheets->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
+ $tpa_tpt->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
+ $approval_pejabat->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
+ $intivations->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
+ $payment_recap->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
+ $report_payment_recap->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
+ $report_pbg_ptsp->id => ["allow_show" => true, "allow_create" => true, "allow_update" => true, "allow_destroy" => true],
]);
// Admin gets limited menus
diff --git a/resources/js/approval/index.js b/resources/js/approval/index.js
new file mode 100644
index 0000000..bd94558
--- /dev/null
+++ b/resources/js/approval/index.js
@@ -0,0 +1,90 @@
+import { Grid } from "gridjs/dist/gridjs.umd.js";
+import "gridjs/dist/gridjs.umd.js";
+import gridjs from "gridjs/dist/gridjs.umd.js";
+import GlobalConfig from "../global-config";
+
+class Approval {
+ constructor() {
+ this.toastMessage = document.getElementById("toast-message");
+ this.toastElement = document.getElementById("toastNotification");
+ this.toast = new bootstrap.Toast(this.toastElement);
+ this.table = null;
+ this.initTableApproval();
+ }
+ initTableApproval() {
+ let tableContainer = document.getElementById("table-approvals");
+ this.table = new Grid({
+ columns: [
+ "ID",
+ { name: "Name", width: "15%" },
+ { name: "Condition", width: "7%" },
+ "Registration Number",
+ "Document Number",
+ { name: "Address", width: "30%" },
+ "Status",
+ "Function Type",
+ "Consultation Type",
+ { name: "Due Date", width: "10%" },
+ {
+ name: "Action",
+ formatter: (cell) => {
+ return gridjs.html(`
+
+
+
+
+ `);
+ },
+ },
+ ],
+ search: {
+ server: {
+ url: (prev, keyword) => `${prev}?search=${keyword}`,
+ },
+ debounceTimeout: 1000,
+ },
+ pagination: {
+ limit: 15,
+ server: {
+ url: (prev, page) =>
+ `${prev}${prev.includes("?") ? "&" : "?"}page=${
+ page + 1
+ }`,
+ },
+ },
+ sort: true,
+ server: {
+ url: `${GlobalConfig.apiHost}/api/request-assignments`,
+ credentials: "include",
+ headers: {
+ Authorization: `Bearer ${document
+ .querySelector('meta[name="api-token"]')
+ .getAttribute("content")}`,
+ "Content-Type": "application/json",
+ },
+ then: (data) =>
+ data.data.map((item) => [
+ item.id,
+ item.name,
+ item.condition,
+ item.registration_number,
+ item.document_number,
+ item.address,
+ item.status_name,
+ item.function_type,
+ item.consultation_type,
+ item.due_date,
+ item.id,
+ ]),
+ total: (data) => data.meta.total,
+ },
+ }).render(tableContainer);
+ }
+}
+document.addEventListener("DOMContentLoaded", function (e) {
+ new Approval();
+});
diff --git a/resources/js/invitations/index.js b/resources/js/invitations/index.js
new file mode 100644
index 0000000..a08bc7b
--- /dev/null
+++ b/resources/js/invitations/index.js
@@ -0,0 +1,56 @@
+import { Grid } from "gridjs/dist/gridjs.umd.js";
+import "gridjs/dist/gridjs.umd.js";
+
+// Fungsi untuk menghasilkan data dummy
+function generateDummyInvitations(count = 10) {
+ const statuses = ["Terkirim", "Gagal", "Menunggu"];
+ const dummyData = [];
+
+ for (let i = 1; i <= count; i++) {
+ const email = `user${i}@example.com`;
+ const status = statuses[Math.floor(Math.random() * statuses.length)];
+ const createdAt = new Date(
+ Date.now() - Math.floor(Math.random() * 100000000)
+ )
+ .toISOString()
+ .replace("T", " ")
+ .substring(0, 19);
+
+ dummyData.push([i, email, status, createdAt]);
+ }
+
+ return dummyData;
+}
+
+class Invitations {
+ constructor() {
+ this.table = null;
+ this.initEvents();
+ }
+
+ initEvents() {
+ this.initTableInvitations();
+ }
+
+ initTableInvitations() {
+ let tableContainer = document.getElementById("table-invitations");
+ this.table = new Grid({
+ columns: [
+ { name: "ID" },
+ { name: "Email" },
+ { name: "Status" },
+ { name: "Created" },
+ ],
+ data: generateDummyInvitations(50), // Bisa ganti jumlah data dummy
+ pagination: {
+ limit: 10,
+ },
+ sort: true,
+ search: true,
+ }).render(tableContainer);
+ }
+}
+
+document.addEventListener("DOMContentLoaded", function () {
+ new Invitations();
+});
diff --git a/resources/js/payment-recaps/index.js b/resources/js/payment-recaps/index.js
new file mode 100644
index 0000000..0062233
--- /dev/null
+++ b/resources/js/payment-recaps/index.js
@@ -0,0 +1,104 @@
+import { Grid } from "gridjs/dist/gridjs.umd.js";
+import "gridjs/dist/gridjs.umd.js";
+import gridjs from "gridjs/dist/gridjs.umd.js";
+import GlobalConfig, { addThousandSeparators } from "../global-config.js";
+import moment from "moment";
+import InitDatePicker from "../utils/InitDatePicker.js";
+
+class PaymentRecaps {
+ constructor() {
+ this.toastMessage = document.getElementById("toast-message");
+ this.toastElement = document.getElementById("toastNotification");
+ this.toast = new bootstrap.Toast(this.toastElement);
+ this.table = null;
+ this.initTablePaymentRecaps();
+ this.initFilterDatepicker();
+ }
+ initFilterDatepicker() {
+ new InitDatePicker(
+ "#datepicker-payment-recap",
+ this.handleChangeFilterDate.bind(this)
+ ).init();
+ }
+ handleChangeFilterDate(strDate) {
+ console.log("filter date : ", strDate);
+ }
+ formatCategory(category) {
+ const categoryMap = {
+ potention_sum: "Potensi",
+ non_verified_sum: "Belum Terverifikasi",
+ verified_sum: "Terverifikasi",
+ business_sum: "Usaha",
+ non_business_sum: "Non Usaha",
+ spatial_sum: "Tata Ruang",
+ waiting_click_dpmptsp_sum: "Menunggu Klik DPMPTSP",
+ issuance_realization_pbg_sum: "Realisasi Terbit PBG",
+ process_in_technical_office_sum: "Proses Di Dinas Teknis",
+ };
+
+ return categoryMap[category] || category; // Return mapped value or original category
+ }
+ initTablePaymentRecaps() {
+ let tableContainer = document.getElementById("table-payment-recaps");
+
+ this.table = new Grid({
+ columns: [
+ { name: "Kategori", data: (row) => row[0] },
+ { name: "Nominal", data: (row) => row[1] },
+ {
+ name: "Created",
+ data: (row) => row[2],
+ attributes: { style: "width: 200px; white-space: nowrap;" },
+ },
+ ],
+ pagination: {
+ limit: 10,
+ server: {
+ url: (prev, page) =>
+ `${prev}${prev.includes("?") ? "&" : "?"}page=${
+ page + 1
+ }`,
+ },
+ },
+ sort: true,
+ server: {
+ url: `${GlobalConfig.apiHost}/api/payment-recaps`,
+ headers: {
+ Authorization: `Bearer ${document
+ .querySelector('meta[name="api-token"]')
+ .getAttribute("content")}`,
+ "Content-Type": "application/json",
+ },
+ then: (response) => {
+ console.log("API Response:", response); // Debugging
+
+ if (!response.data || !Array.isArray(response.data)) {
+ console.error(
+ "Error: Data is not an array",
+ response.data
+ );
+ return [];
+ }
+
+ return response.data.map((item) => [
+ this.formatCategory(item.category ?? "Unknown"), // Ensure category is not null
+ addThousandSeparators(
+ Number(item.nominal).toString() || 0
+ ), // Ensure nominal is a valid number
+ moment(item.created_at).isValid()
+ ? moment(item.created_at).format(
+ "YYYY-MM-DD H:mm:ss"
+ )
+ : "-", // Handle invalid dates
+ ]);
+ },
+ total: (response) => response.pagination?.total || 0,
+ },
+ width: "auto",
+ fixedHeader: true,
+ }).render(tableContainer);
+ }
+}
+document.addEventListener("DOMContentLoaded", function (e) {
+ new PaymentRecaps();
+});
diff --git a/resources/js/pbg-task/index.js b/resources/js/pbg-task/index.js
index 3b91531..51c0b96 100644
--- a/resources/js/pbg-task/index.js
+++ b/resources/js/pbg-task/index.js
@@ -2,10 +2,15 @@ import { Grid } from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../global-config";
+import { Dropzone } from "dropzone";
+Dropzone.autoDiscover = false;
class PbgTasks {
init() {
this.initTableRequestAssignment();
+ this.handleSendNotification();
+ this.handleUpload();
+ this.handleUploadBeritaAcara();
}
initTableRequestAssignment() {
@@ -28,25 +33,33 @@ class PbgTasks {
{ name: "Due Date", width: "10%" },
{
name: "Action",
- formatter: function (cell) {
- let tableContainer = document.getElementById("table-pbg-tasks");
- let canUpdate = tableContainer.getAttribute("data-updater") === "1";
-
+ formatter: (cell) => {
+ let tableContainer =
+ document.getElementById("table-pbg-tasks");
+ let canUpdate =
+ tableContainer.getAttribute("data-updater") === "1";
+
if (!canUpdate) {
- return gridjs.html(`
- No Privilege
- `);
+ return gridjs.html(
+ `No Privilege`
+ );
}
-
+
return gridjs.html(`
Detail
+
+
`);
},
- }
+ },
],
search: {
server: {
@@ -91,6 +104,96 @@ class PbgTasks {
},
}).render(document.getElementById("table-pbg-tasks"));
}
+
+ handleSendNotification() {
+ this.toastMessage = document.getElementById("toast-message");
+ this.toastElement = document.getElementById("toastNotification");
+ this.toast = new bootstrap.Toast(this.toastElement);
+
+ document
+ .getElementById("sendNotificationBtn")
+ .addEventListener("click", () => {
+ let notificationStatus =
+ document.getElementById("notificationStatus").value;
+
+ // Show success toast
+ this.toastMessage.innerText = "Notifikasi berhasil dikirim!";
+ this.toast.show();
+
+ // Close modal after sending
+ let modal = bootstrap.Modal.getInstance(
+ document.getElementById("sendNotificationModal")
+ );
+ modal.hide();
+ });
+ }
+
+ handleUpload() {
+ // Handle button click to show modal
+ document.addEventListener("click", function (event) {
+ if (event.target.classList.contains("upload-btn")) {
+ // Show modal
+ let uploadModal = new bootstrap.Modal(
+ document.getElementById("uploadModal")
+ );
+ uploadModal.show();
+ }
+ });
+ let dropzone = new Dropzone("#singleFileDropzone", {
+ url: "/upload-bukti-bayar", // Adjust to your backend endpoint
+ maxFiles: 1, // Allow only 1 file
+ maxFilesize: 5, // Limit size to 5MB
+ acceptedFiles: ".jpg,.png,.pdf", // Allowed file types
+ autoProcessQueue: false, // Prevent automatic upload
+ addRemoveLinks: true, // Show remove button
+ dictDefaultMessage: "Drop your file here or click to upload.",
+ init: function () {
+ let dz = this;
+
+ // Remove previous file when a new file is added
+ dz.on("addedfile", function () {
+ if (dz.files.length > 1) {
+ dz.removeFile(dz.files[0]);
+ }
+ });
+
+ // Handle upload button click
+ document
+ .getElementById("uploadBtn")
+ .addEventListener("click", function () {
+ if (dz.getQueuedFiles().length > 0) {
+ dz.processQueue(); // Manually process upload
+ } else {
+ alert("Please select a file to upload.");
+ }
+ });
+
+ // Success callback
+ dz.on("success", function (file, response) {
+ alert("File uploaded successfully!");
+ dz.removeAllFiles(); // Clear after upload
+ });
+
+ // Error callback
+ dz.on("error", function (file, errorMessage) {
+ alert("Upload failed: " + errorMessage);
+ });
+ },
+ });
+ }
+
+ handleUploadBeritaAcara() {
+ // Handle button click to show modal
+ document.addEventListener("click", function (event) {
+ if (event.target.classList.contains("upload-btn-berita-acara")) {
+ // Show modal
+ let uploadModal = new bootstrap.Modal(
+ document.getElementById("uploadBeritaAcara")
+ );
+ uploadModal.show();
+ }
+ });
+ }
}
document.addEventListener("DOMContentLoaded", function (e) {
diff --git a/resources/js/report-payment-recaps/index.js b/resources/js/report-payment-recaps/index.js
new file mode 100644
index 0000000..be8100e
--- /dev/null
+++ b/resources/js/report-payment-recaps/index.js
@@ -0,0 +1,69 @@
+import { Grid } from "gridjs/dist/gridjs.umd.js";
+import "gridjs/dist/gridjs.umd.js";
+import gridjs from "gridjs/dist/gridjs.umd.js";
+import GlobalConfig, { addThousandSeparators } from "../global-config.js";
+
+class ReportPaymentRecaps {
+ constructor() {
+ this.table = null;
+ this.initTableReportPaymentRecaps();
+ }
+ initTableReportPaymentRecaps() {
+ let tableContainer = document.getElementById(
+ "table-report-payment-recaps"
+ );
+
+ this.table = new Grid({
+ columns: [
+ { name: "Kecamatan" },
+ {
+ name: "Total",
+ formatter: (cell) => addThousandSeparators(cell),
+ },
+ ],
+ pagination: {
+ limit: 10,
+ server: {
+ url: (prev, page) =>
+ `${prev}${prev.includes("?") ? "&" : "?"}page=${
+ page + 1
+ }`,
+ },
+ },
+ sort: true,
+ server: {
+ url: `${GlobalConfig.apiHost}/api/report-payment-recaps`,
+ headers: {
+ Authorization: `Bearer ${document
+ .querySelector('meta[name="api-token"]')
+ .getAttribute("content")}`,
+ "Content-Type": "application/json",
+ },
+ then: (response) => {
+ console.log("API Response:", response); // Debugging
+
+ // Pastikan response memiliki data
+ if (
+ !response ||
+ !response.data ||
+ !Array.isArray(response.data.data)
+ ) {
+ console.error("Error: Data is not an array", response);
+ return [];
+ }
+
+ return response.data.data.map((item) => [
+ item.kecamatan || "Unknown",
+ item.total,
+ ]);
+ },
+ total: (response) => response.data.total || 0, // Ambil total dari API pagination
+ },
+ width: "auto",
+ fixedHeader: true,
+ }).render(tableContainer);
+ }
+}
+document.addEventListener("DOMContentLoaded", function (e) {
+ new ReportPaymentRecaps();
+});
diff --git a/resources/js/report-pbg-ptsp/index.js b/resources/js/report-pbg-ptsp/index.js
new file mode 100644
index 0000000..26376b1
--- /dev/null
+++ b/resources/js/report-pbg-ptsp/index.js
@@ -0,0 +1,67 @@
+import { Grid } from "gridjs/dist/gridjs.umd.js";
+import "gridjs/dist/gridjs.umd.js";
+import gridjs from "gridjs/dist/gridjs.umd.js";
+import GlobalConfig, { addThousandSeparators } from "../global-config.js";
+
+class ReportPbgPTSP {
+ constructor() {
+ this.table = null;
+ this.initTableReportPbgPTSP();
+ }
+ initTableReportPbgPTSP() {
+ let tableContainer = document.getElementById("table-report-pbg-ptsp");
+
+ this.table = new Grid({
+ columns: [
+ { name: "Status" },
+ {
+ name: "Total",
+ formatter: (cell) => cell,
+ },
+ ],
+ pagination: {
+ limit: 10,
+ server: {
+ url: (prev, page) =>
+ `${prev}${prev.includes("?") ? "&" : "?"}page=${
+ page + 1
+ }`,
+ },
+ },
+ sort: true,
+ server: {
+ url: `${GlobalConfig.apiHost}/api/report-pbg-ptsp`,
+ headers: {
+ Authorization: `Bearer ${document
+ .querySelector('meta[name="api-token"]')
+ .getAttribute("content")}`,
+ "Content-Type": "application/json",
+ },
+ then: (response) => {
+ console.log("API Response:", response); // Debugging
+
+ // Pastikan response memiliki data
+ if (
+ !response ||
+ !response.data ||
+ !Array.isArray(response.data.data)
+ ) {
+ console.error("Error: Data is not an array", response);
+ return [];
+ }
+
+ return response.data.data.map((item) => [
+ item.status_name || "Unknown",
+ item.total,
+ ]);
+ },
+ total: (response) => response.data.total || 0, // Ambil total dari API pagination
+ },
+ width: "auto",
+ fixedHeader: true,
+ }).render(tableContainer);
+ }
+}
+document.addEventListener("DOMContentLoaded", function (e) {
+ new ReportPbgPTSP();
+});
diff --git a/resources/js/tpa-tpt/index.js b/resources/js/tpa-tpt/index.js
new file mode 100644
index 0000000..12ed634
--- /dev/null
+++ b/resources/js/tpa-tpt/index.js
@@ -0,0 +1,112 @@
+import { Grid } from "gridjs/dist/gridjs.umd.js";
+import "gridjs/dist/gridjs.umd.js";
+
+class TpaTpt {
+ constructor() {
+ this.toastMessage = document.getElementById("toast-message");
+ this.toastElement = document.getElementById("toastNotification");
+ this.toast = new bootstrap.Toast(this.toastElement);
+ this.table = null;
+
+ // Initialize functions
+ this.initTableTpaTpt();
+ this.initEvents();
+ }
+ initEvents() {}
+ initTableTpaTpt() {
+ let tableContainer = document.getElementById("table-tpa-tpt");
+
+ tableContainer.innerHTML = "";
+ let canUpdate = tableContainer.getAttribute("data-updater") === "1";
+ let canDelete = tableContainer.getAttribute("data-destroyer") === "1";
+
+ // Kecamatan (districts) in Kabupaten Bandung
+ const kecamatanList = [
+ "Bojongsoang",
+ "Cangkuang",
+ "Cicalengka",
+ "Cikancung",
+ "Cilengkrang",
+ "Cileunyi",
+ "Cimaung",
+ "Cimenyan",
+ "Ciparay",
+ "Cisaat",
+ "Dayeuhkolot",
+ "Ibun",
+ "Katapang",
+ "Kertasari",
+ "Kutawaringin",
+ "Majalaya",
+ "Margaasih",
+ "Margahayu",
+ "Nagreg",
+ "Pacet",
+ "Pameungpeuk",
+ "Pangalengan",
+ "Paseh",
+ "Rancaekek",
+ "Solokanjeruk",
+ "Soreang",
+ "Banjaran",
+ "Baleendah",
+ ];
+
+ // Generate random PT (companies)
+ function generateCompanyName() {
+ const prefixes = ["PT", "CV", "UD"];
+ const names = [
+ "Mitra Sejahtera",
+ "Berkah Jaya",
+ "Makmur Abadi",
+ "Sukses Mandiri",
+ "Indah Lestari",
+ "Tirta Alam",
+ ];
+ const suffixes = [
+ "Indonesia",
+ "Sentosa",
+ "Persada",
+ "Global",
+ "Tbk",
+ "Jaya",
+ ];
+
+ return `${prefixes[Math.floor(Math.random() * prefixes.length)]} ${
+ names[Math.floor(Math.random() * names.length)]
+ } ${suffixes[Math.floor(Math.random() * suffixes.length)]}`;
+ }
+
+ // Function to generate random dummy data
+ function generateDummyData(count) {
+ let data = [];
+
+ for (let i = 1; i <= count; i++) {
+ let name = `TPA ${String.fromCharCode(64 + (i % 26))}${i}`; // Example: TPA A1, TPA B2, etc.
+ let location =
+ kecamatanList[
+ Math.floor(Math.random() * kecamatanList.length)
+ ];
+ let lat = (-6.9 + Math.random() * 0.3).toFixed(6); // Approximate latitude for Bandung area
+ let lng = (107.5 + Math.random() * 0.5).toFixed(6); // Approximate longitude for Bandung area
+ let owner = generateCompanyName();
+
+ data.push([name, location, lat, lng, owner]);
+ }
+ return data;
+ }
+
+ this.table = new Grid({
+ columns: ["Nama", "Kecamatan", "Lat", "Lng", "Pemilik (PT)"],
+ data: generateDummyData(100), // Generate 100 rows of dummy data
+ pagination: {
+ limit: 10,
+ },
+ search: true,
+ sort: true,
+ }).render(tableContainer);
+ }
+}
+document.addEventListener("DOMContentLoaded", function (e) {
+ new TpaTpt();
+});
diff --git a/resources/views/approval/index.blade.php b/resources/views/approval/index.blade.php
new file mode 100644
index 0000000..361b16d
--- /dev/null
+++ b/resources/views/approval/index.blade.php
@@ -0,0 +1,27 @@
+@extends('layouts.vertical', ['subtitle' => 'Approval'])
+
+@section('css')
+@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
+@endsection
+
+@section('content')
+
+@include('layouts.partials/page-title', ['title' => 'Approval', 'subtitle' => 'Approval Pejabat'])
+
+
+
+
+
+@endsection
+
+@section('scripts')
+@vite(['resources/js/approval/index.js'])
+@endsection
\ No newline at end of file
diff --git a/resources/views/invitations/index.blade.php b/resources/views/invitations/index.blade.php
new file mode 100644
index 0000000..3eccee7
--- /dev/null
+++ b/resources/views/invitations/index.blade.php
@@ -0,0 +1,45 @@
+@extends('layouts.vertical', ['subtitle' => 'Undangan'])
+
+@section('css')
+@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
+@endsection
+
+@section('content')
+
+@include('layouts.partials/page-title', ['title' => 'Tools', 'subtitle' => 'Undangan'])
+
+
+
+
+
+
+
+
+
+
Kirim Undangan
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@endsection
+
+@section('scripts')
+@vite(['resources/js/invitations/index.js'])
+@endsection
\ No newline at end of file
diff --git a/resources/views/payment-recaps/index.blade.php b/resources/views/payment-recaps/index.blade.php
new file mode 100644
index 0000000..60372e7
--- /dev/null
+++ b/resources/views/payment-recaps/index.blade.php
@@ -0,0 +1,34 @@
+@extends('layouts.vertical', ['subtitle' => 'Rekap Pembayaran'])
+
+@section('css')
+@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
+@endsection
+
+@section('content')
+
+@include('layouts.partials/page-title', ['title' => 'Laporan', 'subtitle' => 'Rekap Pembayaran'])
+
+
+
+
+
+
+@endsection
+
+@section('scripts')
+@vite(['resources/js/payment-recaps/index.js'])
+@endsection
\ No newline at end of file
diff --git a/resources/views/pbg_task/index.blade.php b/resources/views/pbg_task/index.blade.php
index db1cdcd..770dec9 100644
--- a/resources/views/pbg_task/index.blade.php
+++ b/resources/views/pbg_task/index.blade.php
@@ -8,11 +8,16 @@
@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'PBG'])
+
+
+
@if ($creator)
Create
@endif
@@ -26,6 +31,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@endsection
@section('scripts')
diff --git a/resources/views/report-payment-recaps/index.blade.php b/resources/views/report-payment-recaps/index.blade.php
new file mode 100644
index 0000000..ffe848b
--- /dev/null
+++ b/resources/views/report-payment-recaps/index.blade.php
@@ -0,0 +1,28 @@
+@extends('layouts.vertical', ['subtitle' => 'Laporan Rekap Data Pembayaran'])
+
+@section('css')
+@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
+@endsection
+
+@section('content')
+
+@include('layouts.partials/page-title', ['title' => 'Laporan', 'subtitle' => 'Lap Rekap Data Pembayaran'])
+
+
+
+
+
+
+@endsection
+
+@section('scripts')
+@vite(['resources/js/report-payment-recaps/index.js'])
+@endsection
\ No newline at end of file
diff --git a/resources/views/report-pbg-ptsp/index.blade.php b/resources/views/report-pbg-ptsp/index.blade.php
new file mode 100644
index 0000000..e562aff
--- /dev/null
+++ b/resources/views/report-pbg-ptsp/index.blade.php
@@ -0,0 +1,27 @@
+@extends('layouts.vertical', ['subtitle' => 'Lap PBG (PTSP)'])
+
+@section('css')
+@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
+@endsection
+
+@section('content')
+
+@include('layouts.partials/page-title', ['title' => 'Laporan', 'subtitle' => 'Lap PBG (PTSP)'])
+
+
+
+
+
+@endsection
+
+@section('scripts')
+@vite(['resources/js/report-pbg-ptsp/index.js'])
+@endsection
\ No newline at end of file
diff --git a/resources/views/tpa-tpt/index.blade.php b/resources/views/tpa-tpt/index.blade.php
new file mode 100644
index 0000000..f6fd7ee
--- /dev/null
+++ b/resources/views/tpa-tpt/index.blade.php
@@ -0,0 +1,27 @@
+@extends('layouts.vertical', ['subtitle' => 'TPA TPT'])
+
+@section('css')
+@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
+@endsection
+
+@section('content')
+
+@include('layouts.partials/page-title', ['title' => 'Data', 'subtitle' => 'TPA TPT'])
+
+
+
+
+
+@endsection
+
+@section('scripts')
+@vite(['resources/js/tpa-tpt/index.js'])
+@endsection
\ No newline at end of file
diff --git a/routes/api.php b/routes/api.php
index 2c9d2b2..060d93c 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -51,6 +51,8 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
// request assignments
Route::apiResource('request-assignments',RequestAssignmentController::class);
+ Route::get('/report-payment-recaps',[RequestAssignmentController::class, 'report_payment_recaps'])->name('report-payment-recaps');
+ Route::get('/report-pbg-ptsp',[RequestAssignmentController::class, 'report_pbg_ptsp'])->name('report-pbg-ptsp');
// all dashboards
Route::controller(DashboardController::class)->group(function(){
@@ -141,6 +143,7 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
Route::controller(BigDataResumeController::class)->group(function (){
Route::get('/bigdata-resume', 'index')->name('api.bigdata-resume');
Route::get('/bigdata-report', 'bigdata_report')->name('api.bigdata-report');
+ Route::get('/payment-recaps', 'payment_recaps')->name('api.payment-recaps');
});
// task-assignments
diff --git a/routes/web.php b/routes/web.php
index 35dd1e3..baaa390 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,5 +1,6 @@
'auth'], function(){
Route::get('/google-sheets/{google_sheet_id}', 'show')->name('google-sheets.show');
Route::get('/google-sheets/{google_sheet_id}/edit', 'edit')->name('google-sheets.edit');
});
+
+ // tpa-tpt
+ Route::resource('/tpa-tpt', TpatptsController::class);
});
// Report
@@ -132,5 +141,26 @@ Route::group(['middleware' => 'auth'], function(){
Route::controller(BigdataResumesController::class)->group(function (){
Route::get('/bigdata-resumes', 'index')->name('bigdata-resumes');
});
+ Route::controller(PaymentRecapsController::class)->group(function (){
+ Route::get('/payment-recaps', 'index')->name('payment-recaps');
+ });
+
+ Route::controller(ReportPaymentRecapsController::class)->group(function (){
+ Route::get('/report-payment-recaps', 'index')->name('report-payment-recaps');
+ });
+
+ Route::controller(ReportPbgPTSPController::class)->group(function (){
+ Route::get('/report-pbg-ptsp', 'index')->name('report-pbg-ptsp');
+ });
+ });
+
+ // approval
+ Route::group(['prefix' => '/approval'], function (){
+ Route::get('/list',[ApprovalController::class, 'index'])->name('approval-list');
+ });
+
+ // tools
+ Route::group(['prefix' => '/tools'], function (){
+ Route::get('/invitations', [InvitationsController::class, 'index'])->name('invitations');
});
});
\ No newline at end of file