mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-04 23:30:19 +01:00
♻️ refactor: Login and Registration component Improvement (#2716)
* ♻️ refactor: Login form improvement * display error message when API is down * add loading animation to Login form while fetching data * optimize startupConfig to fetch data only on initial render to prevent unnecessary API calls * 🚑 fix: clear authentication error messages on successful login * ♻️ refactor: componentize duplicate codes on registration and login screens * chore: update types * refactor: layout rendering order * refactor: startup title fix * refactor: reset/request-reset-password under new AuthLayout * ci: fix Login.spec.ts * ci: fix registration.spec.tsx --------- Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
parent
2b7a973a33
commit
9f2538fcd9
19 changed files with 775 additions and 750 deletions
7
client/src/routes/Layouts/Login.tsx
Normal file
7
client/src/routes/Layouts/Login.tsx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { useAuthContext } from '~/hooks/AuthContext';
|
||||
import StartupLayout from './Startup';
|
||||
|
||||
export default function LoginLayout() {
|
||||
const { isAuthenticated } = useAuthContext();
|
||||
return <StartupLayout isAuthenticated={isAuthenticated} />;
|
||||
}
|
||||
70
client/src/routes/Layouts/Startup.tsx
Normal file
70
client/src/routes/Layouts/Startup.tsx
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
|
||||
import type { TStartupConfig } from 'librechat-data-provider';
|
||||
import AuthLayout from '~/components/Auth/AuthLayout';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
const headerMap = {
|
||||
'/login': 'com_auth_welcome_back',
|
||||
'/register': 'com_auth_create_account',
|
||||
'/forgot-password': 'com_auth_reset_password',
|
||||
'/reset-password': 'com_auth_reset_password',
|
||||
};
|
||||
|
||||
export default function StartupLayout({ isAuthenticated }: { isAuthenticated?: boolean }) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [headerText, setHeaderText] = useState<string | null>(null);
|
||||
const [startupConfig, setStartupConfig] = useState<TStartupConfig | null>(null);
|
||||
const {
|
||||
data,
|
||||
isFetching,
|
||||
error: startupConfigError,
|
||||
} = useGetStartupConfig({
|
||||
enabled: isAuthenticated ? startupConfig === null : true,
|
||||
});
|
||||
const localize = useLocalize();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
navigate('/c/new', { replace: true });
|
||||
}
|
||||
if (data) {
|
||||
setStartupConfig(data);
|
||||
}
|
||||
}, [isAuthenticated, navigate, data]);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = startupConfig?.appTitle || 'LibreChat';
|
||||
}, [startupConfig?.appTitle]);
|
||||
|
||||
useEffect(() => {
|
||||
setError(null);
|
||||
setHeaderText(null);
|
||||
}, [location.pathname]);
|
||||
|
||||
const contextValue = {
|
||||
error,
|
||||
setError,
|
||||
headerText,
|
||||
setHeaderText,
|
||||
startupConfigError,
|
||||
startupConfig,
|
||||
isFetching,
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthLayout
|
||||
header={headerText ? localize(headerText) : localize(headerMap[location.pathname])}
|
||||
isFetching={isFetching}
|
||||
startupConfig={startupConfig}
|
||||
startupConfigError={startupConfigError}
|
||||
pathname={location.pathname}
|
||||
error={error}
|
||||
>
|
||||
<Outlet context={contextValue} />
|
||||
</AuthLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ import {
|
|||
ApiErrorWatcher,
|
||||
} from '~/components/Auth';
|
||||
import { AuthContextProvider } from '~/hooks/AuthContext';
|
||||
import StartupLayout from './Layouts/Startup';
|
||||
import LoginLayout from './Layouts/Login';
|
||||
import ShareRoute from './ShareRoute';
|
||||
import ChatRoute from './ChatRoute';
|
||||
import Search from './Search';
|
||||
|
|
@ -20,28 +22,40 @@ const AuthLayout = () => (
|
|||
);
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
path: 'register',
|
||||
element: <Registration />,
|
||||
},
|
||||
{
|
||||
path: 'forgot-password',
|
||||
element: <RequestPasswordReset />,
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
element: <ResetPassword />,
|
||||
},
|
||||
{
|
||||
path: 'share/:shareId',
|
||||
element: <ShareRoute />,
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
element: <StartupLayout />,
|
||||
children: [
|
||||
{
|
||||
path: 'register',
|
||||
element: <Registration />,
|
||||
},
|
||||
{
|
||||
path: 'forgot-password',
|
||||
element: <RequestPasswordReset />,
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
element: <ResetPassword />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
element: <AuthLayout />,
|
||||
children: [
|
||||
{
|
||||
path: 'login',
|
||||
element: <Login />,
|
||||
path: '/',
|
||||
element: <LoginLayout />,
|
||||
children: [
|
||||
{
|
||||
path: 'login',
|
||||
element: <Login />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue