From 63f51e026fca87868e647e646258aa15a713a94c Mon Sep 17 00:00:00 2001
From: IRBorisov <8611739+IRBorisov@users.noreply.github.com>
Date: Mon, 17 Jun 2024 21:31:19 +0300
Subject: [PATCH] Improve first loading behavior
---
.../src/components/wrap/RequireAuth.tsx | 33 +--
rsconcept/frontend/src/pages/HomePage.tsx | 25 ++-
rsconcept/frontend/src/pages/RegisterPage.tsx | 207 ------------------
.../src/pages/RegisterPage/FormSignup.tsx | 195 +++++++++++++++++
.../src/pages/RegisterPage/RegisterPage.tsx | 40 ++++
.../frontend/src/pages/RegisterPage/index.tsx | 1 +
6 files changed, 270 insertions(+), 231 deletions(-)
delete mode 100644 rsconcept/frontend/src/pages/RegisterPage.tsx
create mode 100644 rsconcept/frontend/src/pages/RegisterPage/FormSignup.tsx
create mode 100644 rsconcept/frontend/src/pages/RegisterPage/RegisterPage.tsx
create mode 100644 rsconcept/frontend/src/pages/RegisterPage/index.tsx
diff --git a/rsconcept/frontend/src/components/wrap/RequireAuth.tsx b/rsconcept/frontend/src/components/wrap/RequireAuth.tsx
index 7cf30688..bd5f1bcd 100644
--- a/rsconcept/frontend/src/components/wrap/RequireAuth.tsx
+++ b/rsconcept/frontend/src/components/wrap/RequireAuth.tsx
@@ -1,27 +1,34 @@
'use client';
+import { AnimatePresence } from 'framer-motion';
+
import { useAuth } from '@/context/AuthContext';
+import Loader from '../ui/Loader';
import TextURL from '../ui/TextURL';
+import AnimateFade from './AnimateFade';
interface RequireAuthProps {
children: React.ReactNode;
}
function RequireAuth({ children }: RequireAuthProps) {
- const { user } = useAuth();
- if (user) {
- return children;
- } else {
- return (
-
-
Пожалуйста войдите в систему
-
-
-
-
- );
- }
+ const { user, loading } = useAuth();
+
+ return (
+
+ {loading ? : null}
+ {!loading && user ? {children} : null}
+ {!loading && !user ? (
+
+ Пожалуйста войдите в систему
+
+
+
+
+ ) : null}
+
+ );
}
export default RequireAuth;
diff --git a/rsconcept/frontend/src/pages/HomePage.tsx b/rsconcept/frontend/src/pages/HomePage.tsx
index a0272dbe..f02778e3 100644
--- a/rsconcept/frontend/src/pages/HomePage.tsx
+++ b/rsconcept/frontend/src/pages/HomePage.tsx
@@ -1,27 +1,30 @@
import { useLayoutEffect } from 'react';
import { urls } from '@/app/urls';
+import Loader from '@/components/ui/Loader';
import { useAuth } from '@/context/AuthContext';
import { useConceptNavigation } from '@/context/NavigationContext';
import { PARAMETER } from '@/utils/constants';
function HomePage() {
const router = useConceptNavigation();
- const { user } = useAuth();
+ const { user, loading } = useAuth();
useLayoutEffect(() => {
- if (!user) {
- setTimeout(() => {
- router.push(urls.manuals);
- }, PARAMETER.refreshTimeout);
- } else {
- setTimeout(() => {
- router.push(urls.library);
- }, PARAMETER.refreshTimeout);
+ if (!loading) {
+ if (!user) {
+ setTimeout(() => {
+ router.push(urls.manuals);
+ }, PARAMETER.refreshTimeout);
+ } else {
+ setTimeout(() => {
+ router.push(urls.library);
+ }, PARAMETER.refreshTimeout);
+ }
}
- }, [router, user]);
+ }, [router, user, loading]);
- return ;
+ return ;
}
export default HomePage;
diff --git a/rsconcept/frontend/src/pages/RegisterPage.tsx b/rsconcept/frontend/src/pages/RegisterPage.tsx
deleted file mode 100644
index adb5bfa2..00000000
--- a/rsconcept/frontend/src/pages/RegisterPage.tsx
+++ /dev/null
@@ -1,207 +0,0 @@
-'use client';
-
-import axios from 'axios';
-import clsx from 'clsx';
-import { useEffect, useMemo, useState } from 'react';
-import { toast } from 'react-toastify';
-
-import { urls } from '@/app/urls';
-import { IconHelp } from '@/components/Icons';
-import InfoError, { ErrorData } from '@/components/info/InfoError';
-import Button from '@/components/ui/Button';
-import Checkbox from '@/components/ui/Checkbox';
-import FlexColumn from '@/components/ui/FlexColumn';
-import Overlay from '@/components/ui/Overlay';
-import PrettyJson from '@/components/ui/PrettyJSON';
-import SubmitButton from '@/components/ui/SubmitButton';
-import TextInput from '@/components/ui/TextInput';
-import TextURL from '@/components/ui/TextURL';
-import Tooltip from '@/components/ui/Tooltip';
-import AnimateFade from '@/components/wrap/AnimateFade';
-import ExpectedAnonymous from '@/components/wrap/ExpectedAnonymous';
-import { useAuth } from '@/context/AuthContext';
-import { useConceptNavigation } from '@/context/NavigationContext';
-import { HelpTopic } from '@/models/miscellaneous';
-import { IUserSignupData } from '@/models/user';
-import { globals, patterns } from '@/utils/constants';
-
-function RegisterPage() {
- const router = useConceptNavigation();
- const { user, signup, loading, error, setError } = useAuth();
-
- const [username, setUsername] = useState('');
- const [email, setEmail] = useState('');
- const [password, setPassword] = useState('');
- const [password2, setPassword2] = useState('');
- const [firstName, setFirstName] = useState('');
- const [lastName, setLastName] = useState('');
-
- const [acceptPrivacy, setAcceptPrivacy] = useState(false);
- const [acceptRules, setAcceptRules] = useState(false);
-
- const isValid = useMemo(
- () => acceptPrivacy && acceptRules && !!email && !!username,
- [acceptPrivacy, acceptRules, email, username]
- );
-
- useEffect(() => {
- setError(undefined);
- }, [username, email, password, password2, setError]);
-
- function handleCancel() {
- if (router.canBack()) {
- router.back();
- } else {
- router.push(urls.library);
- }
- }
-
- function handleSubmit(event: React.FormEvent) {
- event.preventDefault();
- if (!loading) {
- const data: IUserSignupData = {
- username,
- email,
- password,
- password2,
- first_name: firstName,
- last_name: lastName
- };
- signup(data, createdUser => {
- router.push(urls.login_hint(createdUser.username));
- toast.success(`Пользователь успешно создан: ${createdUser.username}`);
- });
- }
- }
-
- if (user) {
- return (
-
-
-
- );
- }
- return (
-
-
-
- );
-}
-
-export default RegisterPage;
-
-// ====== Internals =========
-function ProcessError({ error }: { error: ErrorData }): React.ReactElement {
- if (axios.isAxiosError(error) && error.response && error.response.status === 400) {
- if ('email' in error.response.data) {
- return (
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
- {error.response.data.email}.
- );
- } else if ('username' in error.response.data) {
- return (
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
- {error.response.data.username}.
- );
- } else {
- return (
-
- );
- }
- }
- return ;
-}
diff --git a/rsconcept/frontend/src/pages/RegisterPage/FormSignup.tsx b/rsconcept/frontend/src/pages/RegisterPage/FormSignup.tsx
new file mode 100644
index 00000000..91afc60a
--- /dev/null
+++ b/rsconcept/frontend/src/pages/RegisterPage/FormSignup.tsx
@@ -0,0 +1,195 @@
+'use client';
+
+import axios from 'axios';
+import clsx from 'clsx';
+import { useEffect, useMemo, useState } from 'react';
+import { toast } from 'react-toastify';
+
+import { urls } from '@/app/urls';
+import { IconHelp } from '@/components/Icons';
+import InfoError, { ErrorData } from '@/components/info/InfoError';
+import Button from '@/components/ui/Button';
+import Checkbox from '@/components/ui/Checkbox';
+import FlexColumn from '@/components/ui/FlexColumn';
+import Overlay from '@/components/ui/Overlay';
+import PrettyJson from '@/components/ui/PrettyJSON';
+import SubmitButton from '@/components/ui/SubmitButton';
+import TextInput from '@/components/ui/TextInput';
+import TextURL from '@/components/ui/TextURL';
+import Tooltip from '@/components/ui/Tooltip';
+import { useAuth } from '@/context/AuthContext';
+import { useConceptNavigation } from '@/context/NavigationContext';
+import { HelpTopic } from '@/models/miscellaneous';
+import { IUserSignupData } from '@/models/user';
+import { globals, patterns } from '@/utils/constants';
+
+function FormSignup() {
+ const router = useConceptNavigation();
+ const { signup, loading, error, setError } = useAuth();
+
+ const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [password2, setPassword2] = useState('');
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
+
+ const [acceptPrivacy, setAcceptPrivacy] = useState(false);
+ const [acceptRules, setAcceptRules] = useState(false);
+
+ const isValid = useMemo(
+ () => acceptPrivacy && acceptRules && !!email && !!username,
+ [acceptPrivacy, acceptRules, email, username]
+ );
+
+ useEffect(() => {
+ setError(undefined);
+ }, [username, email, password, password2, setError]);
+
+ function handleCancel() {
+ if (router.canBack()) {
+ router.back();
+ } else {
+ router.push(urls.library);
+ }
+ }
+
+ function handleSubmit(event: React.FormEvent) {
+ event.preventDefault();
+ if (!loading) {
+ const data: IUserSignupData = {
+ username,
+ email,
+ password,
+ password2,
+ first_name: firstName,
+ last_name: lastName
+ };
+ signup(data, createdUser => {
+ router.push(urls.login_hint(createdUser.username));
+ toast.success(`Пользователь успешно создан: ${createdUser.username}`);
+ });
+ }
+ }
+ return (
+
+ );
+}
+
+export default FormSignup;
+
+// ====== Internals =========
+function ProcessError({ error }: { error: ErrorData }): React.ReactElement {
+ if (axios.isAxiosError(error) && error.response && error.response.status === 400) {
+ if ('email' in error.response.data) {
+ return (
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ {error.response.data.email}.
+ );
+ } else if ('username' in error.response.data) {
+ return (
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ {error.response.data.username}.
+ );
+ } else {
+ return (
+
+ );
+ }
+ }
+ return ;
+}
diff --git a/rsconcept/frontend/src/pages/RegisterPage/RegisterPage.tsx b/rsconcept/frontend/src/pages/RegisterPage/RegisterPage.tsx
new file mode 100644
index 00000000..f57ec233
--- /dev/null
+++ b/rsconcept/frontend/src/pages/RegisterPage/RegisterPage.tsx
@@ -0,0 +1,40 @@
+import { AnimatePresence } from 'framer-motion';
+
+import Loader from '@/components/ui/Loader';
+import AnimateFade from '@/components/wrap/AnimateFade';
+import ExpectedAnonymous from '@/components/wrap/ExpectedAnonymous';
+import { useAuth } from '@/context/AuthContext';
+
+import FormSignup from './FormSignup';
+
+function RegisterPage() {
+ const { user, loading } = useAuth();
+
+ if (loading) {
+ return ;
+ }
+ if (user && !loading) {
+ return (
+
+
+
+ );
+ }
+ return (
+
+ {loading ? : null}
+ {!loading && user ? (
+
+
+
+ ) : null}
+ {!loading && !user ? (
+
+
+
+ ) : null}
+
+ );
+}
+
+export default RegisterPage;
diff --git a/rsconcept/frontend/src/pages/RegisterPage/index.tsx b/rsconcept/frontend/src/pages/RegisterPage/index.tsx
new file mode 100644
index 00000000..1b9629b7
--- /dev/null
+++ b/rsconcept/frontend/src/pages/RegisterPage/index.tsx
@@ -0,0 +1 @@
+export { default } from './RegisterPage';