Skip to content

Commit 3de70a2

Browse files
committed
feat: Creating product detail page template
1 parent cf63b66 commit 3de70a2

File tree

3 files changed

+194
-3
lines changed

3 files changed

+194
-3
lines changed

frontend/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import SignUp from "./pages/Signup";
77
import SignIn from "./pages/Signin";
88
import Browse from "./pages/Browse";
99
import Sell from "./pages/Sell";
10-
// import ProductDetailsPage from "./pages/ProductDetail";
10+
import ProductDetailsPage from "./pages/ProductDetail";
1111
const queryClient = new QueryClient();
1212

1313
const App = () => (
@@ -20,7 +20,7 @@ const App = () => (
2020
<Route path="/signup" element={<SignUp />} />
2121
<Route path="/signin" element={<SignIn />} />
2222
<Route path="/browse" element={<Browse />} />
23-
{/* <Route path="/product/:id" element={<ProductDetailsPage />} /> */}
23+
<Route path="/product/:id" element={<ProductDetailsPage />} />
2424
<Route path="/sell" element={<Sell />} />
2525
</Routes>
2626
</BrowserRouter>
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import { useState } from "react";
2+
import { useParams, useNavigate } from "react-router-dom";
3+
import { Button } from "../components/ui/button";
4+
import { ArrowLeft } from "lucide-react";
5+
6+
const allProducts = [
7+
{
8+
id: 1,
9+
title: "Calculus Textbook",
10+
price: 45,
11+
description: "A comprehensive calculus guide ideal for engineering and science students. Covers differential, integral, and multivariable calculus with step-by-step examples and university-level exercises. Perfect for semester preparation and concept building.",
12+
images: ["/book1.jpg"],
13+
seller: { name: "Shubham", Used:"1.2 year", email: "[email protected]" },
14+
auction: { isAuction: false }
15+
},
16+
17+
{
18+
id: 2,
19+
title: "Laptop Stand",
20+
price: 20,
21+
description: "Ergonomic aluminum laptop stand that improves posture and cooling. Lightweight, foldable, and ideal for long study sessions in hostels or libraries. Adjustable height ensures comfort while typing or attending online classes.",
22+
images: ["/laptop1.jpg"],
23+
seller: { name: "Steve Rogers", Used:" 12 months", email: "[email protected]" },
24+
auction: { isAuction: false }
25+
},
26+
27+
{
28+
id: 3,
29+
title: "Study Notes - Physics",
30+
price: 10,
31+
description: "Handwritten physics notes neatly organized chapter-wise, covering Mechanics, Thermodynamics, Electromagnetism, and Modern Physics. Simplified concepts and formulas for quick revision and last-minute preparation.",
32+
images: ["/notes1.jpg"],
33+
seller: { name: "Bruce Banner", Used: "1 year", email: "[email protected]" },
34+
auction: { isAuction: false }
35+
},
36+
37+
{
38+
id: 4,
39+
title: "Scientific Calculator",
40+
price: 30,
41+
description: "Casio fx-991EX ClassWiz calculator with 552 functions. Ideal for engineering students — handles matrices, statistics, and complex equations with ease. Excellent condition with original case and battery included.",
42+
images: ["/calc1.jpg"],
43+
seller: { name: "Peter", Used: "6 months", email: "[email protected]" },
44+
auction: { isAuction: true, highestBid: 35, minIncrement: 5, timeLeft: "6h 15m" }
45+
},
46+
47+
{
48+
id: 5,
49+
title: "C++ Programming Book",
50+
price: 499,
51+
description: "‘Programming in C++’ by E. Balagurusamy. A complete guide to mastering Object-Oriented Programming. Covers basics to advanced topics like inheritance and polymorphism with solved examples and practice problems.",
52+
images: ["/book2.jpg"],
53+
seller: { name: "Thor", Used: "2 years", email: "[email protected]" },
54+
auction: { isAuction: true, highestBid: 550, minIncrement: 50, timeLeft: "12h 30m" }
55+
},
56+
57+
{
58+
id: 6,
59+
title: "Desk Lamp",
60+
price: 15,
61+
description: "Adjustable LED desk lamp with 3 brightness levels. Energy-efficient, flexible design suitable for night study sessions. USB rechargeable and portable — perfect for hostel or dorm desk setups.",
62+
images: ["/lamp1.jpg"],
63+
seller: { name: "Tony Stark", Used:"2 year", email: "[email protected]" },
64+
auction: { isAuction: false }
65+
},
66+
67+
{
68+
id: 7,
69+
title: "Organic Chemistry Notes",
70+
price: 25,
71+
description: "Comprehensive handwritten organic chemistry notes with reaction mechanisms, named reactions, and visual memory aids. Perfect for college exams and quick conceptual revision.",
72+
images: ["/notes2.jpg"],
73+
seller: { name: "Wanda", Used:"1 year", email: "[email protected]" },
74+
auction: { isAuction: false }
75+
},
76+
77+
{
78+
id: 8,
79+
title: "Bluetooth Headphones",
80+
price: 150,
81+
description: "High-quality wireless headphones with deep bass, noise isolation, and 20-hour battery life. Ideal for music, online classes, or movies. Lightweight design with soft ear cushions for comfort.",
82+
images: ["/headphones.jpg"],
83+
seller: { name: "Natasha", Used: "8 months", email: "[email protected]" },
84+
auction: { isAuction: true, highestBid: 160, minIncrement: 10, timeLeft: "3h 45m" }
85+
}
86+
];
87+
88+
export default function ProductDetailsPage() {
89+
const { id } = useParams();
90+
const navigate = useNavigate();
91+
const product = allProducts.find((p) => p.id === parseInt(id));
92+
93+
if (!product) return <div className="p-12 text-center">Product not found.</div>;
94+
95+
const [mainImage, setMainImage] = useState(product.images[0]);
96+
const [bid, setBid] = useState(
97+
product.auction.isAuction ? product.auction.highestBid + product.auction.minIncrement : 0
98+
);
99+
100+
const placeBid = () => {
101+
if (bid > product.auction.highestBid) {
102+
alert(`Bid of ₹${bid} placed successfully!`);
103+
} else {
104+
alert("Bid must be higher than current highest bid!");
105+
}
106+
};
107+
108+
return (
109+
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 px-4 py-10">
110+
{/* Background Blobs */}
111+
<div className="absolute inset-0 -z-10">
112+
<div className="absolute -top-32 -left-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob"></div>
113+
<div className="absolute top-0 -right-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob animation-delay-2000"></div>
114+
<div className="absolute bottom-0 left-1/4 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-2xl animate-blob animation-delay-4000"></div>
115+
</div>
116+
117+
<div className="max-w-6xl mx-auto">
118+
{/* Back Button */}
119+
<Button
120+
onClick={() => navigate(-1)}
121+
variant="outline"
122+
className="flex items-center mb-6 border-2 border-blue-700 text-blue-700 hover:bg-blue-700 hover:text-white"
123+
>
124+
<ArrowLeft className="mr-2 h-4 w-4" /> Back
125+
</Button>
126+
127+
{/* Product Content */}
128+
<div className="flex flex-col md:flex-row bg-white rounded-2xl shadow-lg overflow-hidden border border-blue-100">
129+
{/* Left- Image Section */}
130+
<div className="flex-1 p-6 flex flex-col items-center">
131+
<img
132+
src={mainImage}
133+
alt={product.title}
134+
className="rounded-xl w-full h-96 object-cover shadow-md border border-blue-100"
135+
/>
136+
<div className="flex gap-3 mt-4">
137+
{product.images.map((img, idx) => (
138+
<img
139+
key={idx}
140+
src={img}
141+
alt={`thumb-${idx}`}
142+
className={`w-20 h-20 object-cover rounded-lg cursor-pointer border-2 transition-all duration-200 ${
143+
mainImage === img ? "border-blue-600 scale-105" : "border-gray-200 hover:border-blue-400"
144+
}`}
145+
onClick={() => setMainImage(img)}
146+
/>
147+
))}
148+
</div>
149+
</div>
150+
151+
{/* Right- Details Section */}
152+
<div className="flex-1 p-8 space-y-6 border-t md:border-t-0 md:border-l border-blue-100">
153+
<h1 className="text-3xl md:text-4xl font-extrabold text-blue-800">{product.title}</h1>
154+
<p className="text-gray-700 text-lg leading-relaxed">{product.description}</p>
155+
156+
{product.auction.isAuction ? (
157+
<div className="p-4 bg-blue-50 rounded-xl border border-blue-200 space-y-3">
158+
<p className="text-lg font-semibold text-blue-800">
159+
Highest Bid: <span className="text-blue-600 font-bold">{product.auction.highestBid}</span>
160+
</p>
161+
<p className="text-gray-600">⏰ Time left: {product.auction.timeLeft}</p>
162+
<input
163+
type="number"
164+
value={bid}
165+
onChange={(e) => setBid(Number(e.target.value))}
166+
className="border-2 border-blue-200 focus:border-blue-500 rounded-lg w-full p-2 mt-1"
167+
min={product.auction.highestBid + product.auction.minIncrement}
168+
/>
169+
<Button onClick={placeBid} className="w-full bg-blue-700 hover:bg-blue-800 text-white">
170+
Place Bid
171+
</Button>
172+
</div>
173+
) : (
174+
<div className="p-4 bg-blue-50 rounded-xl border border-blue-200 text-center space-y-3">
175+
<p className="text-2xl font-bold text-blue-800">{product.price}</p>
176+
<Button className="w-full bg-blue-700 hover:bg-blue-800 text-white">Buy Now</Button>
177+
</div>
178+
)}
179+
180+
<div className="p-5 bg-gray-50 rounded-xl border border-blue-100">
181+
<h3 className="font-semibold text-lg text-blue-800 mb-2">Seller Info</h3>
182+
<p className="text-gray-700">👤 Name: {product.seller.name}</p>
183+
<p className="text-gray-700">⭐ Used: {product.seller.Used}</p>
184+
<p className="text-gray-700">📧 Email: {product.seller.email}</p>
185+
</div>
186+
</div>
187+
</div>
188+
</div>
189+
</div>
190+
);
191+
}

frontend/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ export default defineConfig({
1313
"@": path.resolve(__dirname, "./src"),
1414
},
1515
},
16-
});
16+
});

0 commit comments

Comments
 (0)