From 310148397595a4d4615d7bf7e1febfdaa7a638bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:14:52 +0000 Subject: [PATCH 1/2] Initial plan From f0740cb6700507a2b189e03c598fbdf35d2c0d08 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:24:48 +0000 Subject: [PATCH 2/2] Implement shopping cart feature (CartContext, Cart page, nav badge) Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com> --- frontend/src/App.tsx | 7 +- frontend/src/components/Cart.tsx | 164 ++++++++++++++++++ frontend/src/components/Navigation.tsx | 27 +++ .../components/entity/product/Products.tsx | 18 +- frontend/src/context/CartContext.tsx | 83 +++++++++ 5 files changed, 295 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/Cart.tsx create mode 100644 frontend/src/context/CartContext.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 29b9f53..ca7f856 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,8 +5,10 @@ import About from './components/About'; import Footer from './components/Footer'; import Products from './components/entity/product/Products'; import Login from './components/Login'; +import Cart from './components/Cart'; import { AuthProvider } from './context/AuthContext'; import { ThemeProvider } from './context/ThemeContext'; +import { CartProvider } from './context/CartContext'; import AdminProducts from './components/admin/AdminProducts'; import { useTheme } from './context/ThemeContext'; @@ -25,6 +27,7 @@ function ThemedApp() { } /> } /> } /> + } /> } /> } /> @@ -39,7 +42,9 @@ function App() { return ( - + + + ); diff --git a/frontend/src/components/Cart.tsx b/frontend/src/components/Cart.tsx new file mode 100644 index 0000000..c2af8cd --- /dev/null +++ b/frontend/src/components/Cart.tsx @@ -0,0 +1,164 @@ +import { Link } from 'react-router-dom'; +import { useCart, CartItem } from '../context/CartContext'; +import { useTheme } from '../context/ThemeContext'; + +export default function Cart() { + const { items, removeItem, updateQuantity, clearCart, totalPrice } = useCart(); + const { darkMode } = useTheme(); + + return ( +
+
+
+

+ Shopping Cart +

+ {items.length > 0 && ( + + )} +
+ + {items.length === 0 ? ( +
+ + + +

+ Your cart is empty +

+ + Browse Products + +
+ ) : ( +
+ {items.map((item: CartItem) => { + const effectivePrice = item.price * (1 - (item.discount ?? 0)); + return ( +
+ {item.name} +
+

+ {item.name} +

+

+ ${effectivePrice.toFixed(2)}{' '} + + / {item.unit} + +

+
+
+ + + {item.quantity} + + +
+

+ ${(effectivePrice * item.quantity).toFixed(2)} +

+ +
+ ); + })} + +
+
+

+ Total: ${totalPrice.toFixed(2)} +

+ +
+
+
+ )} +
+
+ ); +} diff --git a/frontend/src/components/Navigation.tsx b/frontend/src/components/Navigation.tsx index 5f35e12..82a36c2 100644 --- a/frontend/src/components/Navigation.tsx +++ b/frontend/src/components/Navigation.tsx @@ -1,11 +1,13 @@ import { Link } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; import { useTheme } from '../context/ThemeContext'; +import { useCart } from '../context/CartContext'; import { useState } from 'react'; export default function Navigation() { const { isLoggedIn, isAdmin, logout } = useAuth(); const { darkMode, toggleTheme } = useTheme(); + const { totalItems } = useCart(); const [adminMenuOpen, setAdminMenuOpen] = useState(false); return ( @@ -85,6 +87,31 @@ export default function Navigation() {
+ + + + + {totalItems > 0 && ( + + {totalItems > 99 ? '99+' : totalItems} + + )} +