Kumar commited on
Commit ·
4d36e2e
1
Parent(s): 1c98cc2
update
Browse files- READMEE.md +2 -2
- frontend/src/components/ItemSection.jsx +11 -11
- frontend/src/pages/Home.jsx +3 -3
- frontend/src/pages/LoginPage.jsx +9 -9
- frontend/src/pages/ProductDetail.jsx +33 -33
- frontend/src/pages/ProductList.jsx +25 -25
- frontend/src/pages/ProfilePage.jsx +11 -11
- frontend/src/pages/RegisterPage.jsx +19 -19
- frontend/src/pages/WishlistPage.jsx +20 -20
- frontend/src/store/slices/apiSlice.jsx +1 -1
READMEE.md
CHANGED
|
@@ -78,8 +78,8 @@ PORT=7860
|
|
| 78 |
NODE_ENV=production
|
| 79 |
DB_URL=
|
| 80 |
JWT_SECRET_KEY=
|
| 81 |
-
APP_URL=https://
|
| 82 |
-
FRONTEND_URL=https://
|
| 83 |
```
|
| 84 |
|
| 85 |
#### Frontend (`frontend/.env`)
|
|
|
|
| 78 |
NODE_ENV=production
|
| 79 |
DB_URL=
|
| 80 |
JWT_SECRET_KEY=
|
| 81 |
+
APP_URL=https://kumar715-mkcart.hf.space
|
| 82 |
+
FRONTEND_URL=https://kumar715-mkcart.hf.space
|
| 83 |
```
|
| 84 |
|
| 85 |
#### Frontend (`frontend/.env`)
|
frontend/src/components/ItemSection.jsx
CHANGED
|
@@ -57,7 +57,7 @@ export default function ItemSection() {
|
|
| 57 |
|
| 58 |
useEffect(() => {
|
| 59 |
fetch(
|
| 60 |
-
`${process.env.REACT_APP_API_URL || "https://
|
| 61 |
)
|
| 62 |
.then((res) => res.json())
|
| 63 |
.then((data) => {
|
|
@@ -276,14 +276,14 @@ export default function ItemSection() {
|
|
| 276 |
return (
|
| 277 |
<>
|
| 278 |
<div className="modern-item-section">
|
| 279 |
-
{}
|
| 280 |
<motion.div
|
| 281 |
className="hero-section"
|
| 282 |
initial={{ opacity: 0, y: 50 }}
|
| 283 |
animate={{ opacity: 1, y: 0 }}
|
| 284 |
transition={{ duration: 0.8 }}
|
| 285 |
>
|
| 286 |
-
{}
|
| 287 |
<div className="hero-floating-animations">
|
| 288 |
{[...Array(10)].map((_, i) => (
|
| 289 |
<motion.div
|
|
@@ -352,7 +352,7 @@ export default function ItemSection() {
|
|
| 352 |
</div>
|
| 353 |
</motion.div>
|
| 354 |
|
| 355 |
-
{}
|
| 356 |
{Object.keys(groupedProducts).map((category, categoryIndex) => (
|
| 357 |
<motion.div
|
| 358 |
key={category}
|
|
@@ -382,7 +382,7 @@ export default function ItemSection() {
|
|
| 382 |
{(groupedProducts[category] || []).map((product) => (
|
| 383 |
<div className="modern-product-card" key={product._id}>
|
| 384 |
<div className="product-card-inner">
|
| 385 |
-
{}
|
| 386 |
<div className="product-image-container">
|
| 387 |
<Link
|
| 388 |
to={`/product/${product._id}`}
|
|
@@ -396,7 +396,7 @@ export default function ItemSection() {
|
|
| 396 |
transition={{ duration: 0.3 }}
|
| 397 |
/>
|
| 398 |
</Link>
|
| 399 |
-
{}
|
| 400 |
<motion.button
|
| 401 |
className={`wishlist-btn ${wishlistProductIds.has(product._id) ? "active" : ""}`}
|
| 402 |
onClick={() => toggleWishlist(product._id, product)}
|
|
@@ -412,7 +412,7 @@ export default function ItemSection() {
|
|
| 412 |
}
|
| 413 |
/>
|
| 414 |
</motion.button>
|
| 415 |
-
{}
|
| 416 |
<motion.div
|
| 417 |
className="quick-view-btn"
|
| 418 |
whileHover={{ scale: 1.1 }}
|
|
@@ -422,7 +422,7 @@ export default function ItemSection() {
|
|
| 422 |
</Link>
|
| 423 |
</motion.div>
|
| 424 |
</div>
|
| 425 |
-
{}
|
| 426 |
<div className="product-info">
|
| 427 |
<h1 className="product-title">
|
| 428 |
<Link to={`/product/${product._id}`}>
|
|
@@ -452,7 +452,7 @@ export default function ItemSection() {
|
|
| 452 |
style={{ color: "#00b894", fontWeight: 700 }}
|
| 453 |
>
|
| 454 |
{typeof product.price === "number" &&
|
| 455 |
-
|
| 456 |
? product.price.toLocaleString()
|
| 457 |
: "N/A"}
|
| 458 |
</span>
|
|
@@ -464,7 +464,7 @@ export default function ItemSection() {
|
|
| 464 |
? product.description.slice(0, 25) + "..."
|
| 465 |
: product.description
|
| 466 |
: product.description.slice(0, 50) +
|
| 467 |
-
|
| 468 |
</div>
|
| 469 |
<motion.div
|
| 470 |
whileHover={{ scale: 1.08 }}
|
|
@@ -478,7 +478,7 @@ export default function ItemSection() {
|
|
| 478 |
</Link>
|
| 479 |
</motion.div>
|
| 480 |
</div>
|
| 481 |
-
{}
|
| 482 |
<div className="item-actions">
|
| 483 |
<motion.button
|
| 484 |
className={`add-to-cart-btn-premium${isInCart(product._id) ? " in-cart" : ""}`}
|
|
|
|
| 57 |
|
| 58 |
useEffect(() => {
|
| 59 |
fetch(
|
| 60 |
+
`${process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space"}/api/products`,
|
| 61 |
)
|
| 62 |
.then((res) => res.json())
|
| 63 |
.then((data) => {
|
|
|
|
| 276 |
return (
|
| 277 |
<>
|
| 278 |
<div className="modern-item-section">
|
| 279 |
+
{ }
|
| 280 |
<motion.div
|
| 281 |
className="hero-section"
|
| 282 |
initial={{ opacity: 0, y: 50 }}
|
| 283 |
animate={{ opacity: 1, y: 0 }}
|
| 284 |
transition={{ duration: 0.8 }}
|
| 285 |
>
|
| 286 |
+
{ }
|
| 287 |
<div className="hero-floating-animations">
|
| 288 |
{[...Array(10)].map((_, i) => (
|
| 289 |
<motion.div
|
|
|
|
| 352 |
</div>
|
| 353 |
</motion.div>
|
| 354 |
|
| 355 |
+
{ }
|
| 356 |
{Object.keys(groupedProducts).map((category, categoryIndex) => (
|
| 357 |
<motion.div
|
| 358 |
key={category}
|
|
|
|
| 382 |
{(groupedProducts[category] || []).map((product) => (
|
| 383 |
<div className="modern-product-card" key={product._id}>
|
| 384 |
<div className="product-card-inner">
|
| 385 |
+
{ }
|
| 386 |
<div className="product-image-container">
|
| 387 |
<Link
|
| 388 |
to={`/product/${product._id}`}
|
|
|
|
| 396 |
transition={{ duration: 0.3 }}
|
| 397 |
/>
|
| 398 |
</Link>
|
| 399 |
+
{ }
|
| 400 |
<motion.button
|
| 401 |
className={`wishlist-btn ${wishlistProductIds.has(product._id) ? "active" : ""}`}
|
| 402 |
onClick={() => toggleWishlist(product._id, product)}
|
|
|
|
| 412 |
}
|
| 413 |
/>
|
| 414 |
</motion.button>
|
| 415 |
+
{ }
|
| 416 |
<motion.div
|
| 417 |
className="quick-view-btn"
|
| 418 |
whileHover={{ scale: 1.1 }}
|
|
|
|
| 422 |
</Link>
|
| 423 |
</motion.div>
|
| 424 |
</div>
|
| 425 |
+
{ }
|
| 426 |
<div className="product-info">
|
| 427 |
<h1 className="product-title">
|
| 428 |
<Link to={`/product/${product._id}`}>
|
|
|
|
| 452 |
style={{ color: "#00b894", fontWeight: 700 }}
|
| 453 |
>
|
| 454 |
{typeof product.price === "number" &&
|
| 455 |
+
!isNaN(product.price)
|
| 456 |
? product.price.toLocaleString()
|
| 457 |
: "N/A"}
|
| 458 |
</span>
|
|
|
|
| 464 |
? product.description.slice(0, 25) + "..."
|
| 465 |
: product.description
|
| 466 |
: product.description.slice(0, 50) +
|
| 467 |
+
(product.description.length > 50 ? "..." : "")}
|
| 468 |
</div>
|
| 469 |
<motion.div
|
| 470 |
whileHover={{ scale: 1.08 }}
|
|
|
|
| 478 |
</Link>
|
| 479 |
</motion.div>
|
| 480 |
</div>
|
| 481 |
+
{ }
|
| 482 |
<div className="item-actions">
|
| 483 |
<motion.button
|
| 484 |
className={`add-to-cart-btn-premium${isInCart(product._id) ? " in-cart" : ""}`}
|
frontend/src/pages/Home.jsx
CHANGED
|
@@ -9,9 +9,9 @@ export default function Home() {
|
|
| 9 |
|
| 10 |
useEffect(() => {
|
| 11 |
fetch(
|
| 12 |
-
(process.env.REACT_APP_API_URL || "https://
|
| 13 |
-
|
| 14 |
-
|
| 15 |
)
|
| 16 |
.then((res) => res.json())
|
| 17 |
.then((res) => {
|
|
|
|
| 9 |
|
| 10 |
useEffect(() => {
|
| 11 |
fetch(
|
| 12 |
+
(process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space") +
|
| 13 |
+
"/api/products?" +
|
| 14 |
+
searchParams,
|
| 15 |
)
|
| 16 |
.then((res) => res.json())
|
| 17 |
.then((res) => {
|
frontend/src/pages/LoginPage.jsx
CHANGED
|
@@ -41,8 +41,8 @@ const LoginPage = () => {
|
|
| 41 |
const canvasRef = useRef(null);
|
| 42 |
const BACKEND_URL =
|
| 43 |
process.env.NODE_ENV === "production"
|
| 44 |
-
? (process.env.REACT_APP_API_URL || "https://
|
| 45 |
-
|
| 46 |
: "http://localhost:7860/api";
|
| 47 |
const dispatch = useDispatch();
|
| 48 |
useEffect(() => {
|
|
@@ -239,10 +239,10 @@ const LoginPage = () => {
|
|
| 239 |
|
| 240 |
return (
|
| 241 |
<div className="login-page">
|
| 242 |
-
{}
|
| 243 |
<canvas ref={canvasRef} className="background-canvas" />
|
| 244 |
|
| 245 |
-
{}
|
| 246 |
<div className="floating-particles">
|
| 247 |
{particles.map((particle) => (
|
| 248 |
<motion.div
|
|
@@ -270,10 +270,10 @@ const LoginPage = () => {
|
|
| 270 |
))}
|
| 271 |
</div>
|
| 272 |
|
| 273 |
-
{}
|
| 274 |
<div className="login-container">
|
| 275 |
<div className="login-grid">
|
| 276 |
-
{}
|
| 277 |
<motion.div
|
| 278 |
className="login-branding"
|
| 279 |
initial={{ opacity: 0, x: -100 }}
|
|
@@ -352,7 +352,7 @@ const LoginPage = () => {
|
|
| 352 |
</motion.div>
|
| 353 |
</div>
|
| 354 |
|
| 355 |
-
{}
|
| 356 |
<div className="branding-decorations">
|
| 357 |
<motion.div
|
| 358 |
className="decoration gem-1"
|
|
@@ -406,7 +406,7 @@ const LoginPage = () => {
|
|
| 406 |
</div>
|
| 407 |
</motion.div>
|
| 408 |
|
| 409 |
-
{}
|
| 410 |
<motion.div
|
| 411 |
className="login-form-container"
|
| 412 |
initial={{ opacity: 0, x: 100 }}
|
|
@@ -424,7 +424,7 @@ const LoginPage = () => {
|
|
| 424 |
<p>Enter your credentials to access your account</p>
|
| 425 |
</motion.div>
|
| 426 |
|
| 427 |
-
{}
|
| 428 |
<motion.form
|
| 429 |
className="auth-form"
|
| 430 |
onSubmit={handleSubmit}
|
|
|
|
| 41 |
const canvasRef = useRef(null);
|
| 42 |
const BACKEND_URL =
|
| 43 |
process.env.NODE_ENV === "production"
|
| 44 |
+
? (process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space") +
|
| 45 |
+
"/api"
|
| 46 |
: "http://localhost:7860/api";
|
| 47 |
const dispatch = useDispatch();
|
| 48 |
useEffect(() => {
|
|
|
|
| 239 |
|
| 240 |
return (
|
| 241 |
<div className="login-page">
|
| 242 |
+
{ }
|
| 243 |
<canvas ref={canvasRef} className="background-canvas" />
|
| 244 |
|
| 245 |
+
{ }
|
| 246 |
<div className="floating-particles">
|
| 247 |
{particles.map((particle) => (
|
| 248 |
<motion.div
|
|
|
|
| 270 |
))}
|
| 271 |
</div>
|
| 272 |
|
| 273 |
+
{ }
|
| 274 |
<div className="login-container">
|
| 275 |
<div className="login-grid">
|
| 276 |
+
{ }
|
| 277 |
<motion.div
|
| 278 |
className="login-branding"
|
| 279 |
initial={{ opacity: 0, x: -100 }}
|
|
|
|
| 352 |
</motion.div>
|
| 353 |
</div>
|
| 354 |
|
| 355 |
+
{ }
|
| 356 |
<div className="branding-decorations">
|
| 357 |
<motion.div
|
| 358 |
className="decoration gem-1"
|
|
|
|
| 406 |
</div>
|
| 407 |
</motion.div>
|
| 408 |
|
| 409 |
+
{ }
|
| 410 |
<motion.div
|
| 411 |
className="login-form-container"
|
| 412 |
initial={{ opacity: 0, x: 100 }}
|
|
|
|
| 424 |
<p>Enter your credentials to access your account</p>
|
| 425 |
</motion.div>
|
| 426 |
|
| 427 |
+
{ }
|
| 428 |
<motion.form
|
| 429 |
className="auth-form"
|
| 430 |
onSubmit={handleSubmit}
|
frontend/src/pages/ProductDetail.jsx
CHANGED
|
@@ -68,9 +68,9 @@ export default function ProductDetail() {
|
|
| 68 |
window.scrollTo(0, 0);
|
| 69 |
setLoading(true);
|
| 70 |
fetch(
|
| 71 |
-
(process.env.REACT_APP_API_URL || "https://
|
| 72 |
-
|
| 73 |
-
|
| 74 |
)
|
| 75 |
.then((res) => res.json())
|
| 76 |
.then((res) => {
|
|
@@ -146,19 +146,19 @@ export default function ProductDetail() {
|
|
| 146 |
const mappedCartItems = cartItemsFromRTK.map((i) =>
|
| 147 |
i.product
|
| 148 |
? {
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
: i,
|
| 163 |
);
|
| 164 |
|
|
@@ -337,7 +337,7 @@ export default function ProductDetail() {
|
|
| 337 |
product && (
|
| 338 |
<div className="modern-product-detail">
|
| 339 |
<div className="container">
|
| 340 |
-
{}
|
| 341 |
<motion.div
|
| 342 |
className="Premium-info-bar"
|
| 343 |
initial={{ opacity: 0, y: -20 }}
|
|
@@ -385,7 +385,7 @@ export default function ProductDetail() {
|
|
| 385 |
animate={{ opacity: 1, y: 0 }}
|
| 386 |
transition={{ duration: 0.8 }}
|
| 387 |
>
|
| 388 |
-
{}
|
| 389 |
<div className="product-images-section">
|
| 390 |
<motion.div
|
| 391 |
className="main-image-container"
|
|
@@ -404,7 +404,7 @@ export default function ProductDetail() {
|
|
| 404 |
/>
|
| 405 |
<div className="image-glow"></div>
|
| 406 |
|
| 407 |
-
{}
|
| 408 |
<motion.button
|
| 409 |
className={`wishlist-btn-large ${wishlistProductIds.has(product._id) ? "active" : ""}`}
|
| 410 |
onClick={toggleWishlist}
|
|
@@ -420,7 +420,7 @@ export default function ProductDetail() {
|
|
| 420 |
</motion.button>
|
| 421 |
</motion.div>
|
| 422 |
|
| 423 |
-
{}
|
| 424 |
{product.images.length > 1 && (
|
| 425 |
<div className="thumbnail-images">
|
| 426 |
{product.images.map((img, index) => (
|
|
@@ -441,7 +441,7 @@ export default function ProductDetail() {
|
|
| 441 |
)}
|
| 442 |
</div>
|
| 443 |
|
| 444 |
-
{}
|
| 445 |
<motion.div
|
| 446 |
className="product-info-section"
|
| 447 |
initial={{ opacity: 0, x: 50 }}
|
|
@@ -453,7 +453,7 @@ export default function ProductDetail() {
|
|
| 453 |
<p className="product-id">Product #{product._id}</p>
|
| 454 |
</div>
|
| 455 |
|
| 456 |
-
{}
|
| 457 |
<div className="product-rating-section">
|
| 458 |
<div className="stars-large">
|
| 459 |
{renderStars(
|
|
@@ -469,7 +469,7 @@ export default function ProductDetail() {
|
|
| 469 |
</span>
|
| 470 |
</div>
|
| 471 |
|
| 472 |
-
{}
|
| 473 |
<div className="price-section">
|
| 474 |
<div className="current-price">
|
| 475 |
<span className="currency">₹</span>
|
|
@@ -480,7 +480,7 @@ export default function ProductDetail() {
|
|
| 480 |
<div className="price-glow"></div>
|
| 481 |
</div>
|
| 482 |
|
| 483 |
-
{}
|
| 484 |
<div className="stock-section">
|
| 485 |
<div
|
| 486 |
className={`stock-status ${product.stock > 0 ? "in-stock" : "out-of-stock"}`}
|
|
@@ -494,7 +494,7 @@ export default function ProductDetail() {
|
|
| 494 |
</div>
|
| 495 |
</div>
|
| 496 |
|
| 497 |
-
{}
|
| 498 |
<div className="quantity-section">
|
| 499 |
<label className="quantity-label">Quantity:</label>
|
| 500 |
<div className="quantity-controls">
|
|
@@ -520,7 +520,7 @@ export default function ProductDetail() {
|
|
| 520 |
</div>
|
| 521 |
</div>
|
| 522 |
|
| 523 |
-
{}
|
| 524 |
<div className="action-buttons">
|
| 525 |
<motion.button
|
| 526 |
className="add-to-cart-btn-blue"
|
|
@@ -546,7 +546,7 @@ export default function ProductDetail() {
|
|
| 546 |
</motion.button>
|
| 547 |
</div>
|
| 548 |
|
| 549 |
-
{}
|
| 550 |
<div className="product-features">
|
| 551 |
<div className="feature">
|
| 552 |
<Truck size={20} />
|
|
@@ -562,13 +562,13 @@ export default function ProductDetail() {
|
|
| 562 |
</div>
|
| 563 |
</div>
|
| 564 |
|
| 565 |
-
{}
|
| 566 |
<div className="description-section">
|
| 567 |
<h3 className="description-title">Description</h3>
|
| 568 |
<p className="description-text">{product.description}</p>
|
| 569 |
</div>
|
| 570 |
|
| 571 |
-
{}
|
| 572 |
<div className="seller-section">
|
| 573 |
<h4 className="seller-title">Seller Information</h4>
|
| 574 |
<p className="seller-name">
|
|
@@ -576,7 +576,7 @@ export default function ProductDetail() {
|
|
| 576 |
</p>
|
| 577 |
</div>
|
| 578 |
|
| 579 |
-
{}
|
| 580 |
{product.specifications && (
|
| 581 |
<motion.div
|
| 582 |
className="specifications-section glass-effect-strong"
|
|
@@ -603,7 +603,7 @@ export default function ProductDetail() {
|
|
| 603 |
</motion.div>
|
| 604 |
)}
|
| 605 |
|
| 606 |
-
{}
|
| 607 |
{(product.warrantyDetails || product.afterSalesSupport) && (
|
| 608 |
<motion.div
|
| 609 |
className="warranty-section glass-effect-strong"
|
|
@@ -628,7 +628,7 @@ export default function ProductDetail() {
|
|
| 628 |
</motion.div>
|
| 629 |
)}
|
| 630 |
|
| 631 |
-
{}
|
| 632 |
{product.reviews && product.reviews.length > 0 && (
|
| 633 |
<motion.div
|
| 634 |
className="reviews-section glass-effect-strong"
|
|
@@ -681,7 +681,7 @@ export default function ProductDetail() {
|
|
| 681 |
className="helpful-btn"
|
| 682 |
aria-label="Mark review as helpful"
|
| 683 |
tabIndex={0}
|
| 684 |
-
onClick={() => {}}
|
| 685 |
>
|
| 686 |
👍 Helpful
|
| 687 |
</button>
|
|
|
|
| 68 |
window.scrollTo(0, 0);
|
| 69 |
setLoading(true);
|
| 70 |
fetch(
|
| 71 |
+
(process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space") +
|
| 72 |
+
"/api/product/" +
|
| 73 |
+
id,
|
| 74 |
)
|
| 75 |
.then((res) => res.json())
|
| 76 |
.then((res) => {
|
|
|
|
| 146 |
const mappedCartItems = cartItemsFromRTK.map((i) =>
|
| 147 |
i.product
|
| 148 |
? {
|
| 149 |
+
productId: i.product._id,
|
| 150 |
+
name: i.product.name,
|
| 151 |
+
price: i.product.price,
|
| 152 |
+
qty: i.qty,
|
| 153 |
+
category: i.product.category,
|
| 154 |
+
seller: i.product.seller,
|
| 155 |
+
stock: i.product.stock,
|
| 156 |
+
image:
|
| 157 |
+
i.product.images && i.product.images[0]
|
| 158 |
+
? i.product.images[0].image
|
| 159 |
+
: "",
|
| 160 |
+
ratings: i.product.ratings,
|
| 161 |
+
}
|
| 162 |
: i,
|
| 163 |
);
|
| 164 |
|
|
|
|
| 337 |
product && (
|
| 338 |
<div className="modern-product-detail">
|
| 339 |
<div className="container">
|
| 340 |
+
{ }
|
| 341 |
<motion.div
|
| 342 |
className="Premium-info-bar"
|
| 343 |
initial={{ opacity: 0, y: -20 }}
|
|
|
|
| 385 |
animate={{ opacity: 1, y: 0 }}
|
| 386 |
transition={{ duration: 0.8 }}
|
| 387 |
>
|
| 388 |
+
{ }
|
| 389 |
<div className="product-images-section">
|
| 390 |
<motion.div
|
| 391 |
className="main-image-container"
|
|
|
|
| 404 |
/>
|
| 405 |
<div className="image-glow"></div>
|
| 406 |
|
| 407 |
+
{ }
|
| 408 |
<motion.button
|
| 409 |
className={`wishlist-btn-large ${wishlistProductIds.has(product._id) ? "active" : ""}`}
|
| 410 |
onClick={toggleWishlist}
|
|
|
|
| 420 |
</motion.button>
|
| 421 |
</motion.div>
|
| 422 |
|
| 423 |
+
{ }
|
| 424 |
{product.images.length > 1 && (
|
| 425 |
<div className="thumbnail-images">
|
| 426 |
{product.images.map((img, index) => (
|
|
|
|
| 441 |
)}
|
| 442 |
</div>
|
| 443 |
|
| 444 |
+
{ }
|
| 445 |
<motion.div
|
| 446 |
className="product-info-section"
|
| 447 |
initial={{ opacity: 0, x: 50 }}
|
|
|
|
| 453 |
<p className="product-id">Product #{product._id}</p>
|
| 454 |
</div>
|
| 455 |
|
| 456 |
+
{ }
|
| 457 |
<div className="product-rating-section">
|
| 458 |
<div className="stars-large">
|
| 459 |
{renderStars(
|
|
|
|
| 469 |
</span>
|
| 470 |
</div>
|
| 471 |
|
| 472 |
+
{ }
|
| 473 |
<div className="price-section">
|
| 474 |
<div className="current-price">
|
| 475 |
<span className="currency">₹</span>
|
|
|
|
| 480 |
<div className="price-glow"></div>
|
| 481 |
</div>
|
| 482 |
|
| 483 |
+
{ }
|
| 484 |
<div className="stock-section">
|
| 485 |
<div
|
| 486 |
className={`stock-status ${product.stock > 0 ? "in-stock" : "out-of-stock"}`}
|
|
|
|
| 494 |
</div>
|
| 495 |
</div>
|
| 496 |
|
| 497 |
+
{ }
|
| 498 |
<div className="quantity-section">
|
| 499 |
<label className="quantity-label">Quantity:</label>
|
| 500 |
<div className="quantity-controls">
|
|
|
|
| 520 |
</div>
|
| 521 |
</div>
|
| 522 |
|
| 523 |
+
{ }
|
| 524 |
<div className="action-buttons">
|
| 525 |
<motion.button
|
| 526 |
className="add-to-cart-btn-blue"
|
|
|
|
| 546 |
</motion.button>
|
| 547 |
</div>
|
| 548 |
|
| 549 |
+
{ }
|
| 550 |
<div className="product-features">
|
| 551 |
<div className="feature">
|
| 552 |
<Truck size={20} />
|
|
|
|
| 562 |
</div>
|
| 563 |
</div>
|
| 564 |
|
| 565 |
+
{ }
|
| 566 |
<div className="description-section">
|
| 567 |
<h3 className="description-title">Description</h3>
|
| 568 |
<p className="description-text">{product.description}</p>
|
| 569 |
</div>
|
| 570 |
|
| 571 |
+
{ }
|
| 572 |
<div className="seller-section">
|
| 573 |
<h4 className="seller-title">Seller Information</h4>
|
| 574 |
<p className="seller-name">
|
|
|
|
| 576 |
</p>
|
| 577 |
</div>
|
| 578 |
|
| 579 |
+
{ }
|
| 580 |
{product.specifications && (
|
| 581 |
<motion.div
|
| 582 |
className="specifications-section glass-effect-strong"
|
|
|
|
| 603 |
</motion.div>
|
| 604 |
)}
|
| 605 |
|
| 606 |
+
{ }
|
| 607 |
{(product.warrantyDetails || product.afterSalesSupport) && (
|
| 608 |
<motion.div
|
| 609 |
className="warranty-section glass-effect-strong"
|
|
|
|
| 628 |
</motion.div>
|
| 629 |
)}
|
| 630 |
|
| 631 |
+
{ }
|
| 632 |
{product.reviews && product.reviews.length > 0 && (
|
| 633 |
<motion.div
|
| 634 |
className="reviews-section glass-effect-strong"
|
|
|
|
| 681 |
className="helpful-btn"
|
| 682 |
aria-label="Mark review as helpful"
|
| 683 |
tabIndex={0}
|
| 684 |
+
onClick={() => { }}
|
| 685 |
>
|
| 686 |
👍 Helpful
|
| 687 |
</button>
|
frontend/src/pages/ProductList.jsx
CHANGED
|
@@ -75,7 +75,7 @@ export default function ProductList() {
|
|
| 75 |
}, []);
|
| 76 |
useEffect(() => {
|
| 77 |
fetch(
|
| 78 |
-
`${process.env.REACT_APP_API_URL || "https://
|
| 79 |
)
|
| 80 |
.then((res) => res.json())
|
| 81 |
.then((data) => {
|
|
@@ -254,17 +254,17 @@ export default function ProductList() {
|
|
| 254 |
: true;
|
| 255 |
const matchesPrice = priceRange
|
| 256 |
? (priceRange === "low" && product.price < 500) ||
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
: true;
|
| 262 |
const matchesRating = ratingFilter
|
| 263 |
? product.ratings >= Number(ratingFilter)
|
| 264 |
: true;
|
| 265 |
const matchesKeyword = searchKeyword
|
| 266 |
? product.name.toLowerCase().includes(searchKeyword) ||
|
| 267 |
-
|
| 268 |
: true;
|
| 269 |
return matchesCategory && matchesPrice && matchesRating && matchesKeyword;
|
| 270 |
});
|
|
@@ -312,7 +312,7 @@ export default function ProductList() {
|
|
| 312 |
return (
|
| 313 |
<div className="modern-product-list">
|
| 314 |
<div className="container">
|
| 315 |
-
{}
|
| 316 |
{!searchKeyword ? (
|
| 317 |
<motion.div
|
| 318 |
className="page-header"
|
|
@@ -359,7 +359,7 @@ export default function ProductList() {
|
|
| 359 |
</motion.div>
|
| 360 |
)}
|
| 361 |
|
| 362 |
-
{}
|
| 363 |
<motion.div
|
| 364 |
className="controls-section"
|
| 365 |
initial={{ opacity: 0, y: 30 }}
|
|
@@ -404,7 +404,7 @@ export default function ProductList() {
|
|
| 404 |
</motion.div>
|
| 405 |
|
| 406 |
<div className="main-content">
|
| 407 |
-
{}
|
| 408 |
<motion.div
|
| 409 |
className={`filters-sidebar ${showFilters ? "show" : ""}`}
|
| 410 |
initial={{ x: -300, opacity: 0 }}
|
|
@@ -435,7 +435,7 @@ export default function ProductList() {
|
|
| 435 |
</button>
|
| 436 |
<h3 className="filters-title">Filters</h3>
|
| 437 |
|
| 438 |
-
{}
|
| 439 |
<div className="filter-group">
|
| 440 |
<h4 className="filter-group-title">Categories</h4>
|
| 441 |
<div className="filter-options">
|
|
@@ -461,7 +461,7 @@ export default function ProductList() {
|
|
| 461 |
</div>
|
| 462 |
</div>
|
| 463 |
|
| 464 |
-
{}
|
| 465 |
<div className="filter-group">
|
| 466 |
<h4 className="filter-group-title">Price Range</h4>
|
| 467 |
<select
|
|
@@ -476,7 +476,7 @@ export default function ProductList() {
|
|
| 476 |
</select>
|
| 477 |
</div>
|
| 478 |
|
| 479 |
-
{}
|
| 480 |
<div className="filter-group">
|
| 481 |
<h4 className="filter-group-title">Rating</h4>
|
| 482 |
<select
|
|
@@ -494,7 +494,7 @@ export default function ProductList() {
|
|
| 494 |
</div>
|
| 495 |
</motion.div>
|
| 496 |
|
| 497 |
-
{}
|
| 498 |
<div className="products-section">
|
| 499 |
{filteredProducts.length > 0 ? (
|
| 500 |
<motion.div
|
|
@@ -515,7 +515,7 @@ export default function ProductList() {
|
|
| 515 |
>
|
| 516 |
<div className="modern-product-card">
|
| 517 |
<div className="product-card-inner">
|
| 518 |
-
{}
|
| 519 |
<div className="product-image-container">
|
| 520 |
<Link
|
| 521 |
to={`/product/${product._id}`}
|
|
@@ -533,7 +533,7 @@ export default function ProductList() {
|
|
| 533 |
/>
|
| 534 |
</Link>
|
| 535 |
|
| 536 |
-
{}
|
| 537 |
<motion.button
|
| 538 |
className={`wishlist-btn ${wishlistProductIds.has(product._id) ? "active" : ""}`}
|
| 539 |
onClick={() => toggleWishlist(product._id, product)}
|
|
@@ -550,7 +550,7 @@ export default function ProductList() {
|
|
| 550 |
/>
|
| 551 |
</motion.button>
|
| 552 |
|
| 553 |
-
{}
|
| 554 |
<motion.div
|
| 555 |
className="quick-view-btn"
|
| 556 |
whileHover={{ scale: 1.1 }}
|
|
@@ -561,7 +561,7 @@ export default function ProductList() {
|
|
| 561 |
</motion.div>
|
| 562 |
</div>
|
| 563 |
|
| 564 |
-
{}
|
| 565 |
<div className="product-info">
|
| 566 |
<h3 className="product-title">
|
| 567 |
<Link to={`/product/${product._id}`}>
|
|
@@ -569,7 +569,7 @@ export default function ProductList() {
|
|
| 569 |
</Link>
|
| 570 |
</h3>
|
| 571 |
|
| 572 |
-
{}
|
| 573 |
<div className="product-rating">
|
| 574 |
<div className="stars">
|
| 575 |
{renderStars(product.ratings)}
|
|
@@ -579,14 +579,14 @@ export default function ProductList() {
|
|
| 579 |
</span>
|
| 580 |
</div>
|
| 581 |
|
| 582 |
-
{}
|
| 583 |
<div className="product-price-center">
|
| 584 |
<span className="price-symbol">₹</span>
|
| 585 |
<span className="price-amount">
|
| 586 |
{product.price}
|
| 587 |
</span>
|
| 588 |
</div>
|
| 589 |
-
{}
|
| 590 |
<div className="info-row">
|
| 591 |
<div className="product-description-snippet">
|
| 592 |
{window.innerWidth <= 600
|
|
@@ -594,9 +594,9 @@ export default function ProductList() {
|
|
| 594 |
? product.description.slice(0, 25) + "..."
|
| 595 |
: product.description
|
| 596 |
: product.description.slice(0, 50) +
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
| 600 |
</div>
|
| 601 |
|
| 602 |
<motion.div
|
|
@@ -611,7 +611,7 @@ export default function ProductList() {
|
|
| 611 |
</Link>
|
| 612 |
</motion.div>
|
| 613 |
</div>
|
| 614 |
-
{}
|
| 615 |
<div className="item-actions">
|
| 616 |
<motion.button
|
| 617 |
className={`add-to-cart-btn-premium${isInCart(product._id) ? " in-cart" : ""}`}
|
|
@@ -654,7 +654,7 @@ export default function ProductList() {
|
|
| 654 |
</div>
|
| 655 |
</div>
|
| 656 |
|
| 657 |
-
{}
|
| 658 |
<motion.button
|
| 659 |
onClick={scrollToTop}
|
| 660 |
className="scroll-to-top-btn"
|
|
|
|
| 75 |
}, []);
|
| 76 |
useEffect(() => {
|
| 77 |
fetch(
|
| 78 |
+
`${process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space"}/api/products`,
|
| 79 |
)
|
| 80 |
.then((res) => res.json())
|
| 81 |
.then((data) => {
|
|
|
|
| 254 |
: true;
|
| 255 |
const matchesPrice = priceRange
|
| 256 |
? (priceRange === "low" && product.price < 500) ||
|
| 257 |
+
(priceRange === "mid" &&
|
| 258 |
+
product.price >= 500 &&
|
| 259 |
+
product.price <= 1500) ||
|
| 260 |
+
(priceRange === "high" && product.price > 1500)
|
| 261 |
: true;
|
| 262 |
const matchesRating = ratingFilter
|
| 263 |
? product.ratings >= Number(ratingFilter)
|
| 264 |
: true;
|
| 265 |
const matchesKeyword = searchKeyword
|
| 266 |
? product.name.toLowerCase().includes(searchKeyword) ||
|
| 267 |
+
product.description?.toLowerCase().includes(searchKeyword)
|
| 268 |
: true;
|
| 269 |
return matchesCategory && matchesPrice && matchesRating && matchesKeyword;
|
| 270 |
});
|
|
|
|
| 312 |
return (
|
| 313 |
<div className="modern-product-list">
|
| 314 |
<div className="container">
|
| 315 |
+
{ }
|
| 316 |
{!searchKeyword ? (
|
| 317 |
<motion.div
|
| 318 |
className="page-header"
|
|
|
|
| 359 |
</motion.div>
|
| 360 |
)}
|
| 361 |
|
| 362 |
+
{ }
|
| 363 |
<motion.div
|
| 364 |
className="controls-section"
|
| 365 |
initial={{ opacity: 0, y: 30 }}
|
|
|
|
| 404 |
</motion.div>
|
| 405 |
|
| 406 |
<div className="main-content">
|
| 407 |
+
{ }
|
| 408 |
<motion.div
|
| 409 |
className={`filters-sidebar ${showFilters ? "show" : ""}`}
|
| 410 |
initial={{ x: -300, opacity: 0 }}
|
|
|
|
| 435 |
</button>
|
| 436 |
<h3 className="filters-title">Filters</h3>
|
| 437 |
|
| 438 |
+
{ }
|
| 439 |
<div className="filter-group">
|
| 440 |
<h4 className="filter-group-title">Categories</h4>
|
| 441 |
<div className="filter-options">
|
|
|
|
| 461 |
</div>
|
| 462 |
</div>
|
| 463 |
|
| 464 |
+
{ }
|
| 465 |
<div className="filter-group">
|
| 466 |
<h4 className="filter-group-title">Price Range</h4>
|
| 467 |
<select
|
|
|
|
| 476 |
</select>
|
| 477 |
</div>
|
| 478 |
|
| 479 |
+
{ }
|
| 480 |
<div className="filter-group">
|
| 481 |
<h4 className="filter-group-title">Rating</h4>
|
| 482 |
<select
|
|
|
|
| 494 |
</div>
|
| 495 |
</motion.div>
|
| 496 |
|
| 497 |
+
{ }
|
| 498 |
<div className="products-section">
|
| 499 |
{filteredProducts.length > 0 ? (
|
| 500 |
<motion.div
|
|
|
|
| 515 |
>
|
| 516 |
<div className="modern-product-card">
|
| 517 |
<div className="product-card-inner">
|
| 518 |
+
{ }
|
| 519 |
<div className="product-image-container">
|
| 520 |
<Link
|
| 521 |
to={`/product/${product._id}`}
|
|
|
|
| 533 |
/>
|
| 534 |
</Link>
|
| 535 |
|
| 536 |
+
{ }
|
| 537 |
<motion.button
|
| 538 |
className={`wishlist-btn ${wishlistProductIds.has(product._id) ? "active" : ""}`}
|
| 539 |
onClick={() => toggleWishlist(product._id, product)}
|
|
|
|
| 550 |
/>
|
| 551 |
</motion.button>
|
| 552 |
|
| 553 |
+
{ }
|
| 554 |
<motion.div
|
| 555 |
className="quick-view-btn"
|
| 556 |
whileHover={{ scale: 1.1 }}
|
|
|
|
| 561 |
</motion.div>
|
| 562 |
</div>
|
| 563 |
|
| 564 |
+
{ }
|
| 565 |
<div className="product-info">
|
| 566 |
<h3 className="product-title">
|
| 567 |
<Link to={`/product/${product._id}`}>
|
|
|
|
| 569 |
</Link>
|
| 570 |
</h3>
|
| 571 |
|
| 572 |
+
{ }
|
| 573 |
<div className="product-rating">
|
| 574 |
<div className="stars">
|
| 575 |
{renderStars(product.ratings)}
|
|
|
|
| 579 |
</span>
|
| 580 |
</div>
|
| 581 |
|
| 582 |
+
{ }
|
| 583 |
<div className="product-price-center">
|
| 584 |
<span className="price-symbol">₹</span>
|
| 585 |
<span className="price-amount">
|
| 586 |
{product.price}
|
| 587 |
</span>
|
| 588 |
</div>
|
| 589 |
+
{ }
|
| 590 |
<div className="info-row">
|
| 591 |
<div className="product-description-snippet">
|
| 592 |
{window.innerWidth <= 600
|
|
|
|
| 594 |
? product.description.slice(0, 25) + "..."
|
| 595 |
: product.description
|
| 596 |
: product.description.slice(0, 50) +
|
| 597 |
+
(product.description.length > 50
|
| 598 |
+
? "..."
|
| 599 |
+
: "")}
|
| 600 |
</div>
|
| 601 |
|
| 602 |
<motion.div
|
|
|
|
| 611 |
</Link>
|
| 612 |
</motion.div>
|
| 613 |
</div>
|
| 614 |
+
{ }
|
| 615 |
<div className="item-actions">
|
| 616 |
<motion.button
|
| 617 |
className={`add-to-cart-btn-premium${isInCart(product._id) ? " in-cart" : ""}`}
|
|
|
|
| 654 |
</div>
|
| 655 |
</div>
|
| 656 |
|
| 657 |
+
{ }
|
| 658 |
<motion.button
|
| 659 |
onClick={scrollToTop}
|
| 660 |
className="scroll-to-top-btn"
|
frontend/src/pages/ProfilePage.jsx
CHANGED
|
@@ -61,7 +61,7 @@ const ProfilePage = () => {
|
|
| 61 |
const navigate = useNavigate();
|
| 62 |
const [logoutAPI] = useLogoutAPIMutation();
|
| 63 |
const BACKEND_URL =
|
| 64 |
-
(process.env.REACT_APP_API_URL || "https://
|
| 65 |
const canvasRef = useRef(null);
|
| 66 |
|
| 67 |
const [products, setProducts] = useReactState([]);
|
|
@@ -214,7 +214,7 @@ const ProfilePage = () => {
|
|
| 214 |
|
| 215 |
useEffect(() => {
|
| 216 |
fetch(
|
| 217 |
-
`${process.env.REACT_APP_API_URL || "https://
|
| 218 |
)
|
| 219 |
.then((res) => res.json())
|
| 220 |
.then((data) => {
|
|
@@ -674,7 +674,7 @@ const ProfilePage = () => {
|
|
| 674 |
>
|
| 675 |
{order.status
|
| 676 |
? order.status.charAt(0).toUpperCase() +
|
| 677 |
-
|
| 678 |
: "Placed"}
|
| 679 |
</button>
|
| 680 |
</div>
|
|
@@ -714,7 +714,7 @@ const ProfilePage = () => {
|
|
| 714 |
</motion.div>
|
| 715 |
</div>
|
| 716 |
<div style={{ margin: "24px" }}>
|
| 717 |
-
{}
|
| 718 |
<motion.div
|
| 719 |
className="lux-profile-stats-card cart-preview-section"
|
| 720 |
initial={{ opacity: 0, y: 40 }}
|
|
@@ -848,7 +848,7 @@ const ProfilePage = () => {
|
|
| 848 |
</motion.div>
|
| 849 |
</div>
|
| 850 |
<div style={{ margin: "24px" }}>
|
| 851 |
-
{}
|
| 852 |
<motion.div
|
| 853 |
className="lux-profile-stats-card"
|
| 854 |
initial={{ opacity: 0, y: 40 }}
|
|
@@ -943,7 +943,7 @@ const ProfilePage = () => {
|
|
| 943 |
</motion.div>
|
| 944 |
</div>
|
| 945 |
<div style={{ margin: "24px" }}>
|
| 946 |
-
{}
|
| 947 |
<motion.div
|
| 948 |
className="lux-profile-stats-card"
|
| 949 |
initial={{ opacity: 0, y: 40 }}
|
|
@@ -998,7 +998,7 @@ const ProfilePage = () => {
|
|
| 998 |
</div>
|
| 999 |
<div style={{ margin: "24px" }}></div>
|
| 1000 |
<div style={{ margin: "24px" }}>
|
| 1001 |
-
{}
|
| 1002 |
<motion.div
|
| 1003 |
className="lux-profile-activity-card"
|
| 1004 |
initial={{ opacity: 0, y: 40 }}
|
|
@@ -1032,7 +1032,7 @@ const ProfilePage = () => {
|
|
| 1032 |
))}
|
| 1033 |
</div>
|
| 1034 |
</motion.div>
|
| 1035 |
-
{}
|
| 1036 |
<div style={{ margin: "24px" }}></div>
|
| 1037 |
<motion.div
|
| 1038 |
className="lux-profile-stats-card"
|
|
@@ -1079,7 +1079,7 @@ const ProfilePage = () => {
|
|
| 1079 |
</motion.div>
|
| 1080 |
|
| 1081 |
<div style={{ margin: "24px" }}></div>
|
| 1082 |
-
{}
|
| 1083 |
<motion.div
|
| 1084 |
className="lux-profile-activity-card recommended-section"
|
| 1085 |
initial={{ opacity: 0, y: 40 }}
|
|
@@ -1135,7 +1135,7 @@ const ProfilePage = () => {
|
|
| 1135 |
</motion.div>
|
| 1136 |
</div>
|
| 1137 |
<div style={{ margin: "24px" }}>
|
| 1138 |
-
{}
|
| 1139 |
<motion.div
|
| 1140 |
className="lux-profile-activity-card"
|
| 1141 |
initial={{ opacity: 0, y: 40 }}
|
|
@@ -1203,7 +1203,7 @@ const ProfilePage = () => {
|
|
| 1203 |
</motion.div>
|
| 1204 |
</div>
|
| 1205 |
<div style={{ margin: "24px" }}>
|
| 1206 |
-
{}
|
| 1207 |
<motion.div
|
| 1208 |
className="lux-profile-activity-card"
|
| 1209 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 61 |
const navigate = useNavigate();
|
| 62 |
const [logoutAPI] = useLogoutAPIMutation();
|
| 63 |
const BACKEND_URL =
|
| 64 |
+
(process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space") + "/api";
|
| 65 |
const canvasRef = useRef(null);
|
| 66 |
|
| 67 |
const [products, setProducts] = useReactState([]);
|
|
|
|
| 214 |
|
| 215 |
useEffect(() => {
|
| 216 |
fetch(
|
| 217 |
+
`${process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space"}/api/products`,
|
| 218 |
)
|
| 219 |
.then((res) => res.json())
|
| 220 |
.then((data) => {
|
|
|
|
| 674 |
>
|
| 675 |
{order.status
|
| 676 |
? order.status.charAt(0).toUpperCase() +
|
| 677 |
+
order.status.slice(1)
|
| 678 |
: "Placed"}
|
| 679 |
</button>
|
| 680 |
</div>
|
|
|
|
| 714 |
</motion.div>
|
| 715 |
</div>
|
| 716 |
<div style={{ margin: "24px" }}>
|
| 717 |
+
{ }
|
| 718 |
<motion.div
|
| 719 |
className="lux-profile-stats-card cart-preview-section"
|
| 720 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 848 |
</motion.div>
|
| 849 |
</div>
|
| 850 |
<div style={{ margin: "24px" }}>
|
| 851 |
+
{ }
|
| 852 |
<motion.div
|
| 853 |
className="lux-profile-stats-card"
|
| 854 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 943 |
</motion.div>
|
| 944 |
</div>
|
| 945 |
<div style={{ margin: "24px" }}>
|
| 946 |
+
{ }
|
| 947 |
<motion.div
|
| 948 |
className="lux-profile-stats-card"
|
| 949 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 998 |
</div>
|
| 999 |
<div style={{ margin: "24px" }}></div>
|
| 1000 |
<div style={{ margin: "24px" }}>
|
| 1001 |
+
{ }
|
| 1002 |
<motion.div
|
| 1003 |
className="lux-profile-activity-card"
|
| 1004 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 1032 |
))}
|
| 1033 |
</div>
|
| 1034 |
</motion.div>
|
| 1035 |
+
{ }
|
| 1036 |
<div style={{ margin: "24px" }}></div>
|
| 1037 |
<motion.div
|
| 1038 |
className="lux-profile-stats-card"
|
|
|
|
| 1079 |
</motion.div>
|
| 1080 |
|
| 1081 |
<div style={{ margin: "24px" }}></div>
|
| 1082 |
+
{ }
|
| 1083 |
<motion.div
|
| 1084 |
className="lux-profile-activity-card recommended-section"
|
| 1085 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 1135 |
</motion.div>
|
| 1136 |
</div>
|
| 1137 |
<div style={{ margin: "24px" }}>
|
| 1138 |
+
{ }
|
| 1139 |
<motion.div
|
| 1140 |
className="lux-profile-activity-card"
|
| 1141 |
initial={{ opacity: 0, y: 40 }}
|
|
|
|
| 1203 |
</motion.div>
|
| 1204 |
</div>
|
| 1205 |
<div style={{ margin: "24px" }}>
|
| 1206 |
+
{ }
|
| 1207 |
<motion.div
|
| 1208 |
className="lux-profile-activity-card"
|
| 1209 |
initial={{ opacity: 0, y: 40 }}
|
frontend/src/pages/RegisterPage.jsx
CHANGED
|
@@ -54,7 +54,7 @@ const RegisterPage = () => {
|
|
| 54 |
const navigate = useNavigate();
|
| 55 |
const canvasRef = useRef(null);
|
| 56 |
const BACKEND_URL =
|
| 57 |
-
(process.env.REACT_APP_API_URL || "https://
|
| 58 |
const dispatch = useDispatch();
|
| 59 |
const [register, { isLoading: isRegistering }] = useRegisterAPIMutation();
|
| 60 |
|
|
@@ -320,10 +320,10 @@ const RegisterPage = () => {
|
|
| 320 |
|
| 321 |
return (
|
| 322 |
<div className="auth-page register-page">
|
| 323 |
-
{}
|
| 324 |
<canvas ref={canvasRef} className="background-canvas" />
|
| 325 |
|
| 326 |
-
{}
|
| 327 |
<div className="floating-particles">
|
| 328 |
{particles.map((particle) => (
|
| 329 |
<motion.div
|
|
@@ -351,10 +351,10 @@ const RegisterPage = () => {
|
|
| 351 |
))}
|
| 352 |
</div>
|
| 353 |
|
| 354 |
-
{}
|
| 355 |
<div className="auth-container">
|
| 356 |
<div className="auth-grid register-grid">
|
| 357 |
-
{}
|
| 358 |
<motion.div
|
| 359 |
className="auth-branding"
|
| 360 |
initial={{ opacity: 0, x: -100 }}
|
|
@@ -434,7 +434,7 @@ const RegisterPage = () => {
|
|
| 434 |
</motion.div>
|
| 435 |
</div>
|
| 436 |
|
| 437 |
-
{}
|
| 438 |
<div className="branding-decorations">
|
| 439 |
<motion.div
|
| 440 |
className="decoration gem-1"
|
|
@@ -504,7 +504,7 @@ const RegisterPage = () => {
|
|
| 504 |
</div>
|
| 505 |
</motion.div>
|
| 506 |
|
| 507 |
-
{}
|
| 508 |
<motion.div
|
| 509 |
className="auth-form-container"
|
| 510 |
initial={{ opacity: 0, x: 100 }}
|
|
@@ -512,8 +512,8 @@ const RegisterPage = () => {
|
|
| 512 |
transition={{ duration: 0.8, delay: 0.2 }}
|
| 513 |
>
|
| 514 |
<div className="form-wrapper">
|
| 515 |
-
{}
|
| 516 |
-
{}
|
| 517 |
|
| 518 |
<motion.div
|
| 519 |
className="form-header"
|
|
@@ -530,7 +530,7 @@ const RegisterPage = () => {
|
|
| 530 |
</p>
|
| 531 |
</motion.div>
|
| 532 |
|
| 533 |
-
{}
|
| 534 |
{currentStep === 1 && (
|
| 535 |
<motion.div
|
| 536 |
className="social-login"
|
|
@@ -582,16 +582,16 @@ const RegisterPage = () => {
|
|
| 582 |
</motion.div>
|
| 583 |
)}
|
| 584 |
|
| 585 |
-
{}
|
| 586 |
<motion.form
|
| 587 |
className="auth-form multi-step-form"
|
| 588 |
onSubmit={
|
| 589 |
currentStep === totalSteps
|
| 590 |
? handleSubmit
|
| 591 |
: (e) => {
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
}
|
| 596 |
initial={{ opacity: 0, y: 30 }}
|
| 597 |
animate={{ opacity: 1, y: 0 }}
|
|
@@ -601,7 +601,7 @@ const RegisterPage = () => {
|
|
| 601 |
}}
|
| 602 |
>
|
| 603 |
<AnimatePresence mode="wait">
|
| 604 |
-
{}
|
| 605 |
{currentStep === 1 && (
|
| 606 |
<motion.div
|
| 607 |
key="step1"
|
|
@@ -749,7 +749,7 @@ const RegisterPage = () => {
|
|
| 749 |
)}
|
| 750 |
</button>
|
| 751 |
</div>
|
| 752 |
-
{}
|
| 753 |
{formData.password && (
|
| 754 |
<motion.div
|
| 755 |
className="password-strength"
|
|
@@ -856,7 +856,7 @@ const RegisterPage = () => {
|
|
| 856 |
</motion.div>
|
| 857 |
)}
|
| 858 |
|
| 859 |
-
{}
|
| 860 |
{currentStep === 2 && (
|
| 861 |
<motion.div
|
| 862 |
key="step2"
|
|
@@ -1067,7 +1067,7 @@ const RegisterPage = () => {
|
|
| 1067 |
)}
|
| 1068 |
</AnimatePresence>
|
| 1069 |
|
| 1070 |
-
{}
|
| 1071 |
<div className="form-navigation">
|
| 1072 |
{currentStep > 1 && (
|
| 1073 |
<motion.button
|
|
@@ -1139,7 +1139,7 @@ const RegisterPage = () => {
|
|
| 1139 |
</div>
|
| 1140 |
</motion.form>
|
| 1141 |
|
| 1142 |
-
{}
|
| 1143 |
<motion.div
|
| 1144 |
className="trust-indicators"
|
| 1145 |
initial={{ opacity: 0, y: 30 }}
|
|
|
|
| 54 |
const navigate = useNavigate();
|
| 55 |
const canvasRef = useRef(null);
|
| 56 |
const BACKEND_URL =
|
| 57 |
+
(process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space") + "/api";
|
| 58 |
const dispatch = useDispatch();
|
| 59 |
const [register, { isLoading: isRegistering }] = useRegisterAPIMutation();
|
| 60 |
|
|
|
|
| 320 |
|
| 321 |
return (
|
| 322 |
<div className="auth-page register-page">
|
| 323 |
+
{ }
|
| 324 |
<canvas ref={canvasRef} className="background-canvas" />
|
| 325 |
|
| 326 |
+
{ }
|
| 327 |
<div className="floating-particles">
|
| 328 |
{particles.map((particle) => (
|
| 329 |
<motion.div
|
|
|
|
| 351 |
))}
|
| 352 |
</div>
|
| 353 |
|
| 354 |
+
{ }
|
| 355 |
<div className="auth-container">
|
| 356 |
<div className="auth-grid register-grid">
|
| 357 |
+
{ }
|
| 358 |
<motion.div
|
| 359 |
className="auth-branding"
|
| 360 |
initial={{ opacity: 0, x: -100 }}
|
|
|
|
| 434 |
</motion.div>
|
| 435 |
</div>
|
| 436 |
|
| 437 |
+
{ }
|
| 438 |
<div className="branding-decorations">
|
| 439 |
<motion.div
|
| 440 |
className="decoration gem-1"
|
|
|
|
| 504 |
</div>
|
| 505 |
</motion.div>
|
| 506 |
|
| 507 |
+
{ }
|
| 508 |
<motion.div
|
| 509 |
className="auth-form-container"
|
| 510 |
initial={{ opacity: 0, x: 100 }}
|
|
|
|
| 512 |
transition={{ duration: 0.8, delay: 0.2 }}
|
| 513 |
>
|
| 514 |
<div className="form-wrapper">
|
| 515 |
+
{ }
|
| 516 |
+
{ }
|
| 517 |
|
| 518 |
<motion.div
|
| 519 |
className="form-header"
|
|
|
|
| 530 |
</p>
|
| 531 |
</motion.div>
|
| 532 |
|
| 533 |
+
{ }
|
| 534 |
{currentStep === 1 && (
|
| 535 |
<motion.div
|
| 536 |
className="social-login"
|
|
|
|
| 582 |
</motion.div>
|
| 583 |
)}
|
| 584 |
|
| 585 |
+
{ }
|
| 586 |
<motion.form
|
| 587 |
className="auth-form multi-step-form"
|
| 588 |
onSubmit={
|
| 589 |
currentStep === totalSteps
|
| 590 |
? handleSubmit
|
| 591 |
: (e) => {
|
| 592 |
+
e.preventDefault();
|
| 593 |
+
handleNext();
|
| 594 |
+
}
|
| 595 |
}
|
| 596 |
initial={{ opacity: 0, y: 30 }}
|
| 597 |
animate={{ opacity: 1, y: 0 }}
|
|
|
|
| 601 |
}}
|
| 602 |
>
|
| 603 |
<AnimatePresence mode="wait">
|
| 604 |
+
{ }
|
| 605 |
{currentStep === 1 && (
|
| 606 |
<motion.div
|
| 607 |
key="step1"
|
|
|
|
| 749 |
)}
|
| 750 |
</button>
|
| 751 |
</div>
|
| 752 |
+
{ }
|
| 753 |
{formData.password && (
|
| 754 |
<motion.div
|
| 755 |
className="password-strength"
|
|
|
|
| 856 |
</motion.div>
|
| 857 |
)}
|
| 858 |
|
| 859 |
+
{ }
|
| 860 |
{currentStep === 2 && (
|
| 861 |
<motion.div
|
| 862 |
key="step2"
|
|
|
|
| 1067 |
)}
|
| 1068 |
</AnimatePresence>
|
| 1069 |
|
| 1070 |
+
{ }
|
| 1071 |
<div className="form-navigation">
|
| 1072 |
{currentStep > 1 && (
|
| 1073 |
<motion.button
|
|
|
|
| 1139 |
</div>
|
| 1140 |
</motion.form>
|
| 1141 |
|
| 1142 |
+
{ }
|
| 1143 |
<motion.div
|
| 1144 |
className="trust-indicators"
|
| 1145 |
initial={{ opacity: 0, y: 30 }}
|
frontend/src/pages/WishlistPage.jsx
CHANGED
|
@@ -100,13 +100,13 @@ export default function WishlistPage() {
|
|
| 100 |
|
| 101 |
useEffect(() => {
|
| 102 |
fetch(
|
| 103 |
-
`${process.env.REACT_APP_API_URL || "https://
|
| 104 |
)
|
| 105 |
.then((res) => res.json())
|
| 106 |
.then((data) => {
|
| 107 |
setAllCategories([...new Set(data.products.map((p) => p.category))]);
|
| 108 |
})
|
| 109 |
-
.catch(() => {});
|
| 110 |
}, [location]);
|
| 111 |
|
| 112 |
useEffect(() => {
|
|
@@ -203,7 +203,7 @@ export default function WishlistPage() {
|
|
| 203 |
let product = null;
|
| 204 |
try {
|
| 205 |
const response = await fetch(
|
| 206 |
-
`${process.env.REACT_APP_API_URL || "https://
|
| 207 |
);
|
| 208 |
const data = await response.json();
|
| 209 |
product = data.product;
|
|
@@ -387,11 +387,11 @@ export default function WishlistPage() {
|
|
| 387 |
const wishlistAvgRating =
|
| 388 |
Array.isArray(data?.wishlist) && data.wishlist.length > 0
|
| 389 |
? (
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
: "0.0";
|
| 396 |
|
| 397 |
const wishlistTotalPrice = (filteredAndSortedItems || []).reduce(
|
|
@@ -510,7 +510,7 @@ export default function WishlistPage() {
|
|
| 510 |
|
| 511 |
return (
|
| 512 |
<div className="Premium-wishlist-page">
|
| 513 |
-
{}
|
| 514 |
<div className="wishlist-cosmic-bg">
|
| 515 |
<div className="cosmic-particles">
|
| 516 |
{[...Array(30)].map((_, i) => (
|
|
@@ -563,7 +563,7 @@ export default function WishlistPage() {
|
|
| 563 |
</div>
|
| 564 |
|
| 565 |
<div className="container">
|
| 566 |
-
{}
|
| 567 |
<motion.div
|
| 568 |
className="wishlist-header"
|
| 569 |
initial={{ opacity: 0, y: -50 }}
|
|
@@ -629,7 +629,7 @@ export default function WishlistPage() {
|
|
| 629 |
{data?.wishlist.length} items saved for later
|
| 630 |
</div>
|
| 631 |
<div className="premium-wishlist-actions-row">
|
| 632 |
-
{}
|
| 633 |
{actions}
|
| 634 |
</div>
|
| 635 |
</div>
|
|
@@ -637,7 +637,7 @@ export default function WishlistPage() {
|
|
| 637 |
|
| 638 |
{data?.wishlist.length > 0 ? (
|
| 639 |
<>
|
| 640 |
-
{}
|
| 641 |
<motion.div
|
| 642 |
className="wishlist-controls"
|
| 643 |
initial={{ opacity: 0, y: 30 }}
|
|
@@ -791,7 +791,7 @@ export default function WishlistPage() {
|
|
| 791 |
</div>
|
| 792 |
</motion.div>
|
| 793 |
|
| 794 |
-
{}
|
| 795 |
<motion.div
|
| 796 |
className="wishlist-stats"
|
| 797 |
initial={{ opacity: 0, y: 30 }}
|
|
@@ -845,7 +845,7 @@ export default function WishlistPage() {
|
|
| 845 |
</div>
|
| 846 |
</motion.div>
|
| 847 |
|
| 848 |
-
{}
|
| 849 |
<motion.div
|
| 850 |
className={`wishlist-grid ${viewMode}`}
|
| 851 |
initial={{ opacity: 0 }}
|
|
@@ -865,7 +865,7 @@ export default function WishlistPage() {
|
|
| 865 |
whileHover={{ y: -10 }}
|
| 866 |
>
|
| 867 |
<div className="item-card glass-effect-strong">
|
| 868 |
-
{}
|
| 869 |
<div
|
| 870 |
className="wishlist-heart-icon"
|
| 871 |
style={{
|
|
@@ -882,7 +882,7 @@ export default function WishlistPage() {
|
|
| 882 |
style={{ filter: "drop-shadow(0 0 6px #ff4757aa)" }}
|
| 883 |
/>
|
| 884 |
</div>
|
| 885 |
-
{}
|
| 886 |
{item.stock <= 5 && item.stock > 0 && (
|
| 887 |
<div className="product-badge limited">
|
| 888 |
<Zap size={12} />
|
|
@@ -904,7 +904,7 @@ export default function WishlistPage() {
|
|
| 904 |
</div>
|
| 905 |
)}
|
| 906 |
|
| 907 |
-
{}
|
| 908 |
<div
|
| 909 |
className="item-image-container big-centered"
|
| 910 |
onClick={() => navigate(`/product/${item.productId}`)}
|
|
@@ -921,7 +921,7 @@ export default function WishlistPage() {
|
|
| 921 |
transition={{ duration: 0.3 }}
|
| 922 |
/>
|
| 923 |
|
| 924 |
-
{}
|
| 925 |
<div className="quick-actions">
|
| 926 |
<motion.button
|
| 927 |
className="quick-action-btn view"
|
|
@@ -952,7 +952,7 @@ export default function WishlistPage() {
|
|
| 952 |
<div className="image-overlay"></div>
|
| 953 |
</div>
|
| 954 |
|
| 955 |
-
{}
|
| 956 |
<div className="item-info">
|
| 957 |
<div className="item-category">{item.category}</div>
|
| 958 |
|
|
@@ -1089,7 +1089,7 @@ export default function WishlistPage() {
|
|
| 1089 |
</Link>
|
| 1090 |
</motion.div>
|
| 1091 |
|
| 1092 |
-
{}
|
| 1093 |
<div className="shopping-suggestions">
|
| 1094 |
{[Gift, Crown, Sparkles, Star, TrendingUp, Award].map(
|
| 1095 |
(Icon, index) => (
|
|
|
|
| 100 |
|
| 101 |
useEffect(() => {
|
| 102 |
fetch(
|
| 103 |
+
`${process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space"}/api/products`,
|
| 104 |
)
|
| 105 |
.then((res) => res.json())
|
| 106 |
.then((data) => {
|
| 107 |
setAllCategories([...new Set(data.products.map((p) => p.category))]);
|
| 108 |
})
|
| 109 |
+
.catch(() => { });
|
| 110 |
}, [location]);
|
| 111 |
|
| 112 |
useEffect(() => {
|
|
|
|
| 203 |
let product = null;
|
| 204 |
try {
|
| 205 |
const response = await fetch(
|
| 206 |
+
`${process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space"}/api/product/${productId}`,
|
| 207 |
);
|
| 208 |
const data = await response.json();
|
| 209 |
product = data.product;
|
|
|
|
| 387 |
const wishlistAvgRating =
|
| 388 |
Array.isArray(data?.wishlist) && data.wishlist.length > 0
|
| 389 |
? (
|
| 390 |
+
data.wishlist.reduce(
|
| 391 |
+
(total, item) => total + getAverageRating(item),
|
| 392 |
+
0,
|
| 393 |
+
) / data.wishlist.length
|
| 394 |
+
).toFixed(1)
|
| 395 |
: "0.0";
|
| 396 |
|
| 397 |
const wishlistTotalPrice = (filteredAndSortedItems || []).reduce(
|
|
|
|
| 510 |
|
| 511 |
return (
|
| 512 |
<div className="Premium-wishlist-page">
|
| 513 |
+
{ }
|
| 514 |
<div className="wishlist-cosmic-bg">
|
| 515 |
<div className="cosmic-particles">
|
| 516 |
{[...Array(30)].map((_, i) => (
|
|
|
|
| 563 |
</div>
|
| 564 |
|
| 565 |
<div className="container">
|
| 566 |
+
{ }
|
| 567 |
<motion.div
|
| 568 |
className="wishlist-header"
|
| 569 |
initial={{ opacity: 0, y: -50 }}
|
|
|
|
| 629 |
{data?.wishlist.length} items saved for later
|
| 630 |
</div>
|
| 631 |
<div className="premium-wishlist-actions-row">
|
| 632 |
+
{ }
|
| 633 |
{actions}
|
| 634 |
</div>
|
| 635 |
</div>
|
|
|
|
| 637 |
|
| 638 |
{data?.wishlist.length > 0 ? (
|
| 639 |
<>
|
| 640 |
+
{ }
|
| 641 |
<motion.div
|
| 642 |
className="wishlist-controls"
|
| 643 |
initial={{ opacity: 0, y: 30 }}
|
|
|
|
| 791 |
</div>
|
| 792 |
</motion.div>
|
| 793 |
|
| 794 |
+
{ }
|
| 795 |
<motion.div
|
| 796 |
className="wishlist-stats"
|
| 797 |
initial={{ opacity: 0, y: 30 }}
|
|
|
|
| 845 |
</div>
|
| 846 |
</motion.div>
|
| 847 |
|
| 848 |
+
{ }
|
| 849 |
<motion.div
|
| 850 |
className={`wishlist-grid ${viewMode}`}
|
| 851 |
initial={{ opacity: 0 }}
|
|
|
|
| 865 |
whileHover={{ y: -10 }}
|
| 866 |
>
|
| 867 |
<div className="item-card glass-effect-strong">
|
| 868 |
+
{ }
|
| 869 |
<div
|
| 870 |
className="wishlist-heart-icon"
|
| 871 |
style={{
|
|
|
|
| 882 |
style={{ filter: "drop-shadow(0 0 6px #ff4757aa)" }}
|
| 883 |
/>
|
| 884 |
</div>
|
| 885 |
+
{ }
|
| 886 |
{item.stock <= 5 && item.stock > 0 && (
|
| 887 |
<div className="product-badge limited">
|
| 888 |
<Zap size={12} />
|
|
|
|
| 904 |
</div>
|
| 905 |
)}
|
| 906 |
|
| 907 |
+
{ }
|
| 908 |
<div
|
| 909 |
className="item-image-container big-centered"
|
| 910 |
onClick={() => navigate(`/product/${item.productId}`)}
|
|
|
|
| 921 |
transition={{ duration: 0.3 }}
|
| 922 |
/>
|
| 923 |
|
| 924 |
+
{ }
|
| 925 |
<div className="quick-actions">
|
| 926 |
<motion.button
|
| 927 |
className="quick-action-btn view"
|
|
|
|
| 952 |
<div className="image-overlay"></div>
|
| 953 |
</div>
|
| 954 |
|
| 955 |
+
{ }
|
| 956 |
<div className="item-info">
|
| 957 |
<div className="item-category">{item.category}</div>
|
| 958 |
|
|
|
|
| 1089 |
</Link>
|
| 1090 |
</motion.div>
|
| 1091 |
|
| 1092 |
+
{ }
|
| 1093 |
<div className="shopping-suggestions">
|
| 1094 |
{[Gift, Crown, Sparkles, Star, TrendingUp, Award].map(
|
| 1095 |
(Icon, index) => (
|
frontend/src/store/slices/apiSlice.jsx
CHANGED
|
@@ -7,7 +7,7 @@ const getApiUrl = () => {
|
|
| 7 |
return "/api";
|
| 8 |
}
|
| 9 |
return (
|
| 10 |
-
(process.env.REACT_APP_API_URL || "https://
|
| 11 |
);
|
| 12 |
}
|
| 13 |
return "http://localhost:7860/api";
|
|
|
|
| 7 |
return "/api";
|
| 8 |
}
|
| 9 |
return (
|
| 10 |
+
(process.env.REACT_APP_API_URL || "https://kumar715-mkcart.hf.space") + "/api"
|
| 11 |
);
|
| 12 |
}
|
| 13 |
return "http://localhost:7860/api";
|