-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #715 from IkkiOcean/agro-backend-route-1
[FEAT] Integrated Cart Backend with Cart Page, Category Page and Product Page
- Loading branch information
Showing
13 changed files
with
457 additions
and
204 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
const ExtendedUser = require('../model/shop/extendedUser'); | ||
|
||
// Add product to cart | ||
exports.addProductToCart = async (req, res) => { | ||
const { userId } = req.params; | ||
const { productId,variantId, quantity} = req.body; | ||
|
||
try { | ||
let user = await ExtendedUser.findOne({ _id: userId }); | ||
if (!user) { | ||
user = new ExtendedUser({ _id: userId }); | ||
} | ||
|
||
const existingItemIndex = user.cart.findIndex(item => item.variantId === variantId); | ||
if (existingItemIndex !== -1) { | ||
user.cart[existingItemIndex].quantity += quantity; | ||
} else { | ||
user.cart.push({ productId,variantId, quantity }); | ||
} | ||
|
||
await user.save(); | ||
res.status(200).json({ message: 'Product added to cart', cart: user.cart }); | ||
} catch (error) { | ||
res.status(500).json({ error: 'Failed to add product to cart' }); | ||
} | ||
}; | ||
|
||
// Get user's cart | ||
exports.getUserCart = async (req, res) => { | ||
const { userId } = req.params; | ||
|
||
try { | ||
// Fetch the user and populate the cart with variant and product data | ||
const user = await ExtendedUser.findById(userId) | ||
.populate({ | ||
path: 'cart', // Populate the cart | ||
populate: [ | ||
{ | ||
path: 'variantId', // Populate the variant inside each cart item | ||
model: 'Variant', // Replace 'Variant' with the actual model name for variants | ||
}, | ||
{ | ||
path: 'productId', // Populate the productId inside each cart item | ||
model: 'Product', // Replace 'Product' with the actual model name for products | ||
}, | ||
], | ||
}); | ||
|
||
// Check if user exists | ||
if (!user) return res.status(404).json({ error: 'User not found' }); | ||
|
||
// Return the cart directly | ||
res.status(200).json({ cart: user.cart }); | ||
} catch (error) { | ||
console.error(error); // Log the error for debugging | ||
res.status(500).json({ error: 'Failed to fetch cart' }); | ||
} | ||
}; | ||
|
||
|
||
|
||
// Update cart item quantity | ||
exports.updateCartItemQuantity = async (req, res) => { | ||
const { userId } = req.params; | ||
const { productId, variantId,quantity } = req.body; | ||
|
||
try { | ||
const user = await ExtendedUser.findById(userId); | ||
if (!user) return res.status(404).json({ error: 'User not found' }); | ||
|
||
const item = user.cart.find(item => item.variantId === variantId); | ||
if (!item) return res.status(404).json({ error: 'Product not found in cart' }); | ||
|
||
item.quantity = quantity; | ||
await user.save(); | ||
|
||
res.status(200).json({ message: 'Cart updated successfully', cart: user.cart }); | ||
} catch (error) { | ||
res.status(500).json({ error: 'Failed to update cart' }); | ||
} | ||
}; | ||
|
||
// Remove product from cart | ||
exports.removeProductFromCart = async (req, res) => { | ||
const { userId } = req.params; | ||
const { productId, variantId } = req.body; | ||
|
||
try { | ||
const user = await ExtendedUser.findById(userId); | ||
if (!user) return res.status(404).json({ error: 'User not found' }); | ||
|
||
user.cart = user.cart.filter(item => item.variantId !== variantId); | ||
await user.save(); | ||
|
||
res.status(200).json({ message: 'Product removed from cart', cart: user.cart }); | ||
} catch (error) { | ||
res.status(500).json({ error: 'Failed to remove product from cart' }); | ||
} | ||
}; | ||
|
||
// Clear user's cart | ||
exports.clearUserCart = async (req, res) => { | ||
const { userId } = req.params; | ||
|
||
try { | ||
const user = await ExtendedUser.findById(userId); | ||
if (!user) return res.status(404).json({ error: 'User not found' }); | ||
|
||
user.cart = []; | ||
await user.save(); | ||
|
||
res.status(200).json({ message: 'Cart cleared successfully' }); | ||
} catch (error) { | ||
res.status(500).json({ error: 'Failed to clear cart' }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
REACT_APP_MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoiYW5hbmRoYSIsImEiOiJjbTIwN29haWEwYzVrMmpzZ25yeTF4MmN4In0.3fHnwKMxxXNy9pM-Vcn9gw' | ||
VITE_BACKEND_BASE_URL = https://agrotech-ai-11j3.onrender.com/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons'; | ||
|
||
const CartItem = ({ index, image, title, description,size, type,color, qty, price, originalPrice, updateQuantity, deleteItem }) => ( | ||
<div className="flex justify-between items-start mb-4 border-b border-gray-200 pb-4"> | ||
<img alt={title} className="w-24 h-24" src={image} /> | ||
<div className="flex-1 ml-4"> | ||
<h2 className="font-bold">{title}</h2> | ||
<p>{description}</p> | ||
|
||
<p>SIZE: {size} {type ? "Kg" : "L"}</p> | ||
<p>COLOR: {color}</p> | ||
<p>QTY: | ||
<button onClick={() => updateQuantity(index, Math.max(1, qty - 1))} className="text-red-500 mx-2">-</button> | ||
<span className="mx-2">{qty}</span> | ||
<button onClick={() => updateQuantity(index, qty + 1)} className="text-green-500 mx-2">+</button> | ||
|
||
</p> | ||
<div className="flex space-x-4 text-gray-500"> | ||
<button onClick={() => deleteItem(index)} className="hover:text-red-500"> | ||
<FontAwesomeIcon icon={faTrashAlt} /> {/* Trash Can Icon */} | ||
</button> | ||
</div> | ||
</div> | ||
<div className="flex flex-col items-end text-right w-24"> {/* Width set for alignment */} | ||
{originalPrice && ( | ||
<p className="line-through text-gray-400">₹{originalPrice.toFixed(2)}</p> | ||
)} | ||
<p className="font-bold">₹{price.toFixed(2)}</p> | ||
</div> | ||
<div className="flex flex-col items-end text-right w-24"> {/* Width set for alignment */} | ||
<p className="font-bold">₹{(price * qty).toFixed(2)}</p> {/* Calculate total */} | ||
</div> | ||
</div> | ||
); | ||
|
||
const PromoCodeInput = () => ( | ||
<div className="mb-4"> | ||
<label className="block text-gray-500 mb-2" htmlFor="promo-code"> | ||
Do you have a promo code? | ||
</label> | ||
<div className="flex flex-wrap"> | ||
<input | ||
className="border border-gray-300 p-2 flex-1 min-w-0" // Added 'min-w-0' to prevent overflow | ||
id="promo-code" | ||
placeholder="Enter code" | ||
type="text" | ||
/> | ||
<button className="bg-black text-white p-2 ml-2"> | ||
APPLY | ||
</button> | ||
</div> | ||
</div> | ||
); | ||
|
||
const OrderSummary = ({ subtotal }) => ( | ||
<div className="border-t border-gray-200 pt-4"> | ||
<div className="flex justify-between mb-2"> | ||
<span>SUBTOTAL</span> | ||
<span className="font-bold">₹{subtotal.toFixed(2)}</span> | ||
</div> | ||
<div className="flex justify-between mb-2"> | ||
<span>Shipping</span> | ||
<span className="text-gray-500">TBD</span> | ||
</div> | ||
<div className="flex justify-between mb-4"> | ||
<span> | ||
Sales Tax | ||
<i className="fas fa-info-circle"></i> | ||
</span> | ||
<span className="text-gray-500">TBD</span> | ||
</div> | ||
<div className="flex justify-between mb-4"> | ||
<span className="font-bold">ESTIMATED TOTAL</span> | ||
<span className="font-bold">₹{subtotal.toFixed(2)}</span> {/* You can calculate the total here as well */} | ||
</div> | ||
<button className="bg-black text-white w-full py-2">CHECKOUT</button> | ||
<p className="text-gray-500 text-sm mt-4">Need help? Call us at 1-877-707-6272</p> | ||
</div> | ||
); | ||
|
||
export {CartItem, OrderSummary, PromoCodeInput}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import React from 'react'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
const LoginPrompt = () => { | ||
const navigate = useNavigate(); | ||
|
||
const handleRedirect = () => { | ||
navigate('/login'); // Adjust the path as per your routing setup | ||
}; | ||
|
||
return ( | ||
<div className="bg-gray-800 font-sans min-h-screen flex flex-col items-center justify-center"> | ||
<p className="text-green-500 text-2xl font-semibold mb-4"> | ||
Please log in to view your cart. | ||
</p> | ||
<button | ||
onClick={handleRedirect} | ||
className="bg-green-500 hover:bg-green-600 text-white py-2 px-6 rounded-lg transition duration-300" | ||
> | ||
Go to Login | ||
</button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default LoginPrompt; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.