ok
This commit is contained in:
@@ -8,10 +8,8 @@ const Dashboard = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
const menuRef = useRef(null);
|
const menuRef = useRef(null);
|
||||||
|
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [selectedRole, setSelectedRole] = useState("officer");
|
|
||||||
const [successMessage, setSuccessMessage] = useState("");
|
const [successMessage, setSuccessMessage] = useState("");
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
const [errorMessage, setErrorMessage] = useState("");
|
||||||
const [user, setUser] = useState({});
|
const [user, setUser] = useState({});
|
||||||
@@ -67,7 +65,6 @@ const Dashboard = () => {
|
|||||||
if (data[0].payload.officerPerformance) {
|
if (data[0].payload.officerPerformance) {
|
||||||
setOfficerPerformanceData(data[0].payload.officerPerformance);
|
setOfficerPerformanceData(data[0].payload.officerPerformance);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Token tidak valid:", error.message);
|
console.error("Token tidak valid:", error.message);
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem("token");
|
||||||
@@ -102,7 +99,6 @@ const Dashboard = () => {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
role: selectedRole,
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -116,7 +112,6 @@ const Dashboard = () => {
|
|||||||
setSuccessMessage("Officer berhasil ditambahkan");
|
setSuccessMessage("Officer berhasil ditambahkan");
|
||||||
setUsername("");
|
setUsername("");
|
||||||
setPassword("");
|
setPassword("");
|
||||||
setSelectedRole("officer");
|
|
||||||
setErrorMessage("");
|
setErrorMessage("");
|
||||||
// Pertimbangkan untuk memuat ulang data performa jika penambahan officer baru mempengaruhi grafik
|
// Pertimbangkan untuk memuat ulang data performa jika penambahan officer baru mempengaruhi grafik
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -144,7 +139,9 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.dropdownContainer} ref={menuRef}>
|
<div className={styles.dropdownContainer} ref={menuRef}>
|
||||||
<span className={styles.userDisplayName}>{user.username || "Guest"}</span>
|
<span className={styles.userDisplayName}>
|
||||||
|
{user.username || "Guest"}
|
||||||
|
</span>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||||
className={styles.dropdownToggle}
|
className={styles.dropdownToggle}
|
||||||
@@ -156,13 +153,19 @@ const Dashboard = () => {
|
|||||||
{isMenuOpen && (
|
{isMenuOpen && (
|
||||||
<div className={styles.dropdownMenu}>
|
<div className={styles.dropdownMenu}>
|
||||||
<button
|
<button
|
||||||
onClick={() => { navigate("/profile"); setIsMenuOpen(false); }} /* Tutup menu setelah klik */
|
onClick={() => {
|
||||||
|
navigate("/profile");
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
}} /* Tutup menu setelah klik */
|
||||||
className={styles.dropdownItem}
|
className={styles.dropdownItem}
|
||||||
>
|
>
|
||||||
Profile
|
Profile
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => { handleLogout(); setIsMenuOpen(false); }} /* Tutup menu setelah klik */
|
onClick={() => {
|
||||||
|
handleLogout();
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
}} /* Tutup menu setelah klik */
|
||||||
className={styles.dropdownItem}
|
className={styles.dropdownItem}
|
||||||
>
|
>
|
||||||
Logout
|
Logout
|
||||||
@@ -191,7 +194,7 @@ const Dashboard = () => {
|
|||||||
|
|
||||||
{/* Grid for Form (Admin) and Chart (Admin & Officer) */}
|
{/* Grid for Form (Admin) and Chart (Admin & Officer) */}
|
||||||
<div className={styles.dashboardGrid}>
|
<div className={styles.dashboardGrid}>
|
||||||
{user.role === "admin" && ( /* Render form hanya jika admin */
|
{user.role === "admin" /* Render form hanya jika admin */ && (
|
||||||
<div className={styles.formSection}>
|
<div className={styles.formSection}>
|
||||||
<h2>Tambah Officer Baru</h2>
|
<h2>Tambah Officer Baru</h2>
|
||||||
<form onSubmit={handleAddOfficer} className={styles.form}>
|
<form onSubmit={handleAddOfficer} className={styles.form}>
|
||||||
@@ -213,23 +216,14 @@ const Dashboard = () => {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
|
||||||
Role:
|
|
||||||
<select
|
|
||||||
value={selectedRole}
|
|
||||||
onChange={(e) => setSelectedRole(e.target.value)}
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<option value="officer">Officer</option>
|
|
||||||
<option value="admin">Admin</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
<button type="submit" className={styles.submitButton}>
|
<button type="submit" className={styles.submitButton}>
|
||||||
Add
|
Add
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{successMessage && <p className={styles.success}>{successMessage}</p>}
|
{successMessage && (
|
||||||
|
<p className={styles.success}>{successMessage}</p>
|
||||||
|
)}
|
||||||
{errorMessage && <p className={styles.error}>{errorMessage}</p>}
|
{errorMessage && <p className={styles.error}>{errorMessage}</p>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -253,11 +247,13 @@ const Dashboard = () => {
|
|||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
*/
|
*/
|
||||||
<div className={styles.chartPlaceholder}>
|
<div className={styles.chartPlaceholder}>
|
||||||
Grafik performa petugas akan ditampilkan di sini.
|
Grafik performa petugas akan ditampilkan di sini. (Integrasikan
|
||||||
(Integrasikan library grafik seperti Recharts/Chart.js)
|
library grafik seperti Recharts/Chart.js)
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className={styles.warning}>Tidak ada data performa petugas untuk ditampilkan.</p>
|
<p className={styles.warning}>
|
||||||
|
Tidak ada data performa petugas untuk ditampilkan.
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const Login = () => {
|
|||||||
<div className={styles.loginContainer}>
|
<div className={styles.loginContainer}>
|
||||||
<div className={styles.loginBox}>
|
<div className={styles.loginBox}>
|
||||||
<img src="/dermalounge.jpg" alt="Logo" className={styles.logo} />
|
<img src="/dermalounge.jpg" alt="Logo" className={styles.logo} />
|
||||||
<h1 className={styles.h1}>Dermalounge AI Admin Login</h1>
|
<h1 className={styles.h1}>PSI Admin Login</h1>
|
||||||
<p className={styles.subtitle}>
|
<p className={styles.subtitle}>
|
||||||
Silakan masuk untuk melanjutkan ke dashboard
|
Silakan masuk untuk melanjutkan ke dashboard
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,73 +1,85 @@
|
|||||||
.loginContainer {
|
.loginContainer {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background-color: #f0f5ff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: #f0f2f5;
|
margin: 0;
|
||||||
width: 100vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.loginBox {
|
.loginBox {
|
||||||
background: #fff;
|
background-color: #ffffff;
|
||||||
|
border-radius: 16px;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
border-radius: 10px;
|
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.05);
|
||||||
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.1);
|
width: 300px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
|
height: auto;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h1 {
|
.h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-size: 24px;
|
color: #d22129; /* 🔴 Warna merah PSI */
|
||||||
color: #333;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #777;
|
color: #6b7280;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
padding: 10px 15px;
|
width: 100%;
|
||||||
margin-bottom: 15px;
|
padding: 12px 15px;
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
color: #1f2937;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border: 1px solid #d1d5db;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
background-color: #337f83;
|
background-color: #d22129; /* 🔴 Warna merah PSI */
|
||||||
color: white;
|
color: #ffffff;
|
||||||
border: none;
|
padding: 12px 24px;
|
||||||
padding: 12px;
|
border-radius: 24px;
|
||||||
border-radius: 6px;
|
font-size: 18px;
|
||||||
font-size: 16px;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
transition: background-color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover {
|
.button:hover {
|
||||||
background-color: #3c9a9f;
|
background-color: #b71c1c; /* versi lebih gelap saat hover */
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
color: red;
|
||||||
margin-bottom: 10px;
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
margin-top: -10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
margin-top: 20px;
|
margin-top: 30px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #aaa;
|
color: #9ca3af;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user