From 102807def3289ceaad936ba6cef4a0ed645a4e49 Mon Sep 17 00:00:00 2001
From: "ALMAZROUEI Shamma (2021) WKIS203"
 <shamma.almazrouei.2021@live.rhul.ac.uk>
Date: Tue, 11 Mar 2025 20:36:08 +0530
Subject: [PATCH] Build the cart page

---
 golden-crust-bakery/src/main.jsx           |   5 +
 golden-crust-bakery/src/pages/About.jsx    |   2 +-
 golden-crust-bakery/src/pages/Cart.jsx     | 243 +++++++++++++++++++++
 golden-crust-bakery/src/pages/Landing.jsx  |   2 +-
 golden-crust-bakery/src/pages/MenuItem.jsx |   2 +-
 5 files changed, 251 insertions(+), 3 deletions(-)
 create mode 100644 golden-crust-bakery/src/pages/Cart.jsx

diff --git a/golden-crust-bakery/src/main.jsx b/golden-crust-bakery/src/main.jsx
index bb357ce..f7c36cc 100644
--- a/golden-crust-bakery/src/main.jsx
+++ b/golden-crust-bakery/src/main.jsx
@@ -16,6 +16,7 @@ import Register from './pages/Register';
 import Menu from './pages/Menu';
 import MenuItem from './pages/MenuItem';
 import ErrorPage from './pages/Error';
