Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { Mail, Lock } from 'lucide-react';
import { useAuth } from '@/lib/auth-context';
import { useRedirectIfAuthenticated } from '@/lib/use-redirect-if-authenticated';
import { ApiError } from '@/lib/api';
import { FormError } from '@/components/form-error';
import { AuthLayout } from '@/components/auth-layout';
Expand All @@ -18,6 +19,7 @@ export default function LoginPage() {
const [password, setPassword] = useState('');
const [error, setError] = useState<string | null>(null);
const [submitting, setSubmitting] = useState(false);
const redirecting = useRedirectIfAuthenticated();

async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
Expand All @@ -37,6 +39,9 @@ export default function LoginPage() {
}
}

// Signed-in users are sent to their dashboard instead of seeing the form (#50).
if (redirecting) return null;

return (
<AuthLayout title="Welcome back" subtitle="Log in to manage your tickets and organizations.">
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
Expand Down
5 changes: 5 additions & 0 deletions src/app/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { User, Mail, Lock } from 'lucide-react';
import { useAuth } from '@/lib/auth-context';
import { useRedirectIfAuthenticated } from '@/lib/use-redirect-if-authenticated';
import { ApiError } from '@/lib/api';
import { FormError } from '@/components/form-error';
import { AuthLayout } from '@/components/auth-layout';
Expand All @@ -19,6 +20,7 @@ export default function RegisterPage() {
const [password, setPassword] = useState('');
const [error, setError] = useState<string | null>(null);
const [submitting, setSubmitting] = useState(false);
const redirecting = useRedirectIfAuthenticated();

async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
Expand All @@ -38,6 +40,9 @@ export default function RegisterPage() {
}
}

// Signed-in users are sent to their dashboard instead of seeing the form (#50).
if (redirecting) return null;

return (
<AuthLayout
title="Create your account"
Expand Down
27 changes: 27 additions & 0 deletions src/lib/use-redirect-if-authenticated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from './auth-context';

/** Where a signed-in user lands by default (matches the post-login redirect). */
export const DEFAULT_AUTHENTICATED_PATH = '/dashboard';

/**
* Guest-only pages (/login, /register): once auth has finished loading, send
* a signed-in user to their default page with `router.replace`, so the auth
* form isn't left in history (#50).
*
* Returns true while the page should render nothing — auth still loading or a
* redirect in flight — so the form never flashes for a signed-in user.
*/
export function useRedirectIfAuthenticated(to: string = DEFAULT_AUTHENTICATED_PATH): boolean {
const { user, loading } = useAuth();
const router = useRouter();

useEffect(() => {
if (!loading && user) router.replace(to);
}, [loading, user, router, to]);

return loading || user !== null;
}
Loading