diff --git a/src/components/Header/MainHeader.jsx b/src/components/Header/MainHeader.jsx index 178f1d6e..26df2452 100644 --- a/src/components/Header/MainHeader.jsx +++ b/src/components/Header/MainHeader.jsx @@ -9,163 +9,125 @@ import { User, ShoppingCart, } from 'lucide-react'; -import SearchBox from '../Search/SearchBox'; +import SearchBox from '../Search/SearchBox'; +import TopHeader from "../TopHeader/TopHeader"; export default function Header() { const [mobileOpen, setMobileOpen] = useState(false); const [shopOpen, setShopOpen] = useState(false); const [search, setSearch] = useState(false); - return ( -
-
-
- {/* Left: Logo */} -
- - CoreX Logo - -
- - {/* Center: Desktop Navigation */} - - - {/* Right: Icons (desktop) + Mobile Hamburger */} -
- {/* Desktop Icons */} -
- {/* search box logic */} - setSearch(!search)} - className="cursor-pointer "> - - {(search) && -
-
-
-

SEARCH

-
-
+ + + Garage Sale + + + All Products + + + About CoreX + + + + {/* Right Icons */} +
+
+ + + + + + + + + + + +
+ + {/* Mobile Hamburger */} +
+ + +
+
+
+
- {/* Mobile Hamburger */} -
+ {/* 🔍 Right Slide Search Drawer */} + {search && ( +
+ {/* Drawer */} +
+
+

SEARCH

+
+ +
-
- - {/* Mobile Menu */} - {mobileOpen && ( -
- -
)} - + ); -} \ No newline at end of file +} diff --git a/src/components/Search/SearchBox.jsx b/src/components/Search/SearchBox.jsx index 52cc1d27..ed5a6e69 100644 --- a/src/components/Search/SearchBox.jsx +++ b/src/components/Search/SearchBox.jsx @@ -1,89 +1,115 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from "react"; -export default function SearchBox(){ - const [searchQuery, setSearchQuery] = useState(''); +export default function SearchBox() { + const [searchQuery, setSearchQuery] = useState(""); + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); - // dummy product data - const products = [ - { - id: 1, - brand: 'CoreX', - name: '100% Whey Protein - Vanilla', - price: 84.99, - image: '/api/placeholder/60/60' - }, - { - id: 2, - brand: 'CoreX', - name: '100% Nova Whey - Vanilla Ice Cream', - price: 74.99, - image: '/api/placeholder/60/60' - }, - { - id: 3, - brand: 'CoreX', - name: '100% Nova Whey - Vanilla Ice Cream', - price: 74.99, - image: '/api/placeholder/60/60' - }, - { - id: 4, - brand: 'CoreX', - name: '100% Nova Whey - Vanilla Ice Cream', - price: 78.99, - image: '/api/placeholder/60/60' - }, - { - id: 5, - brand: 'CoreX', - name: '100% Nova Whey - Vanilla Ice Cream', - price: 73.99, - image: '/api/placeholder/60/60' - } - ]; + const API_URL = import.meta.env.VITE_API_URL; - const filteredProducts = products.filter(product => - product.name.toLowerCase().includes(searchQuery.toLowerCase()) || - product.brand.toLowerCase().includes(searchQuery.toLowerCase()) - ); + // Fetch matching products from backend after 3+ characters + useEffect(() => { + const fetchProducts = async () => { + if (searchQuery.length < 3) { + setProducts([]); + return; + } - return ( -
-
-
- setSearchQuery(e.target.value)} - placeholder="Search products..." - className="w-full px-4 py-3 pr-20 bg-[#89949f] border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" - /> - -
-
-
-

Products

-
+ setLoading(true); + setError(""); -
- {filteredProducts.map((product) => ( -
-
- Product_Image + try { + const response = await fetch(`${API_URL}/products?search=${searchQuery}`); + if (!response.ok) throw new Error("Failed to fetch products"); + + const data = await response.json(); + setProducts(data.products || data); // handle both {products: []} or [] + } catch { + setError("Something went wrong while fetching products."); + } finally { + setLoading(false); + } + }; + + const debounce = setTimeout(fetchProducts, 400); // debounce typing + return () => clearTimeout(debounce); + }, [searchQuery, API_URL]); + + return ( +
+ {/* Input */} +
+ setSearchQuery(e.target.value)} + placeholder="Search products..." + className="w-full px-4 py-3 pr-16 border border-gray-300 + rounded-md bg-gray-100 text-gray-800 placeholder-gray-500 + focus:outline-none focus:ring-2 focus:ring-blue-600" + /> + {searchQuery && ( + + )} +
+ + {/* Status */} + {loading &&

Searching...

} + {error &&

{error}

} + + {/* Product List */} + {!loading && !error && products.length > 0 && ( + <> +

PRODUCTS

+
+ +
+ {products.map((product) => ( +
+
+ {product.name}
-

{product.brand}

-

{product.name}

-

{product.price}

+

{product.brand}

+

+ {product.name} +

+

${product.price}

-
- ))} -
+
+ ))} +
+ +
+ +
+ + )} + + {/* Empty state */} + {!loading && searchQuery.length >= 3 && products.length === 0 && !error && ( +
+

+ No products found for "{searchQuery}" +

+

Check the spelling or use a different word or phrase.

- ) -} \ No newline at end of file + )} +
+ ); +} diff --git a/src/components/TopHeader/TopHeader.jsx b/src/components/TopHeader/TopHeader.jsx index afb44769..fa06346b 100644 --- a/src/components/TopHeader/TopHeader.jsx +++ b/src/components/TopHeader/TopHeader.jsx @@ -14,7 +14,7 @@ export default function TopHeader() { }, [messages.length]); return ( -
+
{/* Center Promo Message */}

diff --git a/src/layouts/RootLayout.jsx b/src/layouts/RootLayout.jsx index b379b5a8..f11f8703 100755 --- a/src/layouts/RootLayout.jsx +++ b/src/layouts/RootLayout.jsx @@ -5,12 +5,11 @@ import 'react-toastify/dist/ReactToastify.css'; import SEO from '../components/SEO'; import TopFooter from '../components/Footer'; import MainHeader from '../components/Header'; -import TopHeader from '../components/TopHeader'; + function RootLayout() { return ( <> -