feat(keamanan): tambah modul CCTV — schema, API, admin UI, seeder
- Tambah model CctvKeamanan + enum StatusCctv ke prisma schema - Tambah status Baru ke enum StatusLaporan - Migration: add_cctv_keamanan_model - API CRUD + stats endpoint di /api/keamanan/cctv/... - Admin state (valtio proxy) dengan create/findMany/edit/delete/stats - Admin pages: list, create, detail (peta Leaflet), edit (peta picker) - Seeder 8 data CCTV lokasi Darmasaba - Tambah submenu CCTV di sidebar nav keamanan - Bump version 0.1.57 → 0.1.58 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
35
prisma/_seeder_list/keamanan/seed_cctv.ts
Normal file
35
prisma/_seeder_list/keamanan/seed_cctv.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { loadJsonData } from "../../load-json";
|
||||
|
||||
const cctvData = loadJsonData("keamanan/cctv/cctv.json");
|
||||
|
||||
export async function seedCctv() {
|
||||
console.log("🔄 Seeding CCTV Keamanan...");
|
||||
|
||||
for (const c of cctvData) {
|
||||
await prisma.cctvKeamanan.upsert({
|
||||
where: { id: c.id },
|
||||
update: {
|
||||
kode: c.kode,
|
||||
nama: c.nama,
|
||||
lokasi: c.lokasi,
|
||||
latitude: c.latitude ?? null,
|
||||
longitude: c.longitude ?? null,
|
||||
status: c.status,
|
||||
lastActive: new Date(c.lastActive),
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
kode: c.kode,
|
||||
nama: c.nama,
|
||||
lokasi: c.lokasi,
|
||||
latitude: c.latitude ?? null,
|
||||
longitude: c.longitude ?? null,
|
||||
status: c.status,
|
||||
lastActive: new Date(c.lastActive),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✅ CCTV Keamanan seeded: ${cctvData.length} data`);
|
||||
}
|
||||
82
prisma/data/keamanan/cctv/cctv.json
Normal file
82
prisma/data/keamanan/cctv/cctv.json
Normal file
@@ -0,0 +1,82 @@
|
||||
[
|
||||
{
|
||||
"id": "cctv_darmasaba_01",
|
||||
"kode": "CCTV-01",
|
||||
"nama": "Balai Desa",
|
||||
"lokasi": "Jl. Raya Darmasaba, Depan Balai Desa",
|
||||
"latitude": -8.5712,
|
||||
"longitude": 115.1923,
|
||||
"status": "Online",
|
||||
"lastActive": "2026-02-12T14:30:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_02",
|
||||
"kode": "CCTV-02",
|
||||
"nama": "Pintu Masuk Desa Utara",
|
||||
"lokasi": "Jl. Raya Darmasaba, Pintu Masuk Utara",
|
||||
"latitude": -8.5685,
|
||||
"longitude": 115.1917,
|
||||
"status": "Online",
|
||||
"lastActive": "2026-02-12T13:45:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_03",
|
||||
"kode": "CCTV-03",
|
||||
"nama": "Taman Desa",
|
||||
"lokasi": "Area Taman Desa Darmasaba",
|
||||
"latitude": -8.5730,
|
||||
"longitude": 115.1935,
|
||||
"status": "Offline",
|
||||
"lastActive": "2026-02-11T09:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_04",
|
||||
"kode": "CCTV-04",
|
||||
"nama": "Pasar Desa",
|
||||
"lokasi": "Pasar Tradisional Darmasaba",
|
||||
"latitude": -8.5698,
|
||||
"longitude": 115.1945,
|
||||
"status": "Online",
|
||||
"lastActive": "2026-02-12T15:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_05",
|
||||
"kode": "CCTV-05",
|
||||
"nama": "Pintu Masuk Desa Selatan",
|
||||
"lokasi": "Jl. Raya Darmasaba, Pintu Masuk Selatan",
|
||||
"latitude": -8.5755,
|
||||
"longitude": 115.1920,
|
||||
"status": "Online",
|
||||
"lastActive": "2026-02-12T14:55:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_06",
|
||||
"kode": "CCTV-06",
|
||||
"nama": "SD Negeri Darmasaba",
|
||||
"lokasi": "Depan SD Negeri 1 Darmasaba",
|
||||
"latitude": -8.5720,
|
||||
"longitude": 115.1910,
|
||||
"status": "Online",
|
||||
"lastActive": "2026-02-12T12:30:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_07",
|
||||
"kode": "CCTV-07",
|
||||
"nama": "Pura Desa",
|
||||
"lokasi": "Area Pura Desa Darmasaba",
|
||||
"latitude": -8.5708,
|
||||
"longitude": 115.1950,
|
||||
"status": "Offline",
|
||||
"lastActive": "2026-02-10T18:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "cctv_darmasaba_08",
|
||||
"kode": "CCTV-08",
|
||||
"nama": "Persimpangan Utama",
|
||||
"lokasi": "Persimpangan Jl. Raya Darmasaba - Jl. Abiansemal",
|
||||
"latitude": -8.5695,
|
||||
"longitude": 115.1930,
|
||||
"status": "Online",
|
||||
"lastActive": "2026-02-12T15:10:00.000Z"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "StatusCctv" AS ENUM ('Online', 'Offline');
|
||||
|
||||
-- AlterEnum
|
||||
ALTER TYPE "StatusLaporan" ADD VALUE 'Baru';
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CctvKeamanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"kode" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"lokasi" TEXT NOT NULL,
|
||||
"latitude" DOUBLE PRECISION,
|
||||
"longitude" DOUBLE PRECISION,
|
||||
"status" "StatusCctv" NOT NULL DEFAULT 'Online',
|
||||
"lastActive" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "CctvKeamanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
@@ -1395,11 +1395,33 @@ model PenangananLaporanPublik {
|
||||
}
|
||||
|
||||
enum StatusLaporan {
|
||||
Baru
|
||||
Selesai
|
||||
Proses
|
||||
Gagal
|
||||
}
|
||||
|
||||
// ========================================= CCTV KEAMANAN ========================================= //
|
||||
enum StatusCctv {
|
||||
Online
|
||||
Offline
|
||||
}
|
||||
|
||||
model CctvKeamanan {
|
||||
id String @id @default(cuid())
|
||||
kode String // e.g. "CCTV-01"
|
||||
nama String // e.g. "Balai Desa"
|
||||
lokasi String
|
||||
latitude Float?
|
||||
longitude Float?
|
||||
status StatusCctv @default(Online)
|
||||
lastActive DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model Pelapor {
|
||||
id String @id @default(cuid())
|
||||
nama String
|
||||
|
||||
@@ -32,6 +32,7 @@ import { seedInfoTeknologi } from "./_seeder_list/inovasi/seed_info_teknologi";
|
||||
import { seedKolaborasiInovasi } from "./_seeder_list/inovasi/seed_kolaborasi_inovasi";
|
||||
import { seedLayananOnlineDesa } from "./_seeder_list/inovasi/seed_layanan_online_desa";
|
||||
import { seedProgramKreatifDesa } from "./_seeder_list/inovasi/seed_program_kreatif_desa";
|
||||
import { seedCctv } from "./_seeder_list/keamanan/seed_cctv";
|
||||
import { seedKeamananLingkungan } from "./_seeder_list/keamanan/seed_keamanan_lingkungan";
|
||||
import { seedKontakDaruratKeamanan } from "./_seeder_list/keamanan/seed_kontak_darurat";
|
||||
import { seedLaporanPublik } from "./_seeder_list/keamanan/seed_laporan_publik";
|
||||
@@ -280,6 +281,8 @@ import seedAssets from "./seed_assets";
|
||||
await seedPencegahanKriminalitas();
|
||||
// // ==================== SUBMENU LAPORAN PUBLIK =================
|
||||
await seedLaporanPublik();
|
||||
// // ==================== SUBMENU CCTV KEAMANAN ==================
|
||||
await seedCctv();
|
||||
|
||||
// // ==================== SUBMENU TIPS KEAMANAN ==================
|
||||
await seedKeamananLingkungan();
|
||||
|
||||
Reference in New Issue
Block a user