diff --git a/app/dashboard/coordinator/page.tsx b/app/dashboard/coordinator/page.tsx
new file mode 100644
index 0000000..cfda816
--- /dev/null
+++ b/app/dashboard/coordinator/page.tsx
@@ -0,0 +1,13 @@
+import DashboardNavbar from "@/components/dashboard/dashboard-navbar";
+import CoordinatorTable from "@/components/table/coordinator-table";
+
+export default function CoordinatorPage() {
+ return (
+
+
+ Deskripsi
+
+ {data.deskripsi}
+
Durasi
diff --git a/components/form/campaign-form.tsx b/components/form/campaign-form.tsx
index 205cd61..3a31d44 100644
--- a/components/form/campaign-form.tsx
+++ b/components/form/campaign-form.tsx
@@ -24,6 +24,8 @@ import { id } from "date-fns/locale";
import { Progress } from "../ui/progress";
import DialogMediaOnline from "../dialog/media-online";
import DialogMediaSosial from "../dialog/media-sosial";
+import MapVideotron from "../global/maps";
+import dynamic from "next/dynamic";
export default function FormCampaign() {
const [startDate, setStartDate] = useState(undefined);
@@ -34,6 +36,10 @@ export default function FormCampaign() {
const [media, setMedia] = useState("Media Online");
const [isDialogOpen, setIsDialogOpen] = useState(false);
+ const MapVideotron = dynamic(() => import("../global/maps"), {
+ ssr: false,
+ });
+
// contoh data pilihan media online (bisa diganti sesuai kebutuhan)
const mediaOnlineList = [
"Tribrata News Mabes",
@@ -44,10 +50,13 @@ export default function FormCampaign() {
];
const [selectedMediaOnline, setSelectedMediaOnline] = useState([]);
+ const [contentType, setContentType] = useState("Meme");
+ const [talkshowType, setTalkshowType] = useState("Renjani Nyrah");
+ const [musicType, setMusicType] = useState("Sendrasena");
const toggleMediaOnline = (item: string) => {
setSelectedMediaOnline((prev) =>
- prev.includes(item) ? prev.filter((m) => m !== item) : [...prev, item]
+ prev.includes(item) ? prev.filter((m) => m !== item) : [...prev, item],
);
};
@@ -73,7 +82,7 @@ export default function FormCampaign() {
// ✅ Simulasi upload progress
const simulateUpload = (
- fileList: { file: File; progress: number; uploaded: boolean }[]
+ fileList: { file: File; progress: number; uploaded: boolean }[],
) => {
fileList.forEach((fileObj) => {
let progress = 0;
@@ -83,8 +92,8 @@ export default function FormCampaign() {
prev.map((f) =>
f.file === fileObj.file
? { ...f, progress, uploaded: progress >= 100 }
- : f
- )
+ : f,
+ ),
);
if (progress >= 100) clearInterval(interval);
}, 300);
@@ -214,17 +223,11 @@ export default function FormCampaign() {
Tambahkan Media Sosial
)}
-
{media === "Videotron" && (
-
+
+ {/* Map tampil */}
+
+
)}
{/* 🧩 Komponen DialogMediaOnline dipanggil di sini */}
@@ -325,28 +328,332 @@ export default function FormCampaign() {
{available === "Yes" ? (
- // ✅ Jika user pilih "Yes" → tampil upload file
+ // ✅ Upload
-
-
-
+
) : (
- // ✅ Jika user pilih "Tidak" → tampil textarea deskripsi
-
-
-
+ // ❌ Tidak → tampil pilihan konten
+
+ {/* Pilih Jenis Konten */}
+
+
Pilih Jenis Konten
+
+
+ {["Meme", "AI Influencer", "Talkshow", "Musik"].map((item) => (
+
+
+
+
+ ))}
+
+
+
+ {/* List Konten (Dummy) */}
+ {/* List Konten */}
+
+
Pilih {contentType}
+
+ {/* 🔥 TAMPILAN KHUSUS MEME */}
+ {contentType === "Meme" && (
+
+ {/* Search */}
+
+
+
+ 🔍
+
+
+
+ {/* Grid Meme */}
+
+ {[
+ {
+ img: "/meme1.png",
+ title:
+ "Respons Cepat Lakukan Sterilisasi Ancaman Bom di Depok",
+ },
+ {
+ img: "/meme2.png",
+ title: "Upacara Penutupan Pendidikan Anggota Polri",
+ },
+ {
+ img: "/meme3.png",
+ title: "Pantau Situasi Kamtibmas Malam Natal",
+ },
+ {
+ img: "/meme4.png",
+ title: "Program SPPG Bersama Penerima Manfaat",
+ },
+ ].map((item, i) => (
+
+
+

+
+
+
+
+ ⛶
+
+
+
+
+ {item.title}
+
+
+ ))}
+
+
+ )}
+
+ {contentType === "AI Influencer" && (
+
+ {/* Search */}
+
+
+
+ 🔍
+
+
+
+ {/* Grid AI */}
+
+ {[
+ { img: "/ai1.png", name: "Revandra Jaya" },
+ { img: "/ai2.png", name: "Fudhalina Adisty" },
+ { img: "/ai3.png", name: "Adriyan Pratama" },
+ { img: "/ai4.png", name: "Nadhya Wijaya" },
+ ].map((item, i) => (
+
+ {/* Image */}
+

+
+ {/* Overlay bawah */}
+
+
+
+ {item.name}
+
+
+
+ ))}
+
+
+ {/* Footer */}
+
+
Rows per page: 1
+
1-1 of 1
+
+
+
+
+
+
+ )}
+ {contentType === "Talkshow" && (
+
+ {/* Select Talkshow */}
+
+
Pilih Talkshow
+
+
+
+
+ {/* Konten berdasarkan pilihan */}
+
+ {(talkshowType === "Renjani Nyrah"
+ ? [
+ {
+ img: "/ts1.jpg",
+ title: "Renjani Nyrah - Napak Tilas di Museum",
+ },
+ {
+ img: "/ts2.jpg",
+ title: "Renjani Nyrah - Kata Kata Baru",
+ },
+ {
+ img: "/ts3.jpg",
+ title: "Renjani Nyrah - Pestapora 2025",
+ },
+ ]
+ : [
+ {
+ img: "/agatha1.jpg",
+ title: "Agatha Bicara - Kerja DPR Itu Apa?",
+ },
+ {
+ img: "/agatha1.jpg",
+ title: "Agatha Bicara - Kerja DPR Itu Apa?",
+ },
+ {
+ img: "/agatha2.png",
+ title: "Agatha Bicara - Penghargaan dari Presiden",
+ },
+ ]
+ ).map((item, i) => (
+
+ {/* Image */}
+
+

+
+ {/* Checkbox */}
+
+
+ {/* Expand icon */}
+
+ ⛶
+
+
+
+ {/* Title */}
+
+ {item.title}
+
+
+ ))}
+
+
+ )}
+ {contentType === "Musik" && (
+
+ {/* Dropdown Musik */}
+
+
Pilih Musik
+
+
+
+
+ {/* Grid Musik */}
+
+ {(musicType === "Sendrasena"
+ ? [
+ {
+ img: "/m1.jpg",
+ title: "Sendrasena - Track 1",
+ },
+ {
+ img: "/m2.jpg",
+ title: "Sendrasena - Track 2",
+ },
+ {
+ img: "/m3.jpg",
+ title: "Sendrasena - Track 3",
+ },
+ {
+ img: "/m4.jpg",
+ title: "Sendrasena - Track 4",
+ },
+ ]
+ : [
+ {
+ img: "/sl1.jpg",
+ title: "Selara Luna - Track 1",
+ },
+ {
+ img: "/sl2.jpg",
+ title: "Selara Luna - Track 2",
+ },
+ {
+ img: "/sl3.jpg",
+ title: "Selara Luna - Track 3",
+ },
+ {
+ img: "/sl4.jpg",
+ title: "Selara Luna - Track 4",
+ },
+ ]
+ ).map((item, i) => (
+
+ {/* Cover */}
+
+

+
+ {/* Checkbox */}
+
+
+ {/* Play icon (biar beda dari talkshow 😄) */}
+
+ ▶
+
+
+
+ {/* Title */}
+
+ {item.title}
+
+
+ ))}
+
+
+ )}
+
)}
diff --git a/components/form/login.tsx b/components/form/login.tsx
index 41a6a11..273647d 100644
--- a/components/form/login.tsx
+++ b/components/form/login.tsx
@@ -12,7 +12,6 @@ import { useRouter } from "next/navigation";
import Footer from "../landing-page/footer";
import Navbar from "../landing-page/navbar";
-// ✅ Dummy user data
const users = [
{
nrp: "1001",
@@ -26,14 +25,19 @@ const users = [
},
{
nrp: "1003",
- password: "super123",
- role: "supervisor",
+ password: "executive123",
+ role: "executive",
},
{
nrp: "1004",
password: "approve123",
role: "approver",
},
+ {
+ nrp: "1005",
+ password: "coordinator123",
+ role: "kordinator",
+ },
];
export default function Login() {
@@ -66,12 +70,15 @@ export default function Login() {
case "user":
router.push("/dashboard/user");
break;
- case "supervisor":
+ case "executive":
router.push("/dashboard/supervisor");
break;
case "approver":
router.push("/dashboard/approver");
break;
+ case "kordinator":
+ router.push("/dashboard/coordinator");
+ break;
default:
router.push("/");
}
diff --git a/components/global/maps.tsx b/components/global/maps.tsx
new file mode 100644
index 0000000..9e726f1
--- /dev/null
+++ b/components/global/maps.tsx
@@ -0,0 +1,13 @@
+"use client";
+
+export default function MapVideotron() {
+ return (
+
+
+
+ );
+}
diff --git a/components/table/coordinator-table.tsx b/components/table/coordinator-table.tsx
new file mode 100644
index 0000000..7cfc0e0
--- /dev/null
+++ b/components/table/coordinator-table.tsx
@@ -0,0 +1,122 @@
+"use client";
+
+import Link from "next/link";
+import { useState } from "react";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { Button } from "@/components/ui/button";
+import { Eye } from "lucide-react";
+import DialogCampaignDetail from "../dialog/campaign-detail";
+
+export default function CoordinatorTable() {
+ const data = [
+ {
+ durasi: "22/08/2025 - 22/08/2026",
+ media: "Media Online",
+ tujuan: "Sosialisasi",
+ materi: "Tersedia",
+ description:
+ "Lorem ipsum dolor sit amet consectetur. Tempor mi scelerisque enim semper sed nibh.",
+ status: "Selesai",
+ },
+ {
+ durasi: "22/08/2025 - 22/08/2026",
+ media: "Media Sosial",
+ tujuan: "Sosialisasi",
+ materi: "Tersedia",
+ description:
+ "Ultricies pellentesque ullamcorper mattis pellentesque. Amet eu ut.",
+ status: "Selesai",
+ },
+ ];
+
+ const [selectedRow, setSelectedRow] = useState
(null);
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
+
+ const openDetail = (row: any) => {
+ setSelectedRow(row);
+ setIsDialogOpen(true);
+ };
+
+ return (
+ <>
+
+
+
+
+
+ Durasi
+ Media
+ Tujuan
+ Materi
+ Deskripsi Promote
+ Status
+ Tindakan
+
+
+
+
+ {data.map((row, i) => (
+
+ {row.durasi}
+ {row.media}
+ {row.tujuan}
+ {row.materi}
+
+ {row.description}
+
+
+
+ {row.status}
+
+
+
+
+
+
+ ))}
+
+
+
+
+ {/* Pagination */}
+
+
+ Rows per page:
+
+
+
+
+
+
+
+ setIsDialogOpen(false)}
+ data={selectedRow}
+ />
+ >
+ );
+}
diff --git a/package-lock.json b/package-lock.json
index 20fe566..68cb3ff 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,12 +25,14 @@
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"js-cookie": "^3.0.5",
+ "leaflet": "^1.9.4",
"lucide-react": "^0.552.0",
"next": "16.0.1",
"react": "19.2.0",
"react-apexcharts": "^1.8.0",
"react-day-picker": "^9.11.1",
"react-dom": "19.2.0",
+ "react-leaflet": "^4.2.1",
"recharts": "^3.8.1",
"tailwind-merge": "^3.3.1"
},
@@ -1936,6 +1938,16 @@
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
},
+ "node_modules/@react-leaflet/core": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz",
+ "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==",
+ "peerDependencies": {
+ "leaflet": "^1.9.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ }
+ },
"node_modules/@reduxjs/toolkit": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz",
@@ -2196,7 +2208,7 @@
"version": "19.2.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -2205,7 +2217,7 @@
"version": "19.2.2",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz",
"integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==",
- "devOptional": true,
+ "dev": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -2431,7 +2443,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "devOptional": true
+ "dev": true
},
"node_modules/d3-array": {
"version": "3.2.4",
@@ -2847,6 +2859,11 @@
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
+ "node_modules/leaflet": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
+ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
+ },
"node_modules/lightningcss": {
"version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
@@ -3169,6 +3186,19 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "node_modules/react-leaflet": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz",
+ "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==",
+ "dependencies": {
+ "@react-leaflet/core": "^2.1.0"
+ },
+ "peerDependencies": {
+ "leaflet": "^1.9.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ }
+ },
"node_modules/react-redux": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
diff --git a/package.json b/package.json
index bc9e9d9..3f6cf8b 100644
--- a/package.json
+++ b/package.json
@@ -25,12 +25,14 @@
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"js-cookie": "^3.0.5",
+ "leaflet": "^1.9.4",
"lucide-react": "^0.552.0",
"next": "16.0.1",
"react": "19.2.0",
"react-apexcharts": "^1.8.0",
"react-day-picker": "^9.11.1",
"react-dom": "19.2.0",
+ "react-leaflet": "^4.2.1",
"recharts": "^3.8.1",
"tailwind-merge": "^3.3.1"
},
diff --git a/public/agatha1.jpg b/public/agatha1.jpg
new file mode 100644
index 0000000..e8207c8
Binary files /dev/null and b/public/agatha1.jpg differ
diff --git a/public/agatha2.png b/public/agatha2.png
new file mode 100644
index 0000000..7b47ce2
Binary files /dev/null and b/public/agatha2.png differ
diff --git a/public/ai1.png b/public/ai1.png
new file mode 100644
index 0000000..27ad9cc
Binary files /dev/null and b/public/ai1.png differ
diff --git a/public/ai2.png b/public/ai2.png
new file mode 100644
index 0000000..839b9a8
Binary files /dev/null and b/public/ai2.png differ
diff --git a/public/ai3.png b/public/ai3.png
new file mode 100644
index 0000000..24cd253
Binary files /dev/null and b/public/ai3.png differ
diff --git a/public/ai4.png b/public/ai4.png
new file mode 100644
index 0000000..fe0acff
Binary files /dev/null and b/public/ai4.png differ
diff --git a/public/m1.jpg b/public/m1.jpg
new file mode 100644
index 0000000..000cb37
Binary files /dev/null and b/public/m1.jpg differ
diff --git a/public/m2.jpg b/public/m2.jpg
new file mode 100644
index 0000000..91e2368
Binary files /dev/null and b/public/m2.jpg differ
diff --git a/public/m3.jpg b/public/m3.jpg
new file mode 100644
index 0000000..5801885
Binary files /dev/null and b/public/m3.jpg differ
diff --git a/public/m4.jpg b/public/m4.jpg
new file mode 100644
index 0000000..c908663
Binary files /dev/null and b/public/m4.jpg differ
diff --git a/public/meme1.png b/public/meme1.png
new file mode 100644
index 0000000..ddde015
Binary files /dev/null and b/public/meme1.png differ
diff --git a/public/meme2.png b/public/meme2.png
new file mode 100644
index 0000000..61d73fc
Binary files /dev/null and b/public/meme2.png differ
diff --git a/public/meme3.png b/public/meme3.png
new file mode 100644
index 0000000..15e3f18
Binary files /dev/null and b/public/meme3.png differ
diff --git a/public/meme4.png b/public/meme4.png
new file mode 100644
index 0000000..126803a
Binary files /dev/null and b/public/meme4.png differ
diff --git a/public/sl1.jpg b/public/sl1.jpg
new file mode 100644
index 0000000..000cb37
Binary files /dev/null and b/public/sl1.jpg differ
diff --git a/public/sl2.jpg b/public/sl2.jpg
new file mode 100644
index 0000000..30a2844
Binary files /dev/null and b/public/sl2.jpg differ
diff --git a/public/sl3.jpg b/public/sl3.jpg
new file mode 100644
index 0000000..6414d57
Binary files /dev/null and b/public/sl3.jpg differ
diff --git a/public/sl4.jpg b/public/sl4.jpg
new file mode 100644
index 0000000..42d8a18
Binary files /dev/null and b/public/sl4.jpg differ
diff --git a/public/ts1.jpg b/public/ts1.jpg
new file mode 100644
index 0000000..870788d
Binary files /dev/null and b/public/ts1.jpg differ
diff --git a/public/ts2.jpg b/public/ts2.jpg
new file mode 100644
index 0000000..472776e
Binary files /dev/null and b/public/ts2.jpg differ
diff --git a/public/ts3.jpg b/public/ts3.jpg
new file mode 100644
index 0000000..f6d80bb
Binary files /dev/null and b/public/ts3.jpg differ