yves.gugger 811e4776c8 fix: Seamless user journey for register/login/Stripe
PROBLEM: Redirect parameters were getting lost during user flows

FIXES APPLIED:

1. Register Page:
   - Default redirect: /command/dashboard (was /dashboard)
   - Stores redirect in localStorage before email verification
   - Preserves redirect when linking to login page

2. Login Page:
   - Checks localStorage for stored redirect (from registration)
   - Clears stored redirect after successful login
   - Uses useState for dynamic redirect handling

3. OAuth Callback:
   - Default redirect: /command/dashboard (was /dashboard)
   - Backend OAuth endpoints also updated

4. Fixed all /dashboard → /command/dashboard links:
   - pricing/page.tsx
   - page.tsx (landing page)
   - AdminLayout.tsx
   - DomainChecker.tsx
   - command/dashboard/page.tsx
   - Header.tsx (simplified check)

5. Backend OAuth:
   - Default redirect_path: /command/dashboard

NEW USER JOURNEY:

Pricing → Register → Email Verify → Login → Pricing → Stripe
                                                    ↓
                                            Welcome Page
                                                    ↓
                                              Dashboard

The redirect is preserved throughout:
- Query param ?redirect=/pricing passed through register/login
- Stored in localStorage during email verification gap
- Cleaned up after successful login

STRIPE FLOW CLARIFICATION:
- Stripe does NOT create users
- Users must register FIRST with email/password
- Then they can upgrade via Stripe checkout
- This is by design for security and flexibility
2025-12-10 16:23:16 +01:00

68 lines
2.0 KiB
TypeScript

'use client'
import { useEffect, Suspense } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { useStore } from '@/lib/store'
import { Loader2, CheckCircle } from 'lucide-react'
function OAuthCallbackContent() {
const router = useRouter()
const searchParams = useSearchParams()
const { checkAuth } = useStore()
useEffect(() => {
const token = searchParams.get('token')
const redirect = searchParams.get('redirect') || '/command/dashboard'
const isNew = searchParams.get('new') === 'true'
const error = searchParams.get('error')
if (error) {
router.push(`/login?error=${error}`)
return
}
if (token) {
// Store the token (using 'token' key to match api.ts)
localStorage.setItem('token', token)
// Update auth state
checkAuth().then(() => {
// Redirect with welcome message for new users
if (isNew) {
router.push(`${redirect}?welcome=true`)
} else {
router.push(redirect)
}
})
} else {
router.push('/login?error=no_token')
}
}, [searchParams, router, checkAuth])
return (
<div className="min-h-screen bg-background flex items-center justify-center">
<div className="text-center">
<div className="relative mb-6">
<Loader2 className="w-12 h-12 text-accent animate-spin mx-auto" />
<div className="absolute inset-0 bg-accent/20 blur-xl rounded-full" />
</div>
<h2 className="text-xl font-display text-foreground mb-2">Signing you in...</h2>
<p className="text-sm text-foreground-muted">Please wait while we complete authentication</p>
</div>
</div>
)
}
export default function OAuthCallbackPage() {
return (
<Suspense fallback={
<div className="min-h-screen flex items-center justify-center bg-background">
<Loader2 className="w-6 h-6 animate-spin text-accent" />
</div>
}>
<OAuthCallbackContent />
</Suspense>
)
}