|
| 1 | +// src/Admin/HomeAdmin.jsx - 100% WORKING (react-icons/fa only) |
| 2 | +import React, { useEffect, useState } from "react"; |
| 3 | +import { motion } from "framer-motion"; |
| 4 | +import { useAuth } from "../utils/auth"; |
| 5 | +import { useNavigate } from "react-router-dom"; |
| 6 | +import { FaShoppingCart, FaUsers, FaBox, FaRupeeSign, FaChartLine, FaChartBar, FaSignOutAlt, FaUser } from "react-icons/fa"; |
| 7 | + |
| 8 | +const stats = [ |
| 9 | + { title: "Revenue", value: "₹2,45,000", change: "+12%", icon: FaRupeeSign, color: "emerald" }, |
| 10 | + { title: "Orders", value: "1,240", change: "+8%", icon: FaShoppingCart, color: "blue" }, |
| 11 | + { title: "Customers", value: "860", change: "+15%", icon: FaUsers, color: "purple" }, |
| 12 | + { title: "Products", value: "320", icon: FaBox, color: "orange" }, |
| 13 | +]; |
| 14 | + |
| 15 | +const recentOrders = [ |
| 16 | + { id: "#1021", customer: "Rahul K.", amount: "₹4,500", status: "Delivered", date: "2025-12-26" }, |
| 17 | + { id: "#1022", customer: "Sneha M.", amount: "₹2,200", status: "Pending", date: "2025-12-27" }, |
| 18 | + { id: "#1023", customer: "Amit S.", amount: "₹6,800", status: "Cancelled", date: "2025-12-27" }, |
| 19 | +]; |
| 20 | + |
| 21 | +const HomeAdmin = () => { |
| 22 | + const { user, logout } = useAuth(); |
| 23 | + const navigate = useNavigate(); |
| 24 | + const [time, setTime] = useState(new Date()); |
| 25 | + |
| 26 | + useEffect(() => { |
| 27 | + const interval = setInterval(() => setTime(new Date()), 60000); |
| 28 | + return () => clearInterval(interval); |
| 29 | + }, []); |
| 30 | + |
| 31 | + const handleLogout = () => { |
| 32 | + logout(); |
| 33 | + navigate("/"); |
| 34 | + }; |
| 35 | + |
| 36 | + return ( |
| 37 | + <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 px-4 sm:px-6 lg:px-8 py-8"> |
| 38 | + {/* Header */} |
| 39 | + <motion.div |
| 40 | + initial={{ opacity: 0, y: -20 }} |
| 41 | + animate={{ opacity: 1, y: 0 }} |
| 42 | + className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-8" |
| 43 | + > |
| 44 | + <div> |
| 45 | + <h1 className="text-3xl lg:text-4xl font-bold bg-gradient-to-r from-gray-900 via-indigo-900 to-purple-900 bg-clip-text text-transparent"> |
| 46 | + Admin Dashboard |
| 47 | + </h1> |
| 48 | + <p className="text-gray-600 mt-1"> |
| 49 | + Welcome back, <span className="font-semibold text-indigo-600">{user?.username}</span>! |
| 50 | + </p> |
| 51 | + </div> |
| 52 | + |
| 53 | + <div className="flex items-center gap-3"> |
| 54 | + <div className="flex items-center gap-2 text-sm text-gray-500 bg-white/50 px-4 py-2 rounded-xl"> |
| 55 | + <FaUser size={16} /> |
| 56 | + <span>{user?.username}</span> |
| 57 | + <span className="px-2 py-1 bg-red-100 text-red-800 text-xs font-bold rounded-full ml-2">ADMIN</span> |
| 58 | + </div> |
| 59 | + <button |
| 60 | + onClick={handleLogout} |
| 61 | + className="p-2 text-gray-500 hover:text-red-500 hover:bg-red-50 rounded-xl transition-all" |
| 62 | + title="Logout" |
| 63 | + > |
| 64 | + <FaSignOutAlt size={20} /> |
| 65 | + </button> |
| 66 | + </div> |
| 67 | + </motion.div> |
| 68 | + |
| 69 | + {/* Stats Cards */} |
| 70 | + <motion.div |
| 71 | + initial={{ opacity: 0, y: 20 }} |
| 72 | + animate={{ opacity: 1, y: 0 }} |
| 73 | + className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8" |
| 74 | + > |
| 75 | + {stats.map(({ title, value, change, icon: Icon, color }, index) => ( |
| 76 | + <motion.div |
| 77 | + key={title} |
| 78 | + initial={{ opacity: 0, y: 20 }} |
| 79 | + animate={{ opacity: 1, y: 0 }} |
| 80 | + transition={{ delay: index * 0.1 }} |
| 81 | + className="group bg-white/80 backdrop-blur-xl rounded-2xl p-6 shadow-xl hover:shadow-2xl border border-white/50 hover:-translate-y-2 transition-all duration-300 cursor-pointer" |
| 82 | + whileHover={{ scale: 1.02 }} |
| 83 | + > |
| 84 | + <div className="flex items-center justify-between"> |
| 85 | + <div> |
| 86 | + <p className="text-sm font-semibold text-gray-700 mb-2 uppercase tracking-wide">{title}</p> |
| 87 | + <p className="text-3xl font-bold text-gray-900">{value}</p> |
| 88 | + {change && ( |
| 89 | + <p className="text-sm font-bold text-emerald-600 flex items-center gap-1 mt-2"> |
| 90 | + <FaChartLine className="w-4 h-4" /> |
| 91 | + {change} from last month |
| 92 | + </p> |
| 93 | + )} |
| 94 | + </div> |
| 95 | + <div className={`p-4 rounded-2xl bg-gradient-to-br from-${color}-100 to-${color}-200 shadow-xl group-hover:scale-110 transition-all`}> |
| 96 | + <Icon size={28} className={`text-${color}-600`} /> |
| 97 | + </div> |
| 98 | + </div> |
| 99 | + </motion.div> |
| 100 | + ))} |
| 101 | + </motion.div> |
| 102 | + |
| 103 | + {/* Main Content */} |
| 104 | + <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-8"> |
| 105 | + {/* Sales Chart */} |
| 106 | + <motion.div |
| 107 | + initial={{ opacity: 0, x: -20 }} |
| 108 | + animate={{ opacity: 1, x: 0 }} |
| 109 | + className="lg:col-span-2 bg-white/80 backdrop-blur-xl rounded-3xl p-8 shadow-2xl border border-white/50" |
| 110 | + > |
| 111 | + <div className="flex items-center justify-between mb-8"> |
| 112 | + <h2 className="text-3xl font-bold text-gray-900 flex items-center gap-3"> |
| 113 | + Sales Overview |
| 114 | + <span className="px-3 py-1 bg-emerald-400 text-white text-sm font-bold rounded-full shadow-lg">Live Data</span> |
| 115 | + </h2> |
| 116 | + <FaChartBar className="w-8 h-8 text-indigo-500" /> |
| 117 | + </div> |
| 118 | + <div className="h-96 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-2xl border-2 border-dashed border-gray-200 flex items-center justify-center"> |
| 119 | + <div className="text-center text-gray-500 p-8"> |
| 120 | + <FaChartBar className="w-20 h-20 mx-auto mb-6 opacity-30" /> |
| 121 | + <p className="text-xl font-semibold mb-2">Interactive Sales Chart</p> |
| 122 | + <p className="text-lg">Real-time analytics coming soon</p> |
| 123 | + </div> |
| 124 | + </div> |
| 125 | + </motion.div> |
| 126 | + |
| 127 | + {/* Quick Stats */} |
| 128 | + <motion.div |
| 129 | + initial={{ opacity: 0, x: 20 }} |
| 130 | + animate={{ opacity: 1, x: 0 }} |
| 131 | + className="bg-white/80 backdrop-blur-xl rounded-3xl p-8 shadow-2xl border border-white/50 space-y-6" |
| 132 | + > |
| 133 | + <h2 className="text-2xl font-bold text-gray-900">Top Products</h2> |
| 134 | + <div className="space-y-4"> |
| 135 | + {[ |
| 136 | + { name: "RO Water Purifier", sales: "120", trend: "+24%" }, |
| 137 | + { name: "UV Filter Kit", sales: "95", trend: "+18%" }, |
| 138 | + { name: "Service AMC", sales: "70", trend: "+12%" }, |
| 139 | + { name: "Installation", sales: "58", trend: "+9%" }, |
| 140 | + ].map((product, index) => ( |
| 141 | + <motion.div |
| 142 | + key={product.name} |
| 143 | + className="flex items-center justify-between p-4 bg-gray-50 rounded-2xl hover:bg-gray-100 transition-all border" |
| 144 | + > |
| 145 | + <span className="font-semibold text-gray-900 truncate">{product.name}</span> |
| 146 | + <div className="text-right"> |
| 147 | + <p className="font-bold text-xl text-indigo-900">{product.sales}</p> |
| 148 | + <p className="text-sm text-emerald-600 font-semibold">{product.trend}</p> |
| 149 | + </div> |
| 150 | + </motion.div> |
| 151 | + ))} |
| 152 | + </div> |
| 153 | + </motion.div> |
| 154 | + </div> |
| 155 | + |
| 156 | + {/* Recent Orders Table */} |
| 157 | + <motion.div |
| 158 | + initial={{ opacity: 0, y: 20 }} |
| 159 | + animate={{ opacity: 1, y: 0 }} |
| 160 | + className="bg-white/80 backdrop-blur-xl rounded-3xl p-8 shadow-2xl border border-white/50" |
| 161 | + > |
| 162 | + <div className="flex items-center justify-between mb-8"> |
| 163 | + <h2 className="text-3xl font-bold text-gray-900">Recent Orders</h2> |
| 164 | + <button className="px-6 py-2 bg-gradient-to-r from-blue-500 to-indigo-600 text-white rounded-xl hover:shadow-xl transition-all font-semibold"> |
| 165 | + View All |
| 166 | + </button> |
| 167 | + </div> |
| 168 | + |
| 169 | + <div className="overflow-x-auto rounded-2xl border border-gray-200"> |
| 170 | + <table className="w-full"> |
| 171 | + <thead className="bg-gradient-to-r from-indigo-50 to-purple-50"> |
| 172 | + <tr> |
| 173 | + <th className="text-left py-5 px-6 text-sm font-bold text-gray-800 uppercase tracking-wider">Order</th> |
| 174 | + <th className="text-left py-5 px-6 text-sm font-bold text-gray-800 uppercase tracking-wider">Customer</th> |
| 175 | + <th className="text-left py-5 px-6 text-sm font-bold text-gray-800 uppercase tracking-wider">Amount</th> |
| 176 | + <th className="text-left py-5 px-6 text-sm font-bold text-gray-800 uppercase tracking-wider">Status</th> |
| 177 | + <th className="text-left py-5 px-6 text-sm font-bold text-gray-800 uppercase tracking-wider">Date</th> |
| 178 | + </tr> |
| 179 | + </thead> |
| 180 | + <tbody className="divide-y divide-gray-100"> |
| 181 | + {recentOrders.map((order) => ( |
| 182 | + <tr key={order.id} className="hover:bg-gradient-to-r hover:from-blue-50 hover:to-indigo-50 transition-all duration-200"> |
| 183 | + <td className="py-5 px-6 font-mono text-sm font-semibold text-indigo-900">{order.id}</td> |
| 184 | + <td className="py-5 px-6"> |
| 185 | + <span className="font-semibold text-gray-900">{order.customer}</span> |
| 186 | + </td> |
| 187 | + <td className="py-5 px-6 font-mono font-bold text-xl text-emerald-700">{order.amount}</td> |
| 188 | + <td className="py-5 px-6"> |
| 189 | + <span className={`px-4 py-2 rounded-full text-xs font-bold shadow-sm ${ |
| 190 | + order.status === "Delivered" |
| 191 | + ? "bg-emerald-100 text-emerald-800" |
| 192 | + : order.status === "Pending" |
| 193 | + ? "bg-amber-100 text-amber-800" |
| 194 | + : "bg-red-100 text-red-800" |
| 195 | + }`}> |
| 196 | + {order.status} |
| 197 | + </span> |
| 198 | + </td> |
| 199 | + <td className="py-5 px-6 text-sm font-medium text-gray-700">{order.date}</td> |
| 200 | + </tr> |
| 201 | + ))} |
| 202 | + </tbody> |
| 203 | + </table> |
| 204 | + </div> |
| 205 | + </motion.div> |
| 206 | + </div> |
| 207 | + ); |
| 208 | +}; |
| 209 | + |
| 210 | +export default HomeAdmin; |
0 commit comments