|
1 | | -import React from 'react' |
2 | | -import { Link, useLocation } from '@tanstack/react-router' |
| 1 | +import { Link, useNavigate } from '@tanstack/react-router' |
3 | 2 | import { Button } from '@/components/ui/button' |
4 | | -import { ArrowLeft, Home, User, LogOut } from 'lucide-react' |
| 3 | +import { CheckCircle, LogOut, User } from 'lucide-react' |
5 | 4 | import { useAuthStore } from '@/stores/authStore' |
6 | | -import { useLogout } from '@/hooks/useAuth' |
7 | 5 |
|
8 | 6 | interface NavigationProps { |
9 | | - showBackButton?: boolean |
10 | 7 | title?: string |
11 | | - transparent?: boolean |
12 | 8 | } |
13 | 9 |
|
14 | | -export function Navigation({ showBackButton = false, title, transparent = false }: NavigationProps) { |
15 | | - const location = useLocation() |
16 | | - const { isAuthenticated, user } = useAuthStore() |
17 | | - const logoutMutation = useLogout() |
18 | | - |
19 | | - const isActive = (path: string) => { |
20 | | - return location.pathname === path |
21 | | - } |
| 10 | +export function Navigation({ title = 'TanStack Todo' }: NavigationProps) { |
| 11 | + const { user, logout } = useAuthStore() |
| 12 | + const navigate = useNavigate() |
22 | 13 |
|
23 | 14 | const handleLogout = () => { |
24 | | - logoutMutation.mutate() |
| 15 | + logout() |
| 16 | + navigate({ to: '/login' }) |
25 | 17 | } |
26 | 18 |
|
27 | 19 | return ( |
28 | | - <nav className={`${transparent ? 'bg-white/95 backdrop-blur-sm' : 'bg-white'} shadow-sm border-b sticky top-0 z-50`}> |
29 | | - <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
30 | | - <div className="flex justify-between items-center h-16"> |
31 | | - <div className="flex items-center"> |
32 | | - {showBackButton && ( |
33 | | - <Link to="/" className="mr-4"> |
34 | | - <Button variant="ghost" size="sm"> |
35 | | - <ArrowLeft className="w-4 h-4 mr-2" /> |
36 | | - Back |
37 | | - </Button> |
38 | | - </Link> |
39 | | - )} |
40 | | - <div className="flex items-center"> |
41 | | - <div className="flex-shrink-0"> |
42 | | - <div className="w-8 h-8 bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg flex items-center justify-center"> |
43 | | - <span className="text-white font-bold text-sm">MS</span> |
44 | | - </div> |
45 | | - </div> |
46 | | - <div className="ml-3"> |
47 | | - <h1 className="text-xl font-semibold text-gray-900"> |
48 | | - {title || 'MERN Stack'} |
49 | | - </h1> |
50 | | - </div> |
51 | | - </div> |
52 | | - </div> |
53 | | - |
54 | | - <div className="hidden md:block"> |
55 | | - <div className="ml-10 flex items-baseline space-x-4"> |
56 | | - <Link |
57 | | - to="/" |
58 | | - className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${ |
59 | | - isActive('/') |
60 | | - ? 'text-blue-600 bg-blue-50' |
61 | | - : 'text-gray-600 hover:text-blue-600' |
62 | | - }`} |
63 | | - > |
64 | | - <Home className="w-4 h-4 inline mr-1" /> |
65 | | - Home |
66 | | - </Link> |
67 | | - <Link |
68 | | - to="/todo" |
69 | | - className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${ |
70 | | - isActive('/todo') |
71 | | - ? 'text-blue-600 bg-blue-50' |
72 | | - : 'text-gray-600 hover:text-blue-600' |
73 | | - }`} |
74 | | - > |
75 | | - Todo |
76 | | - </Link> |
77 | | - <Link |
78 | | - to="/chat" |
79 | | - className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${ |
80 | | - isActive('/chat') |
81 | | - ? 'text-blue-600 bg-blue-50' |
82 | | - : 'text-gray-600 hover:text-blue-600' |
83 | | - }`} |
84 | | - > |
85 | | - Chat |
86 | | - </Link> |
87 | | - <Link |
88 | | - to="/profile" |
89 | | - className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${ |
90 | | - isActive('/profile') |
91 | | - ? 'text-blue-600 bg-blue-50' |
92 | | - : 'text-gray-600 hover:text-blue-600' |
93 | | - }`} |
94 | | - > |
95 | | - Profile |
96 | | - </Link> |
| 20 | + <nav className="bg-white border-b border-gray-200 px-4 py-3"> |
| 21 | + <div className="max-w-2xl mx-auto flex items-center justify-between"> |
| 22 | + <Link to="/" className="flex items-center gap-2 font-semibold text-gray-900 hover:text-indigo-600 transition-colors"> |
| 23 | + <CheckCircle className="w-5 h-5 text-indigo-600" /> |
| 24 | + {title} |
| 25 | + </Link> |
| 26 | + {user && ( |
| 27 | + <div className="flex items-center gap-3"> |
| 28 | + <div className="flex items-center gap-2 text-sm text-gray-600"> |
| 29 | + <User className="w-4 h-4" /> |
| 30 | + <span>{user.name}</span> |
97 | 31 | </div> |
| 32 | + <Button variant="ghost" size="sm" onClick={handleLogout}> |
| 33 | + <LogOut className="w-4 h-4 mr-1" /> |
| 34 | + Logout |
| 35 | + </Button> |
98 | 36 | </div> |
99 | | - |
100 | | - <div className="flex items-center space-x-4"> |
101 | | - {isAuthenticated ? ( |
102 | | - <div className="flex items-center space-x-3"> |
103 | | - <span className="text-sm text-gray-600"> |
104 | | - Welcome, {user?.name} |
105 | | - </span> |
106 | | - <Link to="/profile"> |
107 | | - <Button variant="outline" size="sm"> |
108 | | - <User className="w-4 h-4 mr-2" /> |
109 | | - Profile |
110 | | - </Button> |
111 | | - </Link> |
112 | | - <Button |
113 | | - variant="outline" |
114 | | - size="sm" |
115 | | - onClick={handleLogout} |
116 | | - disabled={logoutMutation.isPending} |
117 | | - > |
118 | | - <LogOut className="w-4 h-4 mr-2" /> |
119 | | - {logoutMutation.isPending ? 'Signing Out...' : 'Sign Out'} |
120 | | - </Button> |
121 | | - </div> |
122 | | - ) : ( |
123 | | - <> |
124 | | - <Link to="/login" search={{ redirect: '/' }}> |
125 | | - <Button variant="outline" size="sm"> |
126 | | - Sign In |
127 | | - </Button> |
128 | | - </Link> |
129 | | - <Link to="/register"> |
130 | | - <Button size="sm"> |
131 | | - Get Started |
132 | | - </Button> |
133 | | - </Link> |
134 | | - </> |
135 | | - )} |
136 | | - </div> |
137 | | - </div> |
138 | | - </div> |
139 | | - |
140 | | - {/* Mobile menu */} |
141 | | - <div className="md:hidden"> |
142 | | - <div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t"> |
143 | | - <Link |
144 | | - to="/" |
145 | | - className={`block px-3 py-2 rounded-md text-base font-medium transition-colors ${ |
146 | | - isActive('/') |
147 | | - ? 'text-blue-600 bg-blue-50' |
148 | | - : 'text-gray-600 hover:text-blue-600' |
149 | | - }`} |
150 | | - > |
151 | | - Home |
152 | | - </Link> |
153 | | - <Link |
154 | | - to="/todo" |
155 | | - className={`block px-3 py-2 rounded-md text-base font-medium transition-colors ${ |
156 | | - isActive('/todo') |
157 | | - ? 'text-blue-600 bg-blue-50' |
158 | | - : 'text-gray-600 hover:text-blue-600' |
159 | | - }`} |
160 | | - > |
161 | | - Todo |
162 | | - </Link> |
163 | | - <Link |
164 | | - to="/chat" |
165 | | - className={`block px-3 py-2 rounded-md text-base font-medium transition-colors ${ |
166 | | - isActive('/chat') |
167 | | - ? 'text-blue-600 bg-blue-50' |
168 | | - : 'text-gray-600 hover:text-blue-600' |
169 | | - }`} |
170 | | - > |
171 | | - Chat |
172 | | - </Link> |
173 | | - <Link |
174 | | - to="/profile" |
175 | | - className={`block px-3 py-2 rounded-md text-base font-medium transition-colors ${ |
176 | | - isActive('/profile') |
177 | | - ? 'text-blue-600 bg-blue-50' |
178 | | - : 'text-gray-600 hover:text-blue-600' |
179 | | - }`} |
180 | | - > |
181 | | - Profile |
182 | | - </Link> |
183 | | - </div> |
| 37 | + )} |
184 | 38 | </div> |
185 | 39 | </nav> |
186 | 40 | ) |
|
0 commit comments