HT
HiαΊΏu Trung

Admin Dashboard - Copy this React, Tailwind Component to your project

.admin page { display: flex; height: 100vh; font family: 'Segoe UI', Tahoma, Geneva, Verdana, sans serif; background color: #f5f7fa; } .sidebar { width: 260px; background color: #1e293b; color: white; display: flex; flex direction: column; padding: 20px; } .sidebar header { font size: 1.8rem; font weight: bold; margin bottom: 30px; text align: center; } .sidebar nav { display: flex; flex direction: column; gap: 16px; list style: none; padding left: 0; } .sidebar nav li { color: #cbd5e1; text decoration: none; padding: 10px 15px; border radius: 8px; cursor: pointer; transition: background color 0.2s; display: flex; align items: center; gap: 10px; } .sidebar nav li:hover, .sidebar nav li.active { background color: #334155; color: #ffffff; } .admin main { flex: 1; padding: 30px; overflow y: auto; background color: #f5f7fa; } .dashboard { background color: white; padding: 24px; border radius: 12px; box shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .dashboard h3 { margin bottom: 16px; } .dashboard grid { display: grid; grid template columns: repeat(auto fit, minmax(200px, 1fr)); gap: 20px; margin top: 20px; } .stat box { background color: #e2e8f0; padding: 20px; border radius: 10px; font weight: bold; text align: center; color: #1e293b; } .user management { background color: white; padding: 24px; border radius: 12px; box shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .user management h3 { margin bottom: 16px; } .user table { width: 100%; border collapse: collapse; margin top: 20px; } .user table th, .user table td { border: 1px solid #e2e8f0; padding: 12px; text align: left; } .user table th { background color: #f1f5f9; } .user table tr:nth child(even) { background color: #f8fafc; } button { margin: 0 4px; padding: 8px 14px; border: none; border radius: 6px; color: white; cursor: pointer; font size: 14px; transition: background color 0.2s; } .edit btn { background color: #007bff; } .edit btn:hover { background color: #0056b3; } .delete btn { background color: #dc3545; } .delete btn:hover { background color: #b02a37; } .save btn { background color: #28a745; } .save btn:hover { background color: #218838; } .clear btn { background color: #ef4444; } .clear btn:hover { background color: #dc2626; } .add staff button { background color: #0ea5e9; padding: 10px 16px; border radius: 8px; } .add staff button:hover { background color: #0284c7; } .edit form { margin top: 20px; display: flex; flex direction: column; gap: 12px; max width: 500px; } .edit form input, .edit form select { padding: 10px; border: 1px solid #d1d5db; border radius: 8px; font size: 14px; width: 100%; } .horizontal fields { display: flex; gap: 12px; width: 100%; } .horizontal fields input { flex: 1; padding: 10px; border: 1px solid #9db8e0; border radius: 8px; font size: 14px; } .dashboard { background color: white; padding: 30px; border radius: 16px; box shadow: 0 4px 16px rgba(0, 0, 0, 0.05); max width: 100%; } .dashboard h3 { margin bottom: 20px; font size: 24px; font weight: bold; color: #2e3a59; } .dashboard container { display: flex; flex direction: column; gap: 30px; } .dashboard card { background color: #fff; padding: 20px; border radius: 12px; box shadow: 0 4px 12px rgba(0, 0, 0, 0.1); margin bottom: 20px; } .stat cards { display: flex; flex wrap: wrap; gap: 20px; justify content: space between; } .stat card { flex: 1 1 calc(25% 20px); background color: #f9fafb; border radius: 12px; padding: 20px; text align: center; box shadow: 0 2px 8px rgba(0, 0, 0, 0.08); transition: transform 0.2s ease; } .stat card:hover { transform: translateY( 4px); } .stat card h4 { font size: 16px; margin bottom: 10px; color: #374151; } .stat card p { font size: 24px; font weight: bold; color: #2563eb; } .dashboard { padding: 20px; } .dashboard title { font size: 24px; font weight: 700; margin bottom: 25px; color: #1e3a8a; } .dashboard cards { display: grid; grid template columns: repeat(auto fit, minmax(220px, 1fr)); gap: 20px; margin bottom: 30px; } .dashboard card { background: #f9fafb; padding: 25px; border radius: 16px; box shadow: 0 4px 12px rgba(0, 0, 0, 0.06); transition: all 0.3s ease; text align: center; } .dashboard card:hover { transform: translateY( 4px); box shadow: 0 6px 18px rgba(0, 0, 0, 0.1); } .dashboard card h4 { font size: 16px; color: #374151; margin bottom: 12px; } .card number { font size: 28px; font weight: 700; color: #2563eb; } .dashboard chart { background: #fff; padding: 24px; border radius: 16px; box shadow: 0 4px 12px rgba(0, 0, 0, 0.06); } import React, { useEffect, useState } from "react"; import axios from "../../helpers/axiosInstance"; import logout from "../../helpers/authLogout"; import "./AdminPage.css"; import { FaSignOutAlt, FaTachometerAlt, FaUserCog, } from "react icons/fa"; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, } from "recharts"; const menuItems = [ { key: "dashboard", label: "Dashboard", icon: <FaTachometerAlt /> }, { key: "staff", label: "Staff Manager", icon: <FaUserCog /> }, { key: "logout", label: "Logout", icon: <FaSignOutAlt /> }, ]; export default function AdminPage() { const [selected, setSelected] = useState("dashboard"); const [dashboardData, setDashboardData] = useState(null); const [users, setUsers] = useState([]); const [newUser, setNewUser] = useState({}); const [error, setError] = useState(""); const token = sessionStorage.getItem("accessToken"); useEffect(() => { if (selected === "dashboard") { axios .get("http://localhost:8080/api/v1/admin/dashboard", { headers: { Authorization: `Bearer ${token}` }, }) .then((res) => setDashboardData(res.data)) .catch(() => setDashboardData(null)); } else if (selected === "staff") { fetchStaff(); } else if (selected === "logout") { logout(); } }, [selected]); const fetchStaff = async () => { try { const res = await axios.get("http://localhost:8080/api/v1/admin/staff", { headers: { Authorization: `Bearer ${token}` }, }); setUsers(res.data); } catch (err) { const message = err.response?.data?.message || "Failed to load list."; setError(message); } }; const handleDelete = async (id) => { if (!window.confirm("Are you sure you want to delete this user?")) return; try { await axios.delete(`http://localhost:8080/api/v1/admin/staff/${id}`, { headers: { Authorization: `Bearer ${token}` }, }); setUsers((prev) => prev.filter((user) => user.id !== id)); } catch { alert("Delete failed"); } }; const handleCreate = async (e) => { e.preventDefault(); try { await axios.post("http://localhost:8080/api/v1/admin/staff", newUser, { headers: { Authorization: `Bearer ${token}` }, }); alert("Staff created successfully"); setNewUser({}); fetchStaff(); } catch (err) { alert("Failed to create staff"); } }; const chartData = [ { name: "Jan", value: 20 }, { name: "Feb", value: 25 }, { name: "Mar", value: 30 }, { name: "Apr", value: 28 }, { name: "May", value: 22 }, { name: "Jun", value: 18 }, ]; const renderContent = () => { if (selected === "dashboard") { return ( <div className="dashboard"> <h2 className="dashboard title">πŸ“Š Dashboard </h2> {!dashboardData ? ( <p>Loading data...</p> ) : ( <> <div className="dashboard cards"> <div className="dashboard card"> <h4>Total Donors</h4> <p className="card number">πŸ§‘β€πŸ€β€πŸ§‘ {dashboardData.totalDonors}</p> </div> <div className="dashboard card"> <h4>Total Staff</h4> <p className="card number">πŸ‘©β€βš•οΈ {dashboardData.totalStaff}</p> </div> <div className="dashboard card"> <h4>Total Donations</h4> <p className="card number">πŸ’‰ {dashboardData.totalDonations}</p> </div> <div className="dashboard card"> <h4>Amount of Blood</h4> <p className="card number">🩸 {Number(dashboardData.totalBloodVolume).toFixed(2)} L</p> </div> </div> <div className="dashboard chart"> <h4>Statsistics by mont</h4> <ResponsiveContainer width="100%" height={300}> <LineChart data={chartData}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="name" /> <YAxis /> <Tooltip /> <Line type="monotone" dataKey="value" stroke="#2563eb" strokeWidth={3} /> </LineChart> </ResponsiveContainer> </div> </> )} </div> ); } if (selected === "staff") { return ( <div className="user management"> <h3>Staff Management</h3> {error ? ( <p>{error}</p> ) : ( <div className="staff content grid"> <div className="staff table section"> <table className="user table"> <thead> <tr> <th>Full Name</th> <th>Email</th> <th>Phone</th> <th>Address</th> <th>Gender</th> <th>Actions</th> </tr> </thead> <tbody> {users.map((user) => ( <tr key={user.id}> <td>{user.fullName}</td> <td>{user.email}</td> <td>{user.phoneNumber}</td> <td>{user.address}</td> <td>{user.sex}</td> <td> <button className="delete btn" onClick={() => handleDelete(user.id)}>Delete</button> </td> </tr> ))} </tbody> </table> </div> <div className="staff form section"> <h4>Add New Staff</h4> <form onSubmit={handleCreate} className="edit form"> <input required value={newUser.fullName || ""} onChange={(e) => setNewUser({ ...newUser, fullName: e.target.value })} placeholder="Full Name" /> <div className="horizontal fields"> <input required value={newUser.email || ""} onChange={(e) => setNewUser({ ...newUser, email: e.target.value })} placeholder="Email" /> <input required type="password" value={newUser.password || ""} onChange={(e) => setNewUser({ ...newUser, password: e.target.value })} placeholder="Password" /> </div> <input required value={newUser.phoneNumber || ""} onChange={(e) => setNewUser({ ...newUser, phoneNumber: e.target.value })} placeholder="Phone Number" /> <input required value={newUser.address || ""} onChange={(e) => setNewUser({ ...newUser, address: e.target.value })} placeholder="Address" /> <select required value={newUser.bloodType || ""} onChange={(e) => setNewUser({ ...newUser, bloodType: e.target.value })} > <option value="">Select Blood Type</option> <option value="A_POSITIVE">A+</option> <option value="A_NEGATIVE">A </option> <option value="B_POSITIVE">B+</option> <option value="B_NEGATIVE">B </option> <option value="O_POSITIVE">O+</option> <option value="O_NEGATIVE">O </option> <option value="AB_POSITIVE">AB+</option> <option value="AB_NEGATIVE">AB </option> </select> <input required type="date" value={newUser.birthday || ""} onChange={(e) => setNewUser({ ...newUser, birthday: e.target.value })} placeholder="yyyy MM dd" /> <select required value={newUser.sex || ""} onChange={(e) => setNewUser({ ...newUser, sex: e.target.value })} > <option value="">Select Gender</option> <option value="MALE">Male</option> <option value="FEMALE">Female</option> </select> <input required value={newUser.occupation || ""} onChange={(e) => setNewUser({ ...newUser, occupation: e.target.value })} placeholder="Occupation" /> <button type="submit" className="save btn">Add</button> <button type="button" className="delete btn" onClick={() => setNewUser({})}>Clear</button> </form> </div> </div> )} </div> ); } return null; }; return ( <div className="admin page"> <aside className="sidebar"> <div className="sidebar header"> <h2>Admin Page</h2> </div> <ul className="sidebar nav"> {menuItems.map((item) => ( <li key={item.key} className={selected === item.key ? "active" : ""} onClick={() => setSelected(item.key)} style={{ display: "flex", alignItems: "center", gap: 10, cursor: "pointer" }} > <span>{item.icon}</span> {item.label} </li> ))} </ul> </aside> <main className="admin main">{renderContent()}</main> </div> ); } fix UI cho tui

Prompt
Component Preview

About

AdminDashboard - A responsive admin panel with a sidebar, user management, and interactive charts, professionally built with React and Tailwind. Download instantly!

Share

Last updated 1 month ago