+import Cart from './pages/Cart';
 
 const router = createBrowserRouter([
   {
@@ -43,6 +44,10 @@ const router = createBrowserRouter([
         path: '/register',
         element: <Register />,
       },
+      {
+        path: '/cart',
+        element: <Cart />,
+      },
       {
         path: '/menu',
         element: <Menu />,
diff --git a/golden-crust-bakery/src/pages/About.jsx b/golden-crust-bakery/src/pages/About.jsx
index 0038ef1..b9e7c50 100644
--- a/golden-crust-bakery/src/pages/About.jsx
+++ b/golden-crust-bakery/src/pages/About.jsx
@@ -66,7 +66,7 @@ export default function About() {
               Get in Touch <ArrowRight className='ml-2 h-4 w-4' />
             </Button>
           </div>
-          <div className='relative h-[300px] md:h-[400px] rounded-2xl overflow-hidden shadow-xl order-1 md:order-2'>
+          <div className='relative h-[300px] md:h-[400px] rounded-2xl overflow-hidden shadow-md order-1 md:order-2'>
             <img
               src='https://images.unsplash.com/photo-1572054466274-25b4ed6d6899?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'
               alt='Our bakery team'
diff --git a/golden-crust-bakery/src/pages/Cart.jsx b/golden-crust-bakery/src/pages/Cart.jsx
new file mode 100644
index 0000000..f289032
--- /dev/null
+++ b/golden-crust-bakery/src/pages/Cart.jsx
@@ -0,0 +1,243 @@
+import { useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { toast } from 'sonner';
+import { Minus, Plus, ShoppingCart, Trash2 } from 'lucide-react';
+
+import { useCartStore } from '@/lib/store';
+import { useAuthStore } from '@/lib/authStore';
+
+import { Button } from '@/components/ui/button';
+
+export default function Cart() {
+  const navigate = useNavigate();
+  const { cart, removeFromCart, updateQuantity, clearCart, initializeCart } =
+    useCartStore();
+  const { isAuthenticated } = useAuthStore();
+
+  useEffect(() => {
+    initializeCart();
+
+    // Redirect to login if not authenticated
+    if (!isAuthenticated) {
+      toast.error('Authentication required!', {
+        description: 'Please sign in to view your cart.',
+      });
+      navigate('/login');
+    }
+  }, [initializeCart, isAuthenticated, navigate]);
+
+  // If not authenticated, don't render the cart content
+  if (!isAuthenticated) {
+    return null;
+  }
+
+  const totalItems = cart.reduce((total, item) => total + item.quantity, 0);
+  const subtotal = cart.reduce(
+    (total, item) => total + item.price * item.quantity,
+    0
+  );
+  const tax = subtotal * 0.08; // 8% tax
+  const total = subtotal + tax;
+
+  const handleQuantityChange = (id, newQuantity) => {
+    if (newQuantity < 1) return;
+    updateQuantity(id, newQuantity);
+  };
+
+  const handleRemoveItem = (id, name) => {
+    removeFromCart(id);
+    toast.success('Item removed', {
+      description: `${name} has been removed from your cart.`,
+    });
+  };
+
+  const handleCheckout = () => {
+    if (cart.length === 0) {
+      toast.error('Cart is empty!', {
+        description: 'Please add items to your cart before checking out.',
+      });
+      return;
+    }
+    navigate('/checkout');
+  };
+
+  return (
+    <div className='container mx-auto px-4 py-8 md:py-12'>
+      <div className='text-center mb-8'>
+        <h1 className='text-4xl font-bold text-gray-800 mb-4'>
+          Your Shopping Cart
+        </h1>
+        <p className='text-gray-600'>
+          {totalItems > 0
+            ? `You have ${totalItems} item${
+                totalItems !== 1 ? 's' : ''
+              } in your cart`
+            : 'Your cart is empty'}
+        </p>
+      </div>
+
+      {cart.length > 0 ? (
+        <div className='grid grid-cols-1 lg:grid-cols-3 gap-8'>
+          <div className='lg:col-span-2'>
+            <div className='bg-white rounded-xl shadow-sm border overflow-hidden'>
+              <div className='p-6'>
+                <div className='flow-root'>
+                  <ul className='divide-y divide-gray-200'>
+                    {cart.map((item) => (
+                      <li key={item.id} className='py-6 flex'>
+                        <div className='relative h-24 w-24 rounded-md overflow-hidden'>
+                          <img
+                            src={item.image}
+                            alt={item.name}
+                            className='object-cover h-full w-full'
+                          />
+                        </div>
+                        <div className='ml-4 flex-1 flex flex-col'>
+                          <div>
+                            <div className='flex justify-between text-base font-medium text-gray-900'>
+                              <h3>{item.name}</h3>
+                              <p className='ml-4'>
+                                ${(item.price * item.quantity).toFixed(2)}
+                              </p>
+                            </div>
+                            <p className='mt-1 text-sm text-gray-500 line-clamp-2'>
+                              {item.description}
+                            </p>
+                          </div>
+                          <div className='flex-1 flex items-end justify-between text-sm'>
+                            <div className='flex items-center space-x-2'>
+                              <Button
+                                variant='outline'
+                                size='icon'
+                                className='h-8 w-8 rounded-full'
+                                onClick={() =>
+                                  handleQuantityChange(
+                                    item.id,
+                                    item.quantity - 1
+                                  )
+                                }
+                              >
+                                <Minus className='h-4 w-4' />
+                              </Button>
+                              <span className='text-gray-700 w-8 text-center'>
+                                {item.quantity}
+                              </span>
+                              <Button
+                                variant='outline'
+                                size='icon'
+                                className='h-8 w-8 rounded-full'
+                                onClick={() =>
+                                  handleQuantityChange(
+                                    item.id,
+                                    item.quantity + 1
+                                  )
+                                }
+                              >
+                                <Plus className='h-4 w-4' />
+                              </Button>
+                            </div>
+                            <Button
+                              variant='ghost'
+                              className='text-red-500 hover:text-red-700 hover:bg-red-50'
+                              onClick={() =>
+                                handleRemoveItem(item.id, item.name)
+                              }
+                            >
+                              <Trash2 className='h-5 w-5' />
+                            </Button>
+                          </div>
+                        </div>
+                      </li>
+                    ))}
+                  </ul>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <div className='lg:col-span-1'>
+            <div className='bg-white rounded-xl shadow-sm border overflow-hidden'>
+              <div className='p-6'>
+                <h2 className='text-lg font-semibold text-gray-900 mb-4'>
+                  Order Summary
+                </h2>
+                <div className='flow-root'>
+                  <div className='border-t border-gray-200 pt-4'>
+                    <div className='flex justify-between py-2'>
+                      <dt className='text-sm text-gray-600'>Subtotal</dt>
+                      <dd className='text-sm font-medium text-gray-900'>
+                        ${subtotal.toFixed(2)}
+                      </dd>
+                    </div>
+                    <div className='flex justify-between py-2'>
+                      <dt className='text-sm text-gray-600'>Tax (8%)</dt>
+                      <dd className='text-sm font-medium text-gray-900'>
+                        ${tax.toFixed(2)}
+                      </dd>
+                    </div>
+                    <div className='flex justify-between py-2 border-t border-gray-200'>
+                      <dt className='text-base font-medium text-gray-900'>
+                        Total
+                      </dt>
+                      <dd className='text-base font-medium text-pink-600'>
+                        ${total.toFixed(2)}
+                      </dd>
+                    </div>
+                  </div>
+                </div>
+                <div className='mt-6'>
+                  <Button
+                    onClick={handleCheckout}
+                    className='w-full bg-pink-500 hover:bg-pink-600 text-white rounded-full py-6'
+                  >
+                    Proceed to Checkout
+                  </Button>
+                  <Button
+                    variant='outline'
+                    onClick={() => navigate('/menu')}
+                    className='w-full mt-4 border-pink-300 text-pink-600 hover:bg-pink-50 rounded-full'
+                  >
+                    Continue Shopping
+                  </Button>
+                  {cart.length > 0 && (
+                    <Button
+                      variant='ghost'
+                      onClick={() => {
+                        clearCart();
+                        toast.success('Cart cleared!', {
+                          description:
+                            'All items have been removed from your cart.',
+                        });
+                      }}
+                      className='w-full mt-2 text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded-full'
+                    >
+                      Clear Cart
+                    </Button>
+                  )}
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      ) : (
+        <div className='text-center py-12'>
+          <div className='mx-auto w-24 h-24 bg-pink-100 rounded-full flex items-center justify-center mb-6'>
+            <ShoppingCart className='h-12 w-12 text-pink-500' />
+          </div>
+          <h2 className='text-2xl font-semibold text-gray-800 mb-4'>
+            Your cart is empty
+          </h2>
+          <p className='text-gray-600 mb-8'>
+            Looks like you haven't added any cakes to your cart yet.
+          </p>
+          <Button
+            onClick={() => navigate('/menu')}
+            className='bg-pink-500 hover:bg-pink-600 text-white rounded-full px-8 py-6 text-lg'
+          >
+            Browse Our Menu
+          </Button>
+        </div>
+      )}
+    </div>
+  );
+}
diff --git a/golden-crust-bakery/src/pages/Landing.jsx b/golden-crust-bakery/src/pages/Landing.jsx
index 6d91362..14e248c 100644
--- a/golden-crust-bakery/src/pages/Landing.jsx
+++ b/golden-crust-bakery/src/pages/Landing.jsx
@@ -95,7 +95,7 @@ export default function Landing() {
                   </Button>
                 </div>
               </div>
-              <div className='relative h-[300px] md:h-[400px] rounded-2xl overflow-hidden shadow-xl'>
+              <div className='relative h-[300px] md:h-[400px] rounded-2xl overflow-hidden'>
                 <img
                   src='https://images.pexels.com/photos/2536967/pexels-photo-2536967.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2'
                   alt='Delicious cake showcase'
diff --git a/golden-crust-bakery/src/pages/MenuItem.jsx b/golden-crust-bakery/src/pages/MenuItem.jsx
index cf670b1..84d2e84 100644
--- a/golden-crust-bakery/src/pages/MenuItem.jsx
+++ b/golden-crust-bakery/src/pages/MenuItem.jsx
@@ -92,7 +92,7 @@ export default function MenuItem() {
       </Button>
 
       <div className='grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-16 mb-12'>
-        <div className='relative h-[300px] md:h-[500px] rounded-2xl overflow-hidden shadow-xl'>
+        <div className='relative h-[300px] md:h-[500px] rounded-2xl overflow-hidden'>
           <img
             src={cake.image}
             alt={cake.name}
-- 
GitLab