Build a Finance SaaS Platform -4 (Navigation Bar)

Install Sheet

1
npx shadcn-ui@latest add sheet

Install react-use

1
npm i react-use

Edit Navigate Component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"use client"

import React, { useState } from 'react'
import { usePathname,useRouter } from 'next/navigation';
import { useMedia } from 'react-use';
import { Menu } from 'lucide-react';

import NavButton from './nav-buttion';
import { Button } from './ui/button';

import {
Sheet,
SheetContent,
SheetTrigger,
} from "@/components/ui/sheet"

const routes = [
{
href: '/',
label: 'Overview',
},
{
href: '/transactions',
label: 'Transactions',
},
{
href: '/accounts',
label: 'Accounts',
},
{
href: '/categories',
label: 'Categories',
},
{
href: '/settings',
label: 'Settings',
},
]

export default function Navigation() {
const [isOpen, setIsOpen] = useState(false);

const pathName = usePathname();
const router = useRouter();
const isMobile = useMedia("(max-width:1024px)",false);

const onClick = (href: string) => {
router.push(href);
setIsOpen(false);
};

if (isMobile){
return (
<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetTrigger>
<Button
variant="outline"
size="sm"
className='font-normal bg-white/10 hover:bg-white/20 hover:text-white border-none focus-visible:ring-offset-0 focus-visible:ring-transparent outline-none-none text-white focus:bg-white/30 transition'
>
<Menu className='size-4' />
</Button>
</SheetTrigger>
<SheetContent side='left' className='px-2'>
<nav className='flex flex-col gap-y-2 pt-6'>
{routes.map((route)=>(
<Button
key={route.href}
variant={route.href === pathName ? "secondary" : "ghost"}
onClick={()=> onClick(route.href)}
className='w-full justify-start'
>
{route.label}
</Button>
))}
</nav>
</SheetContent>
</Sheet>
)
}

return (
<nav className='hidden lg:flex items-center gap-x-2 overflow-x-auto'>
{ routes.map((route)=>(
<NavButton
key= {route.href}
href={route.href}
label={route.label}
isActive={pathName === route.href}
/>
))}
</nav>
)
}

Add UserButton

Modify components/header.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import React from 'react'
import { ClerkLoaded, ClerkLoading, UserButton } from '@clerk/nextjs'
import { Loader2 } from 'lucide-react'

import HeaderLogo from './header-logo'
import Navigation from './navigation'
import WelcomeMsg from './welcome-msg'

export default function Header() {
return (
<div className='bg-gradient-to-b from-blue-700 to-blue-500 px-4 py-8 lg:px-14 pb-36'>
<div className='max-w-screen-2xl mx-auto'>
<div className='w-full flex items-center justify-between mb-14'>
<div className='flex items-center lg:gap-x-16'>
<HeaderLogo />
<Navigation />
</div>
<ClerkLoaded>
<UserButton />
</ClerkLoaded>
<ClerkLoading>
<Loader2 className='size-8 animate-spin text-slate-400' />
</ClerkLoading>
</div>
<WelcomeMsg />
</div>
</div>
)
}

Add WelcomeMsg

Add components/welcome-msg.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"use client"

import React from 'react'
import { useUser } from "@clerk/nextjs"

export default function WelcomeMsg() {
const { user, isLoaded } = useUser();
return (
<div className='space-y-2 mb-4'>
<h2 className='text-2xl lg:text-4xl text-white font-medium'>
Welcome Back{isLoaded ? ", " : " "}{user?.firstName} 🖐🏻
</h2>
<p className='text-sm lg:textbase text-[#89b6fd]'>
This is your Financial Overview Report
</p>
</div>
)
}

请我喝杯咖啡吧~

支付宝
微信