abd9d651dc
- add `createAccountSetup`, `verifyAccountSetupToken`, `deleteAccountSetupToken` to verifications core - add `completeAccountSetup` function to auth core for password creation on invite - add `InvitationEmail` template for sending invite links - add `SetupAccountPage` client page for invited users to set their password - add `UserCreateModal` admin component to invite new users - wire invitation action and API endpoint in auth feature - update admin `UsersPage` to include user creation modal - update auth and admin README docs
95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
'use client';
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
import { useEffect, useState } from 'react';
|
|
import LoginPage from './pages/LoginPage.client.js';
|
|
import RegisterPage from './pages/RegisterPage.client.js';
|
|
import ForgotPasswordPage from './pages/ForgotPasswordPage.client.js';
|
|
import ResetPasswordPage from './pages/ResetPasswordPage.client.js';
|
|
import ConfirmEmailPage from './pages/ConfirmEmailPage.client.js';
|
|
import LogoutPage from './pages/LogoutPage.client.js';
|
|
import SetupAccountPage from './pages/SetupAccountPage.client.js';
|
|
|
|
const PAGE_COMPONENTS = {
|
|
login: LoginPage,
|
|
register: RegisterPage,
|
|
forgot: ForgotPasswordPage,
|
|
reset: ResetPasswordPage,
|
|
confirm: ConfirmEmailPage,
|
|
logout: LogoutPage,
|
|
setup: SetupAccountPage,
|
|
};
|
|
|
|
export default function AuthPage({
|
|
params,
|
|
searchParams,
|
|
registerAction,
|
|
loginAction,
|
|
forgotPasswordAction,
|
|
resetPasswordAction,
|
|
verifyEmailAction,
|
|
setupAccountAction,
|
|
logoutAction,
|
|
setSessionCookieAction,
|
|
redirectAfterLogin = '/',
|
|
currentUser = null,
|
|
}) {
|
|
const router = useRouter();
|
|
const [currentPage, setCurrentPage] = useState(null);
|
|
const [email, setEmail] = useState('');
|
|
const [token, setToken] = useState('');
|
|
|
|
useEffect(() => {
|
|
const fromParams = params?.auth?.[0];
|
|
if (fromParams) { setCurrentPage(fromParams); return; }
|
|
if (typeof window !== 'undefined') {
|
|
const match = window.location.pathname.match(/\/auth\/([^\/?]+)/);
|
|
setCurrentPage(match ? match[1] : 'login');
|
|
} else {
|
|
setCurrentPage('login');
|
|
}
|
|
}, [params]);
|
|
|
|
useEffect(() => {
|
|
const run = async () => {
|
|
// searchParams became a Promise in Next.js 15 — resolve both forms.
|
|
const resolved = searchParams && typeof searchParams.then === 'function'
|
|
? await searchParams
|
|
: searchParams;
|
|
|
|
const urlParams = typeof window !== 'undefined'
|
|
? new URLSearchParams(window.location.search)
|
|
: null;
|
|
setEmail(resolved?.email || urlParams?.get('email') || '');
|
|
setToken(resolved?.token || urlParams?.get('token') || '');
|
|
};
|
|
run();
|
|
}, [searchParams]);
|
|
|
|
const navigate = (page) => router.push(`/auth/${page}`);
|
|
|
|
if (!currentPage) return null;
|
|
|
|
const Page = PAGE_COMPONENTS[currentPage] || LoginPage;
|
|
const common = { onNavigate: navigate, currentUser };
|
|
|
|
switch (Page) {
|
|
case LoginPage:
|
|
return <Page {...common} onSubmit={loginAction} onSetSessionCookie={setSessionCookieAction} redirectAfterLogin={redirectAfterLogin} />;
|
|
case RegisterPage:
|
|
return <Page {...common} onSubmit={registerAction} />;
|
|
case ForgotPasswordPage:
|
|
return <Page {...common} onSubmit={forgotPasswordAction} />;
|
|
case ResetPasswordPage:
|
|
return <Page {...common} onSubmit={resetPasswordAction} email={email} token={token} />;
|
|
case ConfirmEmailPage:
|
|
return <Page {...common} onSubmit={verifyEmailAction} email={email} token={token} />;
|
|
case SetupAccountPage:
|
|
return <Page {...common} onSubmit={setupAccountAction} email={email} token={token} />;
|
|
case LogoutPage:
|
|
return <Page onLogout={logoutAction} onSetSessionCookie={setSessionCookieAction} />;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|