fix(login): resolve session persistence and UI state after successful login

Fixed three critical issues with the login flow:

1. LOGIN SUCCESSFUL REDIRECT
   - Changed redirect from '/' to '/panel' (user personal dashboard)
   - Users now land on their panel page after login instead of home page

2. SESSION PERSISTENCE
   - Navbar now fetches fresh session data on client-side after login
   - Added useEffect in Navbar to call /api/auth/session on component mount
   - UserMenu dynamically updates to show logged-in state
   - Session data is fetched with credentials: 'include'

3. DYNAMIC USER STATE
   - Created currentUser signal in Navbar to track real-time auth state
   - UserMenu now receives currentUser.value instead of static server prop
   - User information updates immediately after successful login
   - No page refresh needed to see user menu change

CHANGES:
- LoginForm.tsx: Redirect to /panel after successful login
- Navbar.tsx: Added session fetching on client-side mount
- UserMenu: Receives live user data via currentUser signal

The user will now see:
 Immediate UI update (UserMenu shows avatar/dropdown)
 Redirect to /panel (user dashboard)
 Session persists across page navigation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Haitao Pan 2025-11-05 16:34:39 +08:00
parent a99070ba6d
commit 844b15af4d
2 changed files with 44 additions and 4 deletions

View File

@ -258,9 +258,9 @@ export default function LoginForm({ language, initialEmail = '', onSuccess }: Lo
if (onSuccess) {
onSuccess()
} else {
// Redirect to home after short delay
// Redirect to user panel after short delay
setTimeout(() => {
globalThis.location.href = '/'
globalThis.location.href = '/panel'
}, 1000)
}
} catch (submitError) {

View File

@ -34,6 +34,46 @@ export default function Navbar({ language, user, pathname = '/' }: NavbarProps)
const searchValue = useSignal('')
const navRef = useRef<HTMLElement>(null)
// Use provided user from server, but try to fetch fresh session on client
const currentUser = useSignal<User | null>(user || null)
// Fetch session on client-side to get fresh user info
useEffect(() => {
let isActive = true
const fetchSession = async () => {
try {
const response = await fetch('/api/auth/session', {
credentials: 'include',
})
if (!isActive || !response.ok) {
return
}
const data = (await response.json()) as {
user?: User
}
if (isActive && data.user) {
currentUser.value = data.user
}
} catch (error) {
// Silently fail if session fetch fails
console.debug('Failed to fetch session:', error)
}
}
// Only fetch on client side
if (typeof window !== 'undefined') {
fetchSession()
}
return () => {
isActive = false
}
}, [])
const isHiddenRoute = pathname ? ['/login', '/register'].some((prefix) => pathname.startsWith(prefix)) : false
// Generate language toggle URL that preserves current path and params
@ -190,7 +230,7 @@ export default function Navbar({ language, user, pathname = '/' }: NavbarProps)
</button>
</form>
<UserMenu user={user} language={language} />
<UserMenu user={currentUser.value} language={language} />
{/* Mail Icon */}
<a
@ -309,7 +349,7 @@ export default function Navbar({ language, user, pathname = '/' }: NavbarProps)
</div>
<div onClick={() => (menuOpen.value = false)}>
<UserMenu user={user} language={language} />
<UserMenu user={currentUser.value} language={language} />
</div>
<div class="flex flex-col gap-2">