diff --git a/client/src/components/Navbar.tsx b/client/src/components/Navbar.tsx index a48cb35..78ca460 100644 --- a/client/src/components/Navbar.tsx +++ b/client/src/components/Navbar.tsx @@ -4,6 +4,7 @@ import { useLocation } from "react-router-dom"; import logo from "../assets/svg/logo.svg"; import tikka from "../assets/svg/Tikka.svg"; import WalletButton from "./WalletButton"; +import ThemeToggle from "./ThemeToggle"; import SignInButton from "./SignInButton"; import NotificationBellIcon from "./cards/NotificationBellIcon"; import { Search } from "lucide-react"; @@ -14,45 +15,45 @@ import { STELLAR_CONFIG } from "../config/stellar"; const Navbar = ({ onStart }: { onStart?: () => void }) => { const [open, setOpen] = React.useState(false); const { isConnected, isWrongNetwork, switchNetwork } = useWalletContext(); - + const location = useLocation(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const [searchValue, setSearchValue] = useState(searchParams.get("q") || ""); - useEffect(() => { - const delayDebounce = setTimeout(() => { - if (searchValue === "") { - if (location.pathname === "/search") { - navigate("/home"); + useEffect(() => { + const delayDebounce = setTimeout(() => { + if (searchValue === "") { + if (location.pathname === "/search") { + navigate("/home"); + } + return; } - return; - } - // Only search if we aren't on detail/create pages - const isForbiddenPage = - location.pathname === "/details" || - location.pathname.startsWith("/raffles/") || - location.pathname === "/create" || - location.pathname === "/leaderboard" || - location.pathname === "/my-raffles"; - if (searchValue.trim() && !isForbiddenPage) { - navigate(`/search?q=${encodeURIComponent(searchValue.trim())}`); - } - }, 400); + // Only search if we aren't on detail/create pages + const isForbiddenPage = + location.pathname === "/details" || + location.pathname.startsWith("/raffles/") || + location.pathname === "/create" || + location.pathname === "/leaderboard" || + location.pathname === "/my-raffles"; + if (searchValue.trim() && !isForbiddenPage) { + navigate(`/search?q=${encodeURIComponent(searchValue.trim())}`); + } + }, 400); + + return () => clearTimeout(delayDebounce); + }, [searchValue, navigate, location.pathname]); - return () => clearTimeout(delayDebounce); -}, [searchValue, navigate, location.pathname]); + useEffect(() => { + const searchRelatedPages = ["/home", "/search"]; + if (!searchRelatedPages.includes(location.pathname)) { + setSearchValue(""); // Clear the input field text + } + }, [location.pathname]); -useEffect(() => { - const searchRelatedPages = ["/home", "/search"]; - if (!searchRelatedPages.includes(location.pathname)) { - setSearchValue(""); // Clear the input field text - } -}, [location.pathname]); - const navItems = [ { label: "Discover Raffles", href: "/home" }, { label: "Create Raffle", href: "/create" }, @@ -64,13 +65,13 @@ useEffect(() => { const targetNetwork = STELLAR_CONFIG.network.charAt(0).toUpperCase() + STELLAR_CONFIG.network.slice(1); return ( -
+
{/* Mobile panel */}
{/* Mobile Search */} @@ -165,30 +171,37 @@ useEffect(() => { value={searchValue} onChange={(e) => setSearchValue(e.target.value)} placeholder="Search raffles..." - className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 text-white placeholder:text-white/40 focus:outline-none" + className="w-full bg-gray-200 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl px-4 py-3 text-gray-900 dark:text-white placeholder:text-gray-600 dark:text-white/40 focus:outline-none" />
- {navItems.map((item) => ( - setOpen(false)} - > - {item.label} - - ))} + {navItems.map((item) => { + const isActive = location.pathname === item.href; + return ( + setOpen(false)} + > + {item.label} + + ); + })} { setOpen(false); if (onStart) onStart(); }} - className="mt-2 rounded-xl px-6 py-3 text-center text-sm font-medium text-white hover:brightness-110 bg-[#FE3796] cursor-pointer" + className="mt-2 rounded-xl px-6 py-3 text-center text-sm font-medium text-gray-900 dark:text-white hover:brightness-110 bg-[#FE3796] cursor-pointer" > Get Started +
diff --git a/client/src/components/create-raffle/ImageStep.tsx b/client/src/components/create-raffle/ImageStep.tsx index ff75bf9..7afb9b3 100644 --- a/client/src/components/create-raffle/ImageStep.tsx +++ b/client/src/components/create-raffle/ImageStep.tsx @@ -284,8 +284,8 @@ const ImageStep: React.FC = ({ onClick={onNext} disabled={!canContinue} className={`px-6 py-3 rounded-lg font-medium transition-colors duration-200 ${canContinue - ? "bg-[#FF389C] hover:bg-[#FF389C]/90 text-gray-900 dark:text-white" - : "bg-gray-600 text-gray-400 cursor-not-allowed" + ? "bg-[#FF389C] hover:bg-[#FF389C]/90 text-gray-900 dark:text-white" + : "bg-gray-600 text-gray-400 cursor-not-allowed" }`} > Continue diff --git a/client/src/components/landing/TrendingRaffles.tsx b/client/src/components/landing/TrendingRaffles.tsx index 2e5fa19..7e61bee 100644 --- a/client/src/components/landing/TrendingRaffles.tsx +++ b/client/src/components/landing/TrendingRaffles.tsx @@ -53,7 +53,7 @@ const RaffleCardWrapper: React.FC<{ if (error || !raffle) { return ( -
+
handleRangeClick(range)} - className={`px-3 py-1 rounded text-sm font-medium transition-colors ${ - activeRange === range.label + className={`px-3 py-1 rounded text-sm font-medium transition-colors ${activeRange === range.label ? 'bg-indigo-600 text-gray-900 dark:text-white' : 'bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-600' - }`} + }`} > {range.label} diff --git a/client/src/pages/RafflePage.tsx b/client/src/pages/RafflePage.tsx index 2f0e9bb..c231bc7 100644 --- a/client/src/pages/RafflePage.tsx +++ b/client/src/pages/RafflePage.tsx @@ -249,7 +249,7 @@ const RafflePage = () => { {isActive ? (
-
- -
- )} - - {!isLoading && !error && ( -
- {results.map((raffle) => ( - - ))} -
- )} -
- ); -}; - -export default SearchPage; - +import React from "react"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { useSearch } from "../hooks/useSearch"; +import { mapListItemToCardProps } from "../services/raffleService"; +import RaffleCard from "../components/cards/RaffleCard"; +import RaffleCardSkeleton from "../components/ui/RaffleCardSkeleton"; +import ErrorMessage from "../components/ui/ErrorMessage"; +import { Breadcrumbs } from "../components/ui/Breadcrumbs"; + +const SearchPage: React.FC = () => { + const [searchParams] = useSearchParams(); + const query = searchParams.get("q") || ""; + const { results, isLoading, error } = useSearch(query); + const navigate = useNavigate(); + + return ( +
+
+ +
+ +

+ {query ? `Search results for "${query}"` : "Search Raffles"} +

+ + {isLoading && ( +
+ {[1, 2, 3].map((n) => ( + + ))} +
+ )} + + {error && !isLoading && ( + + )} + + {!isLoading && !error && results.length === 0 && query && ( +
+ {/* Animated Icon */} +
+
+
+ + + + + +
+
+ +

No raffles found

+

+ We couldn't find anything matching "{query}". + Try a different keyword or category. +

+ + +
+ )} + + {!isLoading && !error && ( +
+ {results.map((raffle) => ( + + ))} +
+ )} +
+ ); +}; + +export default SearchPage; +