diff --git a/src/App.js b/src/App.js
index b04db33..fa71345 100644
--- a/src/App.js
+++ b/src/App.js
@@ -13,26 +13,6 @@ const ProtectedRoute = ({ element }) => {
return token ? element : ;
};
-// Komponen redirect berdasarkan sessionStorage
-const HomeRedirect = () => {
- const token = localStorage.getItem("token");
- const hasOpen = sessionStorage.getItem("hasOpen");
-
- if (!token) {
- return ;
- }
-
- // Jika tidak ada sessionId (anggap sebagai session baru)
- if (!hasOpen) {
- sessionStorage.setItem("hasOpen", true);
-
- return ;
- }
-
- // Jika sudah ada sessionId
- return ;
-};
-
function App() {
return (
@@ -43,11 +23,11 @@ function App() {
path="/dashboard"
element={
} />}
/>
+
} />} />
} />}
/>
-
} />
} />
diff --git a/src/Dashboard.js b/src/Dashboard.js
index 9172433..6f3845c 100644
--- a/src/Dashboard.js
+++ b/src/Dashboard.js
@@ -70,27 +70,28 @@ const Dashboard = () => {
verifyTokenAndFetchData();
}, []);
+ // Memisahkan fungsi fetchOfficers agar dapat dipanggil ulang
+ const fetchOfficers = async () => {
+ const token = localStorage.getItem("token");
+ try {
+ const response = await fetch(
+ "https://bot.kediritechnopark.com/webhook/list-user/psi",
+ {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }
+ );
+
+ const data = await response.json();
+ setOfficers(data);
+ } catch (error) {
+ console.error("Gagal memuat daftar officer:", error.message);
+ }
+ };
+
useEffect(() => {
- const fetchOfficers = async () => {
- const token = localStorage.getItem("token");
- try {
- const response = await fetch(
- "https://bot.kediritechnopark.com/webhook/list-user/psi",
- {
- method: "GET",
- headers: {
- Authorization: `Bearer ${token}`,
- },
- }
- );
-
- const data = await response.json();
- setOfficers(data);
- } catch (error) {
- console.error("Gagal memuat daftar officer:", error.message);
- }
- };
-
if (user.role == "admin") {
fetchOfficers();
}
@@ -133,6 +134,9 @@ const Dashboard = () => {
setUsername("");
setPassword("");
setErrorMessage("");
+
+ // Refresh daftar officer setelah berhasil menambahkan
+ await fetchOfficers();
} catch (error) {
setErrorMessage(error.message || "Gagal menambahkan officer");
setSuccessMessage("");
@@ -148,6 +152,7 @@ const Dashboard = () => {
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
+
const handleDeleteOfficer = async (id) => {
const confirmDelete = window.confirm(
"Apakah Anda yakin ingin menghapus petugas ini?"
@@ -268,21 +273,39 @@ const Dashboard = () => {
{user.role === "admin" && (
Daftar Petugas
-
- {officers.map((officer) => (
- -
- 👤 {officer.username} —{" "}
- {officer.role}
-
-
- ))}
-
+
+
+ {officers.length > 0 ? (
+ officers.map((officer) => (
+
+
+
👤
+
+
+ {officer.username}
+
+
+ {officer.role}
+
+
+
+
+
+ ))
+ ) : (
+
+
📋
+
Belum ada petugas terdaftar
+
+ )}
+
+
Tambah Petugas Baru
diff --git a/src/Dashboard.module.css b/src/Dashboard.module.css
index 7db97ca..728a5fd 100644
--- a/src/Dashboard.module.css
+++ b/src/Dashboard.module.css
@@ -442,3 +442,159 @@ body {
grid-column: 1 / -1;
}
}
+
+/* CSS untuk styling daftar petugas */
+
+.officerListContainer {
+ background: #f8f9fa;
+ border: 1px solid #dee2e6;
+ border-radius: 8px;
+ padding: 16px;
+ margin-bottom: 20px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.officerList {
+ max-height: 300px;
+ overflow-y: auto;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ border-radius: 6px;
+ background: white;
+ border: 1px solid #e9ecef;
+}
+
+.officerItem {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ border-bottom: 1px solid #e9ecef;
+ transition: background-color 0.2s ease;
+}
+
+.officerItem:last-child {
+ border-bottom: none;
+}
+
+.officerItem:hover {
+ background-color: #f8f9fa;
+}
+
+.officerInfo {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ flex: 1;
+}
+
+.officerIcon {
+ font-size: 20px;
+ width: 24px;
+ height: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.officerDetails {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.officerName {
+ font-weight: 600;
+ color: #2c3e50;
+ font-size: 14px;
+}
+
+.officerRole {
+ font-size: 12px;
+ color: #6c757d;
+ font-style: italic;
+ text-transform: capitalize;
+}
+
+.deleteButton {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 12px;
+ padding: 4px 8px;
+ border-radius: 4px;
+ transition: background-color 0.2s ease;
+ opacity: 0.7;
+}
+
+.deleteButton:hover {
+ background-color: #fee;
+ opacity: 1;
+}
+
+.deleteButton:focus {
+ outline: 2px solid #dc3545;
+ outline-offset: 2px;
+}
+
+.emptyState {
+ text-align: center;
+ padding: 40px 20px;
+ color: #6c757d;
+}
+
+.emptyState span {
+ font-size: 32px;
+ display: block;
+ margin-bottom: 8px;
+}
+
+.emptyState p {
+ margin: 0;
+ font-size: 14px;
+}
+
+.separator {
+ border: none;
+ border-top: 1px solid #dee2e6;
+ margin: 24px 0;
+}
+
+/* Custom scrollbar untuk daftar petugas */
+.officerList::-webkit-scrollbar {
+ width: 8px;
+}
+
+.officerList::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 4px;
+}
+
+.officerList::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 4px;
+}
+
+.officerList::-webkit-scrollbar-thumb:hover {
+ background: #a8a8a8;
+}
+
+/* Responsive design */
+@media (max-width: 768px) {
+ .officerItem {
+ padding: 10px 12px;
+ }
+
+ .officerInfo {
+ gap: 8px;
+ }
+
+ .officerName {
+ font-size: 13px;
+ }
+
+ .officerRole {
+ font-size: 11px;
+ }
+}
diff --git a/src/KTPScanner.js b/src/KTPScanner.js
index e17a3d8..defdc53 100644
--- a/src/KTPScanner.js
+++ b/src/KTPScanner.js
@@ -1,4 +1,6 @@
import React, { useEffect, useRef, useState } from "react";
+import styless from "./Dashboard.module.css";
+
import { useNavigate } from "react-router-dom";
import Modal from "./Modal";
@@ -7,6 +9,8 @@ import PaginatedFormEditable from "./PaginatedFormEditable";
const STORAGE_KEY = "camera_canvas_gallery";
const CameraCanvas = () => {
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const menuRef = useRef(null);
const navigate = useNavigate();
const videoRef = useRef(null);
@@ -489,30 +493,57 @@ const CameraCanvas = () => {
return (
-
-
-
Scan KTP atau unggah
+
+
+

+
Kawal PSI Dashboard
+
+
+
+
+ {isMenuOpen && (
+
+
+
+
+ )}
+