Skip to content

Commit b2b9005

Browse files
authored
Merge pull request #4 from PTHARRISH/frontend-src2
Login and Register
2 parents 27a846c + 6fa14c9 commit b2b9005

File tree

20 files changed

+1304
-235
lines changed

20 files changed

+1304
-235
lines changed

frontend/package-lock.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
"dependencies": {
1313
"axios": "^1.13.2",
1414
"framer-motion": "^12.23.26",
15+
"jwt-decode": "^4.0.0",
16+
"lucide-react": "^0.562.0",
1517
"react": "^19.2.0",
1618
"react-dom": "^19.2.0",
1719
"react-icons": "^5.5.0",

frontend/src/Admin/HomeAdmin.jsx

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
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;

frontend/src/App.jsx

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Routes, Route } from "react-router-dom";
1+
// src/App.jsx - PERFECT: ANY USER=LandingPage | ANY ADMIN=HomeAdmin
2+
import { Routes, Route, Navigate } from "react-router-dom";
23
import LandingPage from "./Pages/LandingPage";
34
import Login from "./Authentication/Login";
45
import Signup from "./Authentication/Signup";
@@ -7,24 +8,97 @@ import ProductDetails from "./Pages/ProductsDetails";
78
import Cart from "./Pages/Cart";
89
import AboutUs from "./Pages/About";
910
import Contact from "./Pages/Contact";
11+
import HomeAdmin from "./Admin/HomeAdmin";
12+
import ProtectedRoute from "./ProtectedRoutes/ProtectedRote";
13+
import Settings from "./Profile/ProfileSettings";
14+
import Profile from "./Profile/Profile";
15+
import Navbar from "./reusableComponents/Navbar";
16+
import { useAuth } from "./utils/auth";
1017

11-
export default function App() {
18+
function LoadingSpinner() {
1219
return (
13-
<div className="min-h-screen bg-gray-50">
14-
<Routes>
15-
<Route path="/" element={<LandingPage />} />
16-
<Route path="/login" element={<Login />} />
17-
<Route path="/signup" element={<Signup />} />
20+
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
21+
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600" />
22+
</div>
23+
);
24+
}
1825

19-
<Route path="/products" element={<ProductsPage />} />
20-
<Route path="/product/:id" element={<ProductDetails />} />
26+
// ✅ PERFECT LOGIC: role="user" → LandingPage | role="admin" → HomeAdmin
27+
function HomePage() {
28+
const { user, loading } = useAuth();
2129

22-
<Route path="/cart" element={<Cart />} />
30+
console.log("🎯 HomePage:", {
31+
userId: user?.id,
32+
role: user?.role,
33+
isUser: user?.role === "user",
34+
isAdmin: user?.role === "admin",
35+
loading
36+
});
2337

24-
{/* NEW ROUTES */}
25-
<Route path="/about" element={<AboutUs />} />
26-
<Route path="/contact" element={<Contact />} />
27-
</Routes>
28-
</div>
38+
if (loading) return <LoadingSpinner />;
39+
40+
// ✅ GUEST → LandingPage
41+
if (!user) {
42+
console.log("✅ GUEST → LANDING PAGE");
43+
return (
44+
<>
45+
<Navbar />
46+
<LandingPage />
47+
</>
48+
);
49+
}
50+
51+
// ✅ ANY USER (role="user") → LANDING PAGE
52+
if (user.role === "user") {
53+
console.log("✅ USER (", user.id, ") → LANDING PAGE");
54+
return (
55+
<>
56+
<Navbar />
57+
<LandingPage />
58+
</>
59+
);
60+
}
61+
62+
// ✅ ANY ADMIN (role="admin") → HOMEADMIN
63+
if (user.role === "admin") {
64+
console.log("✅ ADMIN (", user.id, ") → HOMEADMIN");
65+
return (
66+
<>
67+
<Navbar />
68+
<HomeAdmin />
69+
</>
70+
);
71+
}
72+
73+
// ✅ FALLBACK → LANDING PAGE
74+
console.log("✅ FALLBACK → LANDING PAGE");
75+
return (
76+
<>
77+
<Navbar />
78+
<LandingPage />
79+
</>
80+
);
81+
}
82+
83+
export default function App() {
84+
return (
85+
<Routes>
86+
<Route path="/" element={<HomePage />} />
87+
<Route path="/login" element={<Login />} />
88+
<Route path="/signup" element={<Signup />} />
89+
<Route path="/about" element={<AboutUs />} />
90+
<Route path="/contact" element={<Contact />} />
91+
92+
<Route path="/products" element={<ProtectedRoute allowedRoles={["user"]}><ProductsPage /></ProtectedRoute>} />
93+
<Route path="/product/:id" element={<ProtectedRoute allowedRoles={["user"]}><ProductDetails /></ProtectedRoute>} />
94+
<Route path="/cart" element={<ProtectedRoute allowedRoles={["user"]}><Cart /></ProtectedRoute>} />
95+
96+
<Route path="/admin/dashboard" element={<ProtectedRoute allowedRoles={["admin"]}><HomeAdmin /></ProtectedRoute>} />
97+
98+
<Route path="/profile" element={<ProtectedRoute allowedRoles={["user"]}><Profile /></ProtectedRoute>} />
99+
<Route path="/settings" element={<ProtectedRoute allowedRoles={["user"]}><Settings /></ProtectedRoute>} />
100+
101+
<Route path="*" element={<Navigate to="/" replace />} />
102+
</Routes>
29103
);
30104
}

0 commit comments

Comments
 (0)