Skip to content

Commit a781497

Browse files
authored
Merge pull request #170 from MeshJS/layout-fix
Improve sidebar navigation with resources and home section
2 parents d46752f + b56e80b commit a781497

File tree

6 files changed

+327
-162
lines changed

6 files changed

+327
-162
lines changed

src/components/common/overall-layout/layout.tsx

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import { api } from "@/utils/api";
88
import useUser from "@/hooks/useUser";
99
import { useUserStore } from "@/lib/zustand/user";
1010
import useAppWallet from "@/hooks/useAppWallet";
11+
import useMultisigWallet from "@/hooks/useMultisigWallet";
1112

1213
import SessionProvider from "@/components/SessionProvider";
1314
import { getServerSession } from "next-auth";
1415

15-
// import MenuWallets from "@/components/common/overall-layout/menus/wallets";
16+
import MenuWallets from "@/components/common/overall-layout/menus/wallets";
1617
import MenuWallet from "@/components/common/overall-layout/menus/multisig-wallet";
18+
import WalletSelector from "@/components/common/overall-layout/wallet-selector";
1719
import {
1820
WalletDataLoaderWrapper,
1921
DialogReportWrapper,
@@ -69,6 +71,7 @@ export default function RootLayout({
6971
const { user, isLoading } = useUser();
7072
const router = useRouter();
7173
const { appWallet } = useAppWallet();
74+
const { multisigWallet } = useMultisigWallet();
7275
const { generateNsec } = useNostrChat();
7376

7477
const userAddress = useUserStore((state) => state.userAddress);
@@ -164,6 +167,43 @@ export default function RootLayout({
164167
const walletPageNames = walletPageRoute ? walletPageRoute.split("/") : [];
165168
const pageIsPublic = publicRoutes.includes(router.pathname);
166169
const isLoggedIn = !!user;
170+
const isHomepage = router.pathname === "/";
171+
172+
// Keep track of the last visited wallet to show wallet menu even on other pages
173+
const [lastVisitedWalletId, setLastVisitedWalletId] = React.useState<string | null>(null);
174+
const [lastVisitedWalletName, setLastVisitedWalletName] = React.useState<string | null>(null);
175+
const [lastWalletStakingEnabled, setLastWalletStakingEnabled] = React.useState<boolean | null>(null);
176+
177+
React.useEffect(() => {
178+
const walletId = router.query.wallet as string | undefined;
179+
if (walletId && isWalletPath && appWallet && multisigWallet) {
180+
setLastVisitedWalletId(walletId);
181+
setLastVisitedWalletName(appWallet.name);
182+
// Check if staking is enabled for this wallet
183+
try {
184+
const stakingEnabled = multisigWallet.stakingEnabled();
185+
setLastWalletStakingEnabled(stakingEnabled);
186+
} catch (error) {
187+
// Don't update state on error - keep the last known value
188+
console.error("Error checking staking status:", error);
189+
}
190+
}
191+
}, [router.query.wallet, isWalletPath, appWallet, multisigWallet]);
192+
193+
const clearWalletContext = React.useCallback(() => {
194+
setLastVisitedWalletId(null);
195+
setLastVisitedWalletName(null);
196+
setLastWalletStakingEnabled(null);
197+
}, []);
198+
199+
// Clear wallet context when navigating to homepage
200+
React.useEffect(() => {
201+
if (isHomepage && lastVisitedWalletId) {
202+
clearWalletContext();
203+
}
204+
}, [isHomepage, lastVisitedWalletId, clearWalletContext]);
205+
206+
const showWalletMenu = isLoggedIn && (isWalletPath || !!lastVisitedWalletId);
167207

168208
return (
169209
<div className="flex h-screen w-screen flex-col overflow-hidden">
@@ -175,11 +215,21 @@ export default function RootLayout({
175215
data-header="main"
176216
>
177217
<div className="flex h-14 items-center gap-4 lg:h-16">
178-
{/* Mobile menu button - only in wallet context */}
179-
{isWalletPath && <MobileNavigation isWalletPath={isWalletPath} />}
218+
{/* Mobile menu button - hidden only on public homepage (not logged in) */}
219+
{(isLoggedIn || !isHomepage) && (
220+
<MobileNavigation
221+
showWalletMenu={showWalletMenu}
222+
isLoggedIn={isLoggedIn}
223+
walletId={router.query.wallet as string || lastVisitedWalletId || undefined}
224+
fallbackWalletName={lastVisitedWalletName}
225+
onClearWallet={clearWalletContext}
226+
stakingEnabled={lastWalletStakingEnabled ?? undefined}
227+
isWalletPath={isWalletPath}
228+
/>
229+
)}
180230

181231
{/* Logo - in fixed-width container matching sidebar width */}
182-
<div className={`flex items-center md:w-[260px] lg:w-[280px] ${isWalletPath ? 'flex-1 justify-center md:flex-none md:justify-start' : ''}`}>
232+
<div className={`flex items-center md:w-[260px] lg:w-[280px] ${(isLoggedIn || !isHomepage) ? 'flex-1 justify-center md:flex-none md:justify-start' : ''}`}>
183233
<Link
184234
href="/"
185235
className="flex items-center gap-2 rounded-md px-4 py-2 text-sm transition-all duration-200 hover:bg-gray-100/50 dark:hover:bg-white/5 md:px-4"
@@ -218,13 +268,57 @@ export default function RootLayout({
218268
</header>
219269

220270
{/* Content area with sidebar + main */}
221-
<div className={`flex flex-1 overflow-hidden ${isWalletPath ? '' : ''}`}>
222-
{/* Sidebar for larger screens - only in wallet context */}
223-
{isWalletPath && (
271+
<div className={`flex flex-1 overflow-hidden`}>
272+
{/* Sidebar for larger screens - hidden only on public homepage (not logged in) */}
273+
{(isLoggedIn || !isHomepage) && (
224274
<aside className="hidden w-[260px] border-r border-gray-300/50 bg-muted/40 dark:border-white/[0.03] md:block lg:w-[280px]">
225275
<div className="flex h-full max-h-screen flex-col">
226-
<nav className="flex-1 pt-2">
227-
<MenuWallet />
276+
<nav className="flex-1 pt-2 overflow-y-auto">
277+
<div className="flex flex-col">
278+
{/* 1. Home Link - only when NOT logged in */}
279+
{!isLoggedIn && (
280+
<div className="px-2 lg:px-4">
281+
<div className="space-y-1">
282+
<Link
283+
href="/"
284+
className={`flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm transition-all duration-200 hover:bg-gray-100/50 dark:hover:bg-white/5 ${
285+
router.pathname === "/"
286+
? "text-white"
287+
: "text-muted-foreground hover:text-foreground"
288+
}`}
289+
>
290+
<svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
291+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
292+
</svg>
293+
<span>Home</span>
294+
</Link>
295+
</div>
296+
</div>
297+
)}
298+
299+
{/* 2. Wallet Selector - only when logged in */}
300+
{isLoggedIn && (
301+
<WalletSelector
302+
fallbackWalletName={lastVisitedWalletName}
303+
onClearWallet={clearWalletContext}
304+
/>
305+
)}
306+
307+
{/* 3. Wallet Menu - shown when wallet is selected */}
308+
{showWalletMenu && (
309+
<div className="mt-4">
310+
<MenuWallet
311+
walletId={router.query.wallet as string || lastVisitedWalletId || undefined}
312+
stakingEnabled={isWalletPath ? undefined : (lastWalletStakingEnabled ?? undefined)}
313+
/>
314+
</div>
315+
)}
316+
317+
{/* 4. Resources Menu - always visible */}
318+
<div className="mt-4">
319+
<MenuWallets />
320+
</div>
321+
</div>
228322
</nav>
229323
<div className="mt-auto p-4" />
230324
</div>
Lines changed: 28 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,37 @@
1-
import { Banknote, Info, List, Landmark, UserRoundPen, ChartNoAxesColumnIncreasing, FileCode2, ArrowLeft, ChevronDown, ChevronUp, Wallet2, Plus } from "lucide-react";
1+
import { Banknote, Info, List, Landmark, UserRoundPen, ChartNoAxesColumnIncreasing, FileCode2 } from "lucide-react";
22
import { useRouter } from "next/router";
3-
import { useState, useEffect } from "react";
43
import MenuLink from "./menu-link";
54
import usePendingTransactions from "@/hooks/usePendingTransactions";
6-
import useUserWallets from "@/hooks/useUserWallets";
75
import { Badge } from "@/components/ui/badge";
86
import { ChatBubbleIcon } from "@radix-ui/react-icons";
97
import usePendingSignables from "@/hooks/usePendingSignables";
108
import useMultisigWallet from "@/hooks/useMultisigWallet";
11-
import useAppWallet from "@/hooks/useAppWallet";
12-
import WalletNavLink from "@/components/common/overall-layout/wallet-nav-link";
13-
import {
14-
DropdownMenu,
15-
DropdownMenuContent,
16-
DropdownMenuItem,
17-
DropdownMenuSeparator,
18-
DropdownMenuTrigger,
19-
} from "@/components/ui/dropdown-menu";
209

21-
export default function MenuWallet() {
10+
interface MenuWalletProps {
11+
walletId?: string;
12+
stakingEnabled?: boolean;
13+
}
14+
15+
export default function MenuWallet({ walletId, stakingEnabled }: MenuWalletProps) {
2216
const router = useRouter();
23-
const baseUrl = `/wallets/${router.query.wallet as string | undefined}/`;
24-
const { wallets } = useUserWallets();
25-
const { appWallet } = useAppWallet();
17+
const effectiveWalletId = walletId || (router.query.wallet as string | undefined);
18+
const baseUrl = `/wallets/${effectiveWalletId}/`;
2619
const { transactions } = usePendingTransactions();
2720
const { signables } = usePendingSignables();
2821
const { multisigWallet } = useMultisigWallet();
29-
const [open, setOpen] = useState(false);
30-
31-
// Close dropdown on route change
32-
useEffect(() => {
33-
const handleRouteChange = () => {
34-
setOpen(false);
35-
};
36-
router.events.on("routeChangeStart", handleRouteChange);
37-
return () => {
38-
router.events.off("routeChangeStart", handleRouteChange);
39-
};
40-
}, [router.events]);
4122

42-
if (!wallets) return;
23+
// Use fallback staking enabled if provided, otherwise check multisigWallet
24+
const showStaking = stakingEnabled !== undefined
25+
? stakingEnabled
26+
: (multisigWallet ? multisigWallet.stakingEnabled() : false);
4327

4428
return (
45-
<nav className="grid h-full items-start px-2 font-medium lg:px-4">
29+
<div className="grid items-start px-2 font-medium lg:px-4">
4630
<div className="grid items-start space-y-1">
47-
{/* Wallet Selector */}
48-
<div className="mt-1 mb-1">
49-
<DropdownMenu open={open} onOpenChange={setOpen}>
50-
<DropdownMenuTrigger asChild>
51-
<button type="button" className="flex w-full max-w-[244px] lg:max-w-[248px] items-center gap-3 rounded-md px-3 py-2 text-sm transition-all duration-200 bg-white dark:bg-zinc-900 border border-zinc-300/40 dark:border-white/10 text-muted-foreground hover:bg-zinc-100 dark:hover:bg-zinc-800 hover:text-foreground">
52-
<Wallet2 className="h-5 w-5 flex-shrink-0" />
53-
<span className="truncate">{appWallet?.name || "Select Wallet"}</span>
54-
{open ? (
55-
<ChevronUp className="h-5 w-5 flex-shrink-0 ml-auto" />
56-
) : (
57-
<ChevronDown className="h-5 w-5 flex-shrink-0 ml-auto" />
58-
)}
59-
</button>
60-
</DropdownMenuTrigger>
61-
<DropdownMenuContent align="start" className="w-[var(--radix-dropdown-menu-trigger-width)]">
62-
{wallets
63-
.filter((wallet) => !wallet.isArchived)
64-
.sort((a, b) => a.name.localeCompare(b.name))
65-
.map((wallet) => (
66-
<DropdownMenuItem asChild key={wallet.id}>
67-
<WalletNavLink wallet={wallet} />
68-
</DropdownMenuItem>
69-
))}
70-
<DropdownMenuSeparator />
71-
<DropdownMenuItem asChild>
72-
<button
73-
type="button"
74-
onClick={() => {
75-
setOpen(false);
76-
void router.push("/wallets/new-wallet-flow/save");
77-
}}
78-
className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-muted-foreground transition-all duration-200 hover:bg-zinc-100 dark:hover:bg-zinc-800 hover:text-foreground cursor-pointer"
79-
>
80-
<Plus className="h-5 w-5 flex-shrink-0" />
81-
<span>New Wallet</span>
82-
</button>
83-
</DropdownMenuItem>
84-
</DropdownMenuContent>
85-
</DropdownMenu>
86-
</div>
87-
88-
{/* Menu Items */}
31+
{/* Wallet Items */}
8932
<div className="mt-1 pt-1 space-y-1">
9033
<div className="px-3 py-1 text-xs font-medium text-muted-foreground">
91-
Menu
34+
Wallet
9235
</div>
9336
<MenuLink
9437
href={`${baseUrl}`}
@@ -138,15 +81,17 @@ export default function MenuWallet() {
13881
</Badge>
13982
)}
14083
</MenuLink>
141-
{multisigWallet && multisigWallet.stakingEnabled() && <MenuLink
142-
href={`${baseUrl}staking`}
143-
className={
144-
router.pathname == "/wallets/[wallet]/staking" ? "text-white" : ""
145-
}
146-
>
147-
<ChartNoAxesColumnIncreasing className="h-5 w-5" />
148-
Staking
149-
</MenuLink>}
84+
{showStaking && (
85+
<MenuLink
86+
href={`${baseUrl}staking`}
87+
className={
88+
router.pathname == "/wallets/[wallet]/staking" ? "text-white" : ""
89+
}
90+
>
91+
<ChartNoAxesColumnIncreasing className="h-5 w-5" />
92+
Staking
93+
</MenuLink>
94+
)}
15095
<MenuLink
15196
href={`${baseUrl}assets`}
15297
className={
@@ -175,15 +120,7 @@ export default function MenuWallet() {
175120
Dapps
176121
</MenuLink>
177122
</div>
178-
179-
{/* Back to All Wallets */}
180-
<div className="mt-2 border-t border-gray-300/50 dark:border-white/[0.03] pt-1">
181-
<MenuLink href={`/`}>
182-
<ArrowLeft className="h-5 w-5" />
183-
All Wallets
184-
</MenuLink>
185-
</div>
186123
</div>
187-
</nav>
124+
</div>
188125
);
189126
}

0 commit comments

Comments
 (0)