From 84d2388eb85c4f26e914642f2c024493fe723c1a Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Thu, 6 Nov 2025 10:44:40 +0800 Subject: [PATCH 1/4] upd: coba upload file Deskripsi: - seafile upload - coba api upload file api No Issues --- src/server/lib/seafile.ts | 1 - src/server/routes/pengaduan_route.ts | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/server/lib/seafile.ts b/src/server/lib/seafile.ts index 8fd380a..776478f 100644 --- a/src/server/lib/seafile.ts +++ b/src/server/lib/seafile.ts @@ -158,7 +158,6 @@ export async function uploadFile(config: Config, file: File): Promise { }); const text = await res.text(); - console.log(text); if (!res.ok) throw new Error(`Upload failed: ${text}`); return `✅ Uploaded ${file.name} successfully`; diff --git a/src/server/routes/pengaduan_route.ts b/src/server/routes/pengaduan_route.ts index 2895ea7..cf62aa9 100644 --- a/src/server/routes/pengaduan_route.ts +++ b/src/server/routes/pengaduan_route.ts @@ -1,10 +1,9 @@ -import { swagger } from "@elysiajs/swagger" import Elysia, { t } from "elysia" import type { StatusPengaduan } from "generated/prisma" import { generateNoPengaduan } from "../lib/no-pengaduan" -import { prisma } from "../lib/prisma" -import { defaultConfigSF, testConnection, uploadFile } from "../lib/seafile" import { normalizePhoneNumber } from "../lib/normalizePhone" +import { prisma } from "../lib/prisma" +import { defaultConfigSF, uploadFile } from "../lib/seafile" const PengaduanRoute = new Elysia({ prefix: "pengaduan", @@ -432,7 +431,6 @@ const PengaduanRoute = new Elysia({ tags: ["mcp"] } }) - .use(swagger()) .post("/upload", async ({ body }) => { const { file } = body; @@ -442,16 +440,10 @@ const PengaduanRoute = new Elysia({ return { success: false, message: "File tidak ditemukan" }; } - // Contoh: cek koneksi ke Seafile - const coba = await testConnection(defaultConfigSF); - console.log("Seafile Connection:", coba); - // Upload ke Seafile (pastikan uploadFile menerima Blob atau ArrayBuffer) // const buffer = await file.arrayBuffer(); const result = await uploadFile(defaultConfigSF, file); - console.log("Upload result:", result); - return { success: true, message: "Upload berhasil", -- 2.49.1 From de594acbf62c7318a7638e4ec78c1f49631f3191 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Thu, 6 Nov 2025 11:29:40 +0800 Subject: [PATCH 2/4] upd: api pelayanan surat --- src/server/routes/pelayanan_surat_route.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/server/routes/pelayanan_surat_route.ts b/src/server/routes/pelayanan_surat_route.ts index 43cb9fe..69fdc98 100644 --- a/src/server/routes/pelayanan_surat_route.ts +++ b/src/server/routes/pelayanan_surat_route.ts @@ -2,6 +2,7 @@ import Elysia, { StatusMap, t } from "elysia" import { generateNoPengajuanSurat } from "../lib/no-pengajuan-surat" import { prisma } from "../lib/prisma" import type { StatusPengaduan } from "generated/prisma" +import { normalizePhoneNumber } from "../lib/normalizePhone" const PelayananRoute = new Elysia({ prefix: "pelayanan", @@ -22,7 +23,7 @@ const PelayananRoute = new Elysia({ }, { detail: { summary: "List Kategori Pelayanan Surat", - description: `tool untuk mendapatkan list kategori pelayanan surat`, + description: `tool untuk mendapatkan list kategori pelayanan surat beserta syaratnya untuk memenuhi syarat dokumen sesuai kategori yg dipilih saat melakukan pengajuan surat`, tags: ["mcp"] } }) @@ -175,9 +176,10 @@ const PelayananRoute = new Elysia({ }) if (!warga) { + const nomorHP = normalizePhoneNumber({ phone }) const cariWarga = await prisma.warga.findFirst({ where: { - phone, + phone: nomorHP, } }) @@ -185,7 +187,7 @@ const PelayananRoute = new Elysia({ const wargaCreate = await prisma.warga.create({ data: { name: idWarga, - phone, + phone: nomorHP, }, select: { id: true @@ -210,7 +212,7 @@ const PelayananRoute = new Elysia({ }) if (!pengaduan.id) { - throw new Error("gagal membuat pengaduan") + throw new Error("gagal membuat pengajuan surat") } let dataInsertSyaratDokumen = [] @@ -270,7 +272,7 @@ const PelayananRoute = new Elysia({ }), detail: { summary: "Create Pengajuan Pelayanan Surat", - description: `tool untuk membuat pengajuan pelayanan surat`, + description: `tool untuk membuat pengajuan pelayanan surat dengan syarat dokumen serta data text sesuai kategori pelayanan surat yang dipilih`, tags: ["mcp"] } }) -- 2.49.1 From df7f93c7949048d30411f65f5a1beb5cae6a1822 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Thu, 6 Nov 2025 12:23:25 +0800 Subject: [PATCH 3/4] upd: configurasi desa Deskripsi: - update table database - seeder configurasi desa NO Issues --- prisma/schema.prisma | 2 +- prisma/seed.ts | 13 ++++++-- src/lib/configurationDesa.ts | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/lib/configurationDesa.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5034611..d30cbbb 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -193,7 +193,7 @@ model SuratPelayanan { model Configuration { id String @id @default(cuid()) - category String + name String value String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/prisma/seed.ts b/prisma/seed.ts index dca6791..56b5941 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,4 +1,5 @@ import { categoryPelayananSurat } from "@/lib/categoryPelayananSurat"; +import { confDesa } from "@/lib/configurationDesa"; import { prisma } from "@/server/lib/prisma"; const category = [ @@ -51,7 +52,6 @@ const user = [ (async () => { for (const r of role) { - console.log(`Seeding role ${r.name}`) await prisma.role.upsert({ where: { id: r.id }, create: r, @@ -81,7 +81,7 @@ const user = [ console.log(`✅ Category ${c.name} seeded successfully`) } - for (const cp of categoryPelayananSurat){ + for (const cp of categoryPelayananSurat) { await prisma.categoryPelayanan.upsert({ where: { id: cp.id }, create: cp, @@ -91,6 +91,15 @@ const user = [ console.log(`✅ Category Pelayanan ${cp.name} seeded successfully`) } + for (const c of confDesa) { + await prisma.configuration.upsert({ + where: { id: c.id }, + create: c, + update: c + }) + + console.log(`✅ Configuration ${c.name} seeded successfully`) + } diff --git a/src/lib/configurationDesa.ts b/src/lib/configurationDesa.ts new file mode 100644 index 0000000..fe8dd0e --- /dev/null +++ b/src/lib/configurationDesa.ts @@ -0,0 +1,57 @@ +export const confDesa = [ + { + id: "desaNama", + name: "Nama Desa", + value: "Darmasaba" + }, + { + id: "desaKabupaten", + name: "Kabupaten", + value: "Badung" + }, + { + id: "desaKecamatan", + name: "Kecamatan", + value: "Abiansemal" + }, + { + id: "desaAlamat", + name: "Alamat Kantor Desa", + value: "Jl. Raya Darmasaba No.22, Darmasaba" + }, + { + id: "desaPos", + name: "Kode Pos", + value: "80352" + }, + { + id: "desaTelepon", + name: "Telepon", + value: "081239580000" + }, + { + id: "desaEmail", + name: "Email", + value: "desadarmasaba@badungkab.go.id" + }, + { + id: "perbekelNama", + name: "Nama Perbekel", + value: "Ida Bagus Surya Prabhawa Manuaba, S.H., M.H., N.L.P." + }, + { + id: "perbekelJabatan", + name: "Jabatan", + value: "Perbekel" + }, + { + id: "perbekelNIP", + name: "NIP", + value: "" + }, + { + id: "perbekelTTD", + name: "TTD", + value: "" + }, +]; -- 2.49.1 From 89e83d806e2275b7ad39d06a2313ba1c72db7a21 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Thu, 6 Nov 2025 17:37:21 +0800 Subject: [PATCH 4/4] upd: dashboard Deskripsi: - menu dashboard - tampilan pengaduan list No Issues --- src/AppRoutes.tsx | 33 ++-- src/clientRoutes.ts | 1 + src/pages/dir/dir_page.tsx | 20 +- src/pages/scr/dashboard/dashboard_layout.tsx | 45 ++++- .../scr/dashboard/pengaduan/list_page.tsx | 186 ++++++++++++++++++ 5 files changed, 253 insertions(+), 32 deletions(-) create mode 100644 src/pages/scr/dashboard/pengaduan/list_page.tsx diff --git a/src/AppRoutes.tsx b/src/AppRoutes.tsx index 14289f7..18589c7 100644 --- a/src/AppRoutes.tsx +++ b/src/AppRoutes.tsx @@ -1,27 +1,28 @@ // ⚡ Auto-generated by generateRoutes.ts — DO NOT EDIT MANUALLY -import { BrowserRouter, Routes, Route } from "react-router-dom"; -import Login from "./pages/Login"; -import DarmasabaLayout from "./pages/darmasaba/darmasaba_layout"; -import FormSuratKeteranganUsaha from "./pages/darmasaba/form_surat_keterangan_usaha"; -import FormSuratKeteranganTidakMampu from "./pages/darmasaba/form_surat_keterangan_tidak_mampu"; +import { BrowserRouter, Route, Routes } from "react-router-dom"; import DarmasabaHome from "./pages/darmasaba/darmasaba_home"; -import FormKartuTandaPenduduk from "./pages/darmasaba/form_kartu_tanda_penduduk"; +import DarmasabaLayout from "./pages/darmasaba/darmasaba_layout"; import FormKartuKeluarga from "./pages/darmasaba/form_kartu_keluarga"; -import FormLaporanSampah from "./pages/darmasaba/form_laporan_sampah"; -import FormSuratKeteranganPenghasilan from "./pages/darmasaba/form_surat_keterangan_penghasilan"; -import FormSuratKeteranganDomisiliOrganisasi from "./pages/darmasaba/form_surat_keterangan_domisili_organisasi"; -import FormSuratKeteranganBelumKawin from "./pages/darmasaba/form_surat_keterangan_belum_kawin"; +import FormKartuTandaPenduduk from "./pages/darmasaba/form_kartu_tanda_penduduk"; import FormKeteranganKelahiran from "./pages/darmasaba/form_keterangan_kelahiran"; -import FormSuratKeteranganTempatUsaha from "./pages/darmasaba/form_surat_keterangan_tempat_usaha"; +import FormLaporanSampah from "./pages/darmasaba/form_laporan_sampah"; +import FormSuratKeteranganBelumKawin from "./pages/darmasaba/form_surat_keterangan_belum_kawin"; +import FormSuratKeteranganDomisiliOrganisasi from "./pages/darmasaba/form_surat_keterangan_domisili_organisasi"; import FormSuratKeteranganKelakuanBaik from "./pages/darmasaba/form_surat_keterangan_kelakuan_baik"; +import FormSuratKeteranganPenghasilan from "./pages/darmasaba/form_surat_keterangan_penghasilan"; +import FormSuratKeteranganTempatUsaha from "./pages/darmasaba/form_surat_keterangan_tempat_usaha"; +import FormSuratKeteranganTidakMampu from "./pages/darmasaba/form_surat_keterangan_tidak_mampu"; +import FormSuratKeteranganUsaha from "./pages/darmasaba/form_surat_keterangan_usaha"; +import DirPage from "./pages/dir/dir_page"; import Home from "./pages/Home"; +import Login from "./pages/Login"; +import NotFound from "./pages/NotFound"; +import ApikeyPage from "./pages/scr/dashboard/apikey/apikey_page"; import CredentialPage from "./pages/scr/dashboard/credential/credential_page"; import DashboardHome from "./pages/scr/dashboard/dashboard_home"; -import ApikeyPage from "./pages/scr/dashboard/apikey/apikey_page"; import DashboardLayout from "./pages/scr/dashboard/dashboard_layout"; +import ListPage from "./pages/scr/dashboard/pengaduan/list_page"; import ScrLayout from "./pages/scr/scr_layout"; -import DirPage from "./pages/dir/dir_page"; -import NotFound from "./pages/NotFound"; export default function AppRoutes() { return ( @@ -92,6 +93,10 @@ export default function AppRoutes() { path="/scr/dashboard/dashboard-home" element={} /> + } + /> } diff --git a/src/clientRoutes.ts b/src/clientRoutes.ts index 6c4d06c..5db3d11 100644 --- a/src/clientRoutes.ts +++ b/src/clientRoutes.ts @@ -19,6 +19,7 @@ const clientRoutes = { "/scr/dashboard": "/scr/dashboard", "/scr/dashboard/credential/credential": "/scr/dashboard/credential/credential", "/scr/dashboard/dashboard-home": "/scr/dashboard/dashboard-home", + "/scr/dashboard/pengaduan/list": "/scr/dashboard/pengaduan/list", "/scr/dashboard/apikey/apikey": "/scr/dashboard/apikey/apikey", "/dir/dir": "/dir/dir", "/*": "/*" diff --git a/src/pages/dir/dir_page.tsx b/src/pages/dir/dir_page.tsx index c28ac42..61d0028 100644 --- a/src/pages/dir/dir_page.tsx +++ b/src/pages/dir/dir_page.tsx @@ -2,16 +2,16 @@ import { Tree } from "@mantine/core"; // ✅ Valid data, all values are unique const data = [ - { - value: 'src', - label: 'src', - children: [ - { value: 'src/components', label: 'components' }, - { value: 'src/hooks', label: 'hooks' }, - ], - }, - { value: 'package.json', label: 'package.json' }, - ]; + { + value: "src", + label: "src", + children: [ + { value: "src/components", label: "components" }, + { value: "src/hooks", label: "hooks" }, + ], + }, + { value: "package.json", label: "package.json" }, +]; export default function DirPage() { return ( diff --git a/src/pages/scr/dashboard/dashboard_layout.tsx b/src/pages/scr/dashboard/dashboard_layout.tsx index f902969..21c53bb 100644 --- a/src/pages/scr/dashboard/dashboard_layout.tsx +++ b/src/pages/scr/dashboard/dashboard_layout.tsx @@ -1,4 +1,8 @@ -import { useEffect, useState } from "react"; +import { + default as clientRoute, + default as clientRoutes, +} from "@/clientRoutes"; +import apiFetch from "@/lib/apiFetch"; import { ActionIcon, AppShell, @@ -22,17 +26,17 @@ import { IconChevronLeft, IconChevronRight, IconDashboard, + IconFileCertificate, IconKey, IconLock, + IconMessageReport, + IconSettings, IconUser, + IconUsersGroup, } from "@tabler/icons-react"; import type { User } from "generated/prisma"; +import { useEffect, useState } from "react"; import { Outlet, useLocation, useNavigate } from "react-router-dom"; -import { - default as clientRoute, - default as clientRoutes, -} from "@/clientRoutes"; -import apiFetch from "@/lib/apiFetch"; function Logout() { return ( @@ -98,7 +102,7 @@ export default function DashboardLayout() { size="lg" style={{ backgroundColor: "rgba(255,255,255,0.05)", - boxShadow: "0 0 6px rgba(0,255,200,0.2)", + boxShadow: "0 0 6px hsla(167, 100%, 50%, 0.20), 0.20)", }} > {opened ? : } @@ -186,7 +190,7 @@ function HostView() { {host.name} - {host.email} + {host.roleId} @@ -219,6 +223,31 @@ function NavigationDashboard() { label: "Dashboard Overview", description: "Quick summary and insights", }, + { + path: "/scr/dashboard/pengaduan/list", + icon: , + label: "Pengaduan Warga", + description: "Manage pengaduan warga", + }, + { + path: "/scr/dashboard/pelayanan", + icon: , + label: "Pelayanan Surat", + description: "Manage pelayanan surat", + }, + { + path: "/scr/dashboard/user", + icon: , + label: "User", + description: "Manage user", + }, + { + path: "/scr/dashboard/setting", + icon: , + label: "Setting", + description: + "Manage setting (category pengaduan dan pelayanan surat, desa, etc)", + }, { path: "/scr/dashboard/apikey/apikey", icon: , diff --git a/src/pages/scr/dashboard/pengaduan/list_page.tsx b/src/pages/scr/dashboard/pengaduan/list_page.tsx new file mode 100644 index 0000000..7682a34 --- /dev/null +++ b/src/pages/scr/dashboard/pengaduan/list_page.tsx @@ -0,0 +1,186 @@ +import apiFetch from "@/lib/apiFetch"; +import { + Badge, + Card, + Container, + Divider, + Flex, + Group, + Stack, + Tabs, + Text, + Title +} from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { showNotification } from "@mantine/notifications"; +import { IconAlignJustified, IconClockHour3, IconMapPin } from "@tabler/icons-react"; +import { useLocation, useNavigate } from "react-router-dom"; +import useSwr from "swr"; +import { proxy, subscribe } from "valtio"; + +const state = proxy({ reload: "" }); +function reloadState() { + state.reload = Math.random().toString(); +} + +export default function PengaduanListPage() { + const { search } = useLocation(); + const query = new URLSearchParams(search); + + const status = query.get("status"); + console.log(status, "status"); + + return ( + + + + + + + ); +} + +function TabListPengaduan({ status }: { status: string }) { + const navigate = useNavigate(); + return ( + + + { navigate("?status=all") }}>Semua + { navigate("?status=antrian") }}>Antrian + { navigate("?status=diterima") }}>Diterima + { navigate("?status=dikerjakan") }}>Dikerjakan + { navigate("?status=ditolak") }}>Ditolak + { navigate("?status=selesai") }}>Selesai + + + ); +} + +function ListPengaduan() { + const { data, mutate, isLoading } = useSwr("/", () => + apiFetch.api.credential.list.get(), + ); + + useShallowEffect(() => { + const unsubscribe = subscribe(state, () => mutate()); + return () => unsubscribe(); + }, []); + + async function handleRemove(id: string) { + try { + await apiFetch.api.credential.rm.delete({ id }); + showNotification({ + color: "teal", + title: "Credential Deleted", + message: "The credential was successfully removed.", + }); + reloadState(); + } catch { + showNotification({ + color: "red", + title: "Error", + message: "Failed to delete credential. Please try again.", + }); + } + } + + if (isLoading) + return ( + + + Loading credentials... + + + ); + + const list = data?.data?.list || []; + + return ( + + + + + + Dompet Hilang + + + + #PGD-061125-001 + + + updated 2 minutes ago + + + + + Antrian + + + + + + + + + Tanggal Aduan + + + + 05 November 2025 + + + + + + + Lokasi + + + + Jalan Darmasaba Raya no 77 + + + + + + + Detail + + + + Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quis, obcaecati. Sint natus culpa temporibus neque quasi expedita ratione, facere optio incidunt quibusdam suscipit nam nemo delectus beatae similique velit obcaecati? + + + + + + ); +} -- 2.49.1