Skip to content
Merged
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
175 changes: 94 additions & 81 deletions client/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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" },
Expand All @@ -64,13 +65,13 @@ useEffect(() => {
const targetNetwork = STELLAR_CONFIG.network.charAt(0).toUpperCase() + STELLAR_CONFIG.network.slice(1);

return (
<header className="w-full fixed-top z-50 bg-[#0B0F1C]/40 backdrop-blur-md">
<header className="w-full fixed-top z-50 bg-white/40 dark:bg-[#0B0F1C]/40 backdrop-blur-md transition-colors duration-300">
<nav className="mx-auto flex max-w-7xl items-center justify-between px-6 py-4 md:px-8">
{/* Left: brand */}
<div className="flex items-center gap-8">
<Link to="/" className="flex items-center gap-3">
<img src={logo} alt="logo" className="h-7 w-auto" />
<img src={tikka} alt="tikka" className="h-5 w-auto mt-1" />
<img src={logo} alt="logo" className="h-7 w-auto invert dark:invert-0" />
<img src={tikka} alt="tikka" className="h-5 w-auto mt-1 invert dark:invert-0" />
</Link>

{/* Desktop Search Bar - Integrated into Brand area */}
Expand All @@ -81,28 +82,34 @@ 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-2 text-sm text-white placeholder:text-white/40 focus:outline-none focus:ring-1 focus:ring-[#FE3796] transition-all"
className="w-full bg-gray-200 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl px-4 py-2 text-sm text-gray-900 dark:text-white placeholder:text-gray-600 dark:text-white/40 focus:outline-none focus:ring-1 focus:ring-[#FE3796] transition-all"
/>
<Search
<Search
size={18}
className="absolute right-4 top-1/2 -translate-y-1/2 text-white"
className="absolute right-4 top-1/2 -translate-y-1/2 text-gray-900 dark:text-white"
/>
</div>

</div>
</div>

{/* Desktop nav */}
<div className="hidden items-center gap-2 lg:flex">
{navItems.map((item) => (
<Link
key={item.label}
to={item.href}
className="px-4 py-2 text-sm text-white/80 hover:text-white transition"
>
{item.label}
</Link>
))}
{navItems.map((item) => {
const isActive = location.pathname === item.href;
return (
<Link
key={item.label}
to={item.href}
className={`px-4 py-2 text-sm text-gray-600 dark:transition ${isActive
? "text-white font-semibold"
: "text-white/80 hover:text-gray-900 dark:text-white"
}`}
>
{item.label}
</Link>
);
})}

{isConnected && (
<div className="flex items-center gap-2 mr-2">
Expand All @@ -123,39 +130,38 @@ useEffect(() => {
</div>
)}

<div className="flex items-center gap-4">

<WalletButton />

</div>

<NotificationBellIcon raffleId={0} onAuthRequired={() => { /* optionally open sign-in drawer */ }} />
<ThemeToggle />
<WalletButton />
<SignInButton />
</div>

{/* Mobile: hamburger */}
<button
type="button"
onClick={() => setOpen((s: boolean) => !s)}
className="lg:hidden inline-flex items-center justify-center rounded-lg p-2 hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-white/40 text-white"
>
{!open ? (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
) : (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M6 6l12 12M18 6l-12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
)}
</button>
<div className="flex gap-4">
<button
type="button"
aria-label={open ? "Close navigation menu" : "Open navigation menu"}
onClick={() => setOpen((s: boolean) => !s)}
className="lg:hidden inline-flex items-center justify-center rounded-lg p-2 hover:bg-gray-200 dark:bg-white/5 focus:outline-none focus:ring-2 focus:ring-white/40 text-gray-900 dark:text-white"
>
{!open ? (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
) : (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M6 6l12 12M18 6l-12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
)}
</button>
</div>

</nav>

{/* Mobile panel */}
<div
className={`lg:hidden overflow-hidden transition-[max-height,opacity] duration-300 bg-[#0B0F1C] ${
open ? "max-h-screen opacity-100" : "max-h-0 opacity-0"
}`}
data-testid="mobile-nav-panel"
className={`lg:hidden overflow-hidden transition-[max-height,opacity,background-color] duration-300 bg-gray-50 dark:bg-[#0B0F1C] ${open ? "max-h-screen opacity-100" : "max-h-0 opacity-0"
}`}
>
<div className="mx-auto flex max-w-7xl flex-col gap-1 px-6 pb-4 md:px-8">
{/* Mobile Search */}
Expand All @@ -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"
/>
</div>

{navItems.map((item) => (
<Link
key={item.label}
to={item.href}
className="rounded-lg px-3 py-3 text-sm text-white/90 hover:bg-white/5"
onClick={() => setOpen(false)}
>
{item.label}
</Link>
))}
{navItems.map((item) => {
const isActive = location.pathname === item.href;
return (
<Link
key={item.label}
to={item.href}
className={`rounded-lg px-3 py-3 text-sm transition ${isActive
? "text-white font-semibold bg-white/10"
: "text-gray-600 dark:text-white/90 hover:bg-gray-200 dark:bg-white/5"
}`}
onClick={() => setOpen(false)}
>
{item.label}
</Link>
);
})}

<a
onClick={() => {
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
</a>
<ThemeToggle />
</div>
</div>
</header>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/create-raffle/ImageStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ const ImageStep: React.FC<StepComponentProps> = ({
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
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/landing/TrendingRaffles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const RaffleCardWrapper: React.FC<{

if (error || !raffle) {
return (
<div className="w-full bg-[#11172E] p-4 rounded-3xl">
<div className="w-full bg-white dark:bg-[#11172E] p-4 rounded-3xl">
<ErrorMessage
variant="inline"
title={`Error loading raffle #${raffleId}`}
Expand Down
5 changes: 2 additions & 3 deletions client/src/components/monitor/LatencyGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ export default function LatencyGraph({ latencyData, onRangeChange }: LatencyGrap
<button
key={range.label}
onClick={() => 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}
</button>
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/RafflePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ const RafflePage = () => {
{isActive ? (
<div className="space-y-4">
<div className="flex items-center justify-between bg-black/20 p-1.5 rounded-xl border border-gray-200 dark:border-white/5">
<button
<button
onClick={handleDecrement}
className="w-10 h-10 rounded-lg flex items-center justify-center bg-gray-200 dark:bg-white/5 hover:bg-gray-300 dark:bg-white/10 text-gray-900 dark:text-white transition-colors"
>
Expand All @@ -264,7 +264,7 @@ const RafflePage = () => {
</button>
</div>

<button
<button
className="w-full py-4 rounded-xl font-black text-gray-900 dark:text-white tracking-wider shadow-lg shadow-[#FE3796]/20 hover:scale-[1.02] active:scale-[0.98] transition-all"
style={{
background: "linear-gradient(100.92deg, #FE3796 13.57%, #3931F9 97.65%)"
Expand Down
Loading