Create an Admin Dashboard for Magazine Websites
import React, { useState, useEffect } from "react"; import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, BarElement } from "chart.js"; import { Line, Bar } from "react-chartjs-2"; import { FiHome, FiUsers, FiFileText, FiPieChart, FiMenu, FiX, FiEdit2, FiTrash2, FiSearch } from "react-icons/fi"; ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, BarElement, Title, Tooltip, Legend); const AdminDashboard = () => { const [activeSection, setActiveSection] = useState("dashboard"); const [sidebarOpen, setSidebarOpen] = useState(true); const [users, setUsers] = useState([]); const [articles, setArticles] = useState([]); const [searchTerm, setSearchTerm] = useState(""); useEffect(() => { // Mock data setUsers([ { id: 1, name: "John Doe", email: "john@example.com", role: "Editor" }, { id: 2, name: "Jane Smith", email: "jane@example.com", role: "Writer" }, { id: 3, name: "Mike Johnson", email: "mike@example.com", role: "Admin" }, ]); setArticles([ { id: 1, title: "Getting Started with React", author: "John Doe", status: "Published", views: 1200 }, { id: 2, title: "Mastering Tailwind CSS", author: "Jane Smith", status: "Draft", views: 800 }, { id: 3, title: "Advanced JavaScript Concepts", author: "Mike Johnson", status: "Published", views: 1500 }, ]); }, []); const chartData = { labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], datasets: [ { label: "Article Views", data: [1200, 1900, 1500, 2100, 1800, 2300], borderColor: "rgb(75, 192, 192)", tension: 0.1, }, ], }; const barData = { labels: ["Users", "Articles", "Comments"], datasets: [ { label: "Statistics", data: [300, 150, 800], backgroundColor: ["#4F46E5", "#10B981", "#F59E0B"], }, ], }; const renderContent = () => { switch (activeSection) { case "dashboard": return ( <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8"> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-2">Total Users</h3> <p className="text-3xl font-bold text-indigo-600">{users.length}</p> </div> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-2">Total Articles</h3> <p className="text-3xl font-bold text-emerald-600">{articles.length}</p> </div> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-2">Total Views</h3> <p className="text-3xl font-bold text-amber-600">4,500</p> </div> <div className="col-span-full lg:col-span-2"> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-4">Views Over Time</h3> <Line data={chartData} /> </div> </div> <div className="col-span-full lg:col-span-1"> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-4">Statistics</h3> <Bar data={barData} /> </div> </div> </div> ); case "users": return ( <div className="bg-white p-6 rounded-lg shadow-md"> <div className="flex justify-between items-center mb-6"> <h2 className="text-xl font-semibold">User Management</h2> <div className="relative"> <FiSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" /> <input type="text" placeholder="Search users..." className="pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" onChange={(e) => setSearchTerm(e.target.value)} /> </div> </div> <div className="overflow-x-auto"> <table className="min-w-full divide-y divide-gray-200"> <thead> <tr> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Role</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> </tr> </thead> <tbody className="divide-y divide-gray-200"> {users.filter(user => user.name.toLowerCase().includes(searchTerm.toLowerCase()) || user.email.toLowerCase().includes(searchTerm.toLowerCase()) ).map((user) => ( <tr key={user.id}> <td className="px-6 py-4 whitespace-nowrap">{user.name}</td> <td className="px-6 py-4 whitespace-nowrap">{user.email}</td> <td className="px-6 py-4 whitespace-nowrap">{user.role}</td> <td className="px-6 py-4 whitespace-nowrap"> <button className="text-indigo-600 hover:text-indigo-900 mr-3"> <FiEdit2 className="w-5 h-5" /> </button> <button className="text-red-600 hover:text-red-900"> <FiTrash2 className="w-5 h-5" /> </button> </td> </tr> ))} </tbody> </table> </div> </div> ); case "articles": return ( <div className="bg-white p-6 rounded-lg shadow-md"> <div className="flex justify-between items-center mb-6"> <h2 className="text-xl font-semibold">Article Management</h2> <button className="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700">Add New Article</button> </div> <div className="overflow-x-auto"> <table className="min-w-full divide-y divide-gray-200"> <thead> <tr> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Title</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Author</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Views</th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> </tr> </thead> <tbody className="divide-y divide-gray-200"> {articles.map((article) => ( <tr key={article.id}> <td className="px-6 py-4 whitespace-nowrap">{article.title}</td> <td className="px-6 py-4 whitespace-nowrap">{article.author}</td> <td className="px-6 py-4 whitespace-nowrap"> <span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${article.status === "Published" ? "bg-green-100 text-green-800" : "bg-yellow-100 text-yellow-800"}`}> {article.status} </span> </td> <td className="px-6 py-4 whitespace-nowrap">{article.views}</td> <td className="px-6 py-4 whitespace-nowrap"> <button className="text-indigo-600 hover:text-indigo-900 mr-3"> <FiEdit2 className="w-5 h-5" /> </button> <button className="text-red-600 hover:text-red-900"> <FiTrash2 className="w-5 h-5" /> </button> </td> </tr> ))} </tbody> </table> </div> </div> ); case "analytics": return ( <div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-4">Article Performance</h3> <Line data={chartData} /> </div> <div className="bg-white p-6 rounded-lg shadow-md"> <h3 className="text-lg font-semibold mb-4">Content Distribution</h3> <Bar data={barData} /> </div> </div> ); default: return null; } }; return ( <div className="min-h-screen bg-gray-100"> <div className="flex"> {/* Sidebar */} <div className={`${sidebarOpen ? "w-64" : "w-20"} bg-indigo-800 min-h-screen transition-all duration-300`}> <div className="p-4 flex justify-between items-center"> <h1 className={`text-white font-bold ${sidebarOpen ? "block" : "hidden"}`}>Admin Dashboard</h1> <button onClick={() => setSidebarOpen(!sidebarOpen)} className="text-white"> {sidebarOpen ? <FiX className="w-6 h-6" /> : <FiMenu className="w-6 h-6" />} </button> </div> <nav className="mt-8"> <button onClick={() => setActiveSection("dashboard")} className={`flex items-center w-full p-4 text-white hover:bg-indigo-700 ${activeSection === "dashboard" ? "bg-indigo-700" : ""}`} > <FiHome className="w-6 h-6" /> {sidebarOpen && <span className="ml-4">Dashboard</span>} </button> <button onClick={() => setActiveSection("users")} className={`flex items-center w-full p-4 text-white hover:bg-indigo-700 ${activeSection === "users" ? "bg-indigo-700" : ""}`} > <FiUsers className="w-6 h-6" /> {sidebarOpen && <span className="ml-4">Users</span>} </button> <button onClick={() => setActiveSection("articles")} className={`flex items-center w-full p-4 text-white hover:bg-indigo-700 ${activeSection === "articles" ? "bg-indigo-700" : ""}`} > <FiFileText className="w-6 h-6" /> {sidebarOpen && <span className="ml-4">Articles</span>} </button> <button onClick={() => setActiveSection("analytics")} className={`flex items-center w-full p-4 text-white hover:bg-indigo-700 ${activeSection === "analytics" ? "bg-indigo-700" : ""}`} > <FiPieChart className="w-6 h-6" /> {sidebarOpen && <span className="ml-4">Analytics</span>} </button> </nav> </div> {/* Main Content */} <div className="flex-1 p-8"> <div className="mb-8"> <h2 className="text-2xl font-bold text-gray-800"> {activeSection.charAt(0).toUpperCase() + activeSection.slice(1)} </h2> </div> {renderContent()} </div> </div> </div> ); }; export default AdminDashboard; Can u split this code to many component to easy reuse and easy to maintain ?