fix chatbox
This commit is contained in:
@@ -4,9 +4,20 @@ import {useCallback, useState} from 'react';
|
||||
import {useRouter, useSearchParams} from 'next/navigation';
|
||||
import {useToast} from '@astryxdesign/core/Toast';
|
||||
import {useSession} from '@/features/auth/providers/SessionProvider';
|
||||
import {
|
||||
LOGIN_ERROR_PARAM,
|
||||
loginErrorFromCode,
|
||||
} from '@/features/auth/services/loginErrorCodes';
|
||||
import {resolveRedirectTarget} from '@/features/auth/services/redirectTarget';
|
||||
import type {LoginError} from '@/features/auth/types/auth';
|
||||
|
||||
/**
|
||||
* Where credentials are POSTed. Exported because the form element itself needs
|
||||
* it for `action` — the no-JavaScript path submits straight here, bypassing
|
||||
* this hook, authService and the repository entirely.
|
||||
*/
|
||||
export const LOGIN_ENDPOINT = '/api/auth/login';
|
||||
|
||||
/**
|
||||
* Every behaviour of the sign-in form, with no markup attached.
|
||||
*
|
||||
@@ -39,12 +50,30 @@ export function useLoginForm() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [rememberMe, setRememberMe] = useState(false);
|
||||
const [errors, setErrors] = useState<LoginFormState['errors']>({});
|
||||
/**
|
||||
* Seeded from `?error=` so a sign-in that failed on the no-JavaScript path
|
||||
* still shows its message once the page hydrates. The code is looked up in a
|
||||
* fixed table — an unrecognised one yields nothing, so the URL cannot be
|
||||
* used to write arbitrary text onto the sign-in screen.
|
||||
*
|
||||
* Seeding in useState rather than an effect keeps the message present in the
|
||||
* first render, server and client alike, so there is no flash and no
|
||||
* hydration mismatch to patch up.
|
||||
*/
|
||||
const [errors, setErrors] = useState<LoginFormState['errors']>(() => {
|
||||
const seeded = loginErrorFromCode(searchParams.get(LOGIN_ERROR_PARAM));
|
||||
return seeded ? {[seeded.field]: seeded.message} : {};
|
||||
});
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
// Raw, for the hidden field the native form path posts back. Unvalidated
|
||||
// here on purpose: the server validates it through resolveRedirectTarget,
|
||||
// which is the only side that can be trusted to.
|
||||
const next = searchParams.get('next');
|
||||
|
||||
// Shared with GuestGuard, which redirects on the same event — see
|
||||
// resolveRedirectTarget for why that matters and how `next` is validated.
|
||||
const destination = resolveRedirectTarget(searchParams.get('next'));
|
||||
const destination = resolveRedirectTarget(next);
|
||||
|
||||
const submit = useCallback(
|
||||
async (event: React.FormEvent) => {
|
||||
@@ -106,6 +135,7 @@ export function useLoginForm() {
|
||||
rememberMe,
|
||||
errors,
|
||||
isSubmitting,
|
||||
next,
|
||||
setEmail: updateEmail,
|
||||
setPassword: updatePassword,
|
||||
setRememberMe,
|
||||
|
||||
Reference in New Issue
Block a user