Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,276 changes: 717 additions & 559 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"gh-pages": "^6.1.1",
"vite": "^5.2.0"
"vite": "^7.2.4"
}
}
11 changes: 6 additions & 5 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,25 @@
.divider {
width: 50px;
height: 2px;
background-color: #4caf50;
background-color: #1E90FF;
margin: 10px 0;
}

.get-started-button {
padding: 15px 25px;
font-size: 23px;
border: none;
border-radius: 5px;
background-color: #4caf50;
border-radius: 8px;
background-color: #1E90FF;
color: white;
cursor: pointer;
transition: background-color 0.3s ease;
transition: background-color 0.2s ease, transform 0.08s ease;
margin-top: 40px;
}

.get-started-button:hover {
background-color: #45a049;
background-color: #187bcd;
transform: translateY(-1px);
}

/* ProductList.css */
Expand Down
45 changes: 27 additions & 18 deletions src/CartItem.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@

.cart-item {
display: flex;
border-bottom: 1px solid #ccc;
padding: 10px 0;
border-bottom: 1px solid #eee;
padding: 12px;
background-color: white;
width: 500px;
width: 100%;
gap: 30px;
border-radius: 10px;
box-shadow: 0 6px 14px rgba(32,33,36,0.06);
}

.cart-item-image {
width: 200px;
height: 200px;
/* object-fit: contain; */
margin-right: 20px;
border-radius: 8px;
object-fit: cover;
}

.cart-item-details {
Expand All @@ -39,14 +43,14 @@
}

.cart-item-button {
background-color: #f0f0f0;
border: 1px solid lightgrey;
background-color: #f7f9fb;
border: 1px solid #e6eaf0;
color: #333;
font-size: 18px;
cursor: pointer;
padding: 5px 10px;
padding: 6px 12px;
margin: 0 5px;
border-radius: 5px;
border-radius: 8px;
}

.cart-item-quantity-value {
Expand All @@ -60,7 +64,7 @@
}

.cart-item-delete {
background-color: #ff6961;
background-color: #ff6b6b;
border: none;
color: #fff;
font-size: 14px;
Expand All @@ -71,7 +75,7 @@
}

.cart-item-delete:hover {
background-color: #cc0000;
background-color: #e04444;
}
/* .cart-item-button-dec{
background-color: red;
Expand Down Expand Up @@ -230,14 +234,19 @@
}

.get-started-button1 {
padding: 15px 75px;
font-size: 23px;
border: none;
border-radius: 5px;
background-color: #4caf50;
color: white;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 40px;
padding: 12px 48px;
font-size: 18px;
border: none;
border-radius: 10px;
background-color: #1E90FF; /* match accent */
color: white;
cursor: pointer;
transition: background-color 0.2s ease, transform 0.08s ease;
margin-top: 24px;
}

.get-started-button1:hover {
background-color: #187bcd;
transform: translateY(-1px);
}

53 changes: 46 additions & 7 deletions src/CartItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,77 @@ import { useSelector, useDispatch } from 'react-redux';
import { removeItem, updateQuantity } from './CartSlice';
import './CartItem.css';

const CartItem = ({ onContinueShopping }) => {
const CartItem = ({ onContinueShopping, onCheckout }) => {
const cart = useSelector(state => state.cart.items);
const dispatch = useDispatch();

// Calculate total amount for all products in the cart
const calculateTotalAmount = () => {

const total = cart.reduce((sum, it) => {
const price = parseFloat(String(it.cost).replace(/[^0-9.]/g, '')) || 0;
const qty = it.quantity || 1;
return sum + price * qty;
}, 0);
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(total);
};

const handleContinueShopping = (e) => {

e.preventDefault();
if (onContinueShopping) onContinueShopping();
};

const handleCheckoutShopping = (e) => {
e.preventDefault();
if (onCheckout) onCheckout();
else alert('Functionality to be added for future reference');
};



const handleIncrement = (item) => {
const newQty = (item.quantity || 1) + 1;
dispatch(updateQuantity({ name: item.name, quantity: newQty }));
};

const handleDecrement = (item) => {

const currentQty = item.quantity || 1;
if (currentQty > 1) {
dispatch(updateQuantity({ name: item.name, quantity: currentQty - 1 }));
} else {
// If quantity would go below 1, remove the item
dispatch(removeItem(item.name));
}
};

const handleRemove = (item) => {
dispatch(removeItem(item.name));
};

// Calculate total cost based on quantity for an item
const calculateTotalCost = (item) => {
const price = parseFloat(String(item.cost).replace(/[^0-9.]/g, '')) || 0;
const qty = item.quantity || 1;
const total = price * qty;
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(total);
};

const isEmpty = !cart || cart.length === 0;

if (isEmpty) {
return (
<div className="cart-container">
<h2 style={{ color: 'black' }}>Your cart is empty</h2>
<p>Looks like you haven't added any plants yet.</p>
<div className="continue_shopping_btn">
<button className="get-started-button" onClick={(e) => handleContinueShopping(e)}>Continue Shopping</button>
</div>
</div>
);
}

return (
<div className="cart-container">
<h2 style={{ color: 'black' }}>Total Cart Amount: ${calculateTotalAmount()}</h2>
<h2 style={{ color: 'black' }}>Total Cart Amount: {calculateTotalAmount()}</h2>
<div>
{cart.map(item => (
<div className="cart-item" key={item.name}>
Expand All @@ -47,7 +86,7 @@ const CartItem = ({ onContinueShopping }) => {
<span className="cart-item-quantity-value">{item.quantity}</span>
<button className="cart-item-button cart-item-button-inc" onClick={() => handleIncrement(item)}>+</button>
</div>
<div className="cart-item-total">Total: ${calculateTotalCost(item)}</div>
<div className="cart-item-total">Total: {calculateTotalCost(item)}</div>
<button className="cart-item-delete" onClick={() => handleRemove(item)}>Delete</button>
</div>
</div>
Expand All @@ -57,7 +96,7 @@ const CartItem = ({ onContinueShopping }) => {
<div className="continue_shopping_btn">
<button className="get-started-button" onClick={(e) => handleContinueShopping(e)}>Continue Shopping</button>
<br />
<button className="get-started-button1">Checkout</button>
<button className="get-started-button1" onClick={(e) => handleCheckoutShopping(e)}>Checkout</button>
</div>
</div>
);
Expand Down
19 changes: 16 additions & 3 deletions src/CartSlice.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,26 @@ export const CartSlice = createSlice({
},
reducers: {
addItem: (state, action) => {

const item = action.payload;
const index = state.items.findIndex((i) => i.name === item.name);
if (index >= 0) {
// Increment quantity if already present
state.items[index].quantity = (state.items[index].quantity || 1) + (item.quantity || 1);
} else {
// Add new item
state.items.push(item);
}
},
removeItem: (state, action) => {
const name = action.payload.name || action.payload;
state.items = state.items.filter((i) => i.name !== name);
},
updateQuantity: (state, action) => {


const { name, quantity } = action.payload;
const index = state.items.findIndex((i) => i.name === name);
if (index >= 0) {
state.items[index].quantity = quantity;
}
},
},
});
Expand Down
56 changes: 56 additions & 0 deletions src/Checkout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { useSelector } from 'react-redux';
import './ProductList.css';

const Checkout = ({ onBack }) => {
const cart = useSelector((s) => s.cart.items || []);

const total = cart.reduce((sum, it) => {
const price = parseFloat(String(it.cost).replace(/[^0-9.]/g, '')) || 0;
const qty = it.quantity || 1;
return sum + price * qty;
}, 0);

const formattedTotal = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(total);

const handleExternalCheckout = () => {
// Open a dummy (placeholder) checkout page in a new tab
window.open('https://example.com/one-shopping', '_blank', 'noopener');
};

return (
<div className="product-grid" style={{ padding: 40 }}>
<div style={{ maxWidth: 900, width: '100%', background: '#fff', padding: 24, borderRadius: 12, boxShadow: '0 8px 24px rgba(0,0,0,0.06)' }}>
<h2>Checkout (Demo)</h2>
{cart.length === 0 ? (
<p>Your cart is empty.</p>
) : (
<div>
<ul style={{ listStyle: 'none', padding: 0 }}>
{cart.map((it) => (
<li key={it.name} style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0', borderBottom: '1px solid #f0f0f0' }}>
<div>
<strong>{it.name}</strong>
<div style={{ fontSize: 13, color: '#666' }}>{it.quantity} × {it.cost}</div>
</div>
<div>{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format((parseFloat(String(it.cost).replace(/[^0-9.]/g, '')) || 0) * (it.quantity || 1))}</div>
</li>
))}
</ul>
<div style={{ marginTop: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<strong>Total:</strong>
<strong>{formattedTotal}</strong>
</div>
</div>
)}

<div style={{ marginTop: 24, display: 'flex', gap: 12 }}>
<button className="product-button" onClick={onBack}>Back to Cart</button>
<button className="product-button" onClick={handleExternalCheckout}>Proceed to Dummy Shop</button>
</div>
</div>
</div>
);
};

export default Checkout;
Loading