Layout improvements, some additions

This commit is contained in:
2020-11-29 07:03:22 +05:00
parent df69c05ff5
commit 8dcbdbdbd5
38 changed files with 2249 additions and 94 deletions

View File

@ -0,0 +1,15 @@
import React from "react";
import styles from "styles/errorMessage.module.css";
interface IErrorMessageProps {
message: string;
}
const ErrorMessage: React.FC<IErrorMessageProps> = ({ message }) => (
<div>
<p className={styles.text}>{message}</p>
</div>
);
export default ErrorMessage;

View File

@ -0,0 +1,18 @@
import { HomeRefContext } from "context/ref";
import React, { useContext } from "react";
import styles from "styles/layout.module.css";
const HomeHeader: React.FC = () => {
const ref = useContext(HomeRefContext);
const scrollToRef = () => ref?.current?.scrollIntoView();
return (
<a onClick={scrollToRef} className={styles.link}>
Регистрация
</a>
);
};
export default HomeHeader;

View File

@ -0,0 +1,33 @@
import React, { useContext, useEffect, useState } from "react";
import styles from "styles/layout.module.css";
import { LoadingContext } from "context/loading";
import HomeHeader from "./HomeHeader";
import UserHeader from "./UserHeader";
const Layout: React.FC<{ pathname: string }> = ({ children, pathname }) => {
const { loading, setLoading } = useContext(LoadingContext);
useEffect(() => setLoading(false), []);
if (loading) return <h1>Loading...</h1>;
return (
<div className={styles.content}>
<nav className={styles.header}>
<div className={styles.logo}>
<img src="logo.svg" alt="" />
<p className={styles.textLogo}>Ko.Map</p>
</div>
<div />
<div>
{pathname == "/" ? <HomeHeader /> : ""}
{pathname == "/user" ? <UserHeader /> : ""}
</div>
</nav>
<div>{children}</div>
</div>
);
};
export default Layout;

View File

@ -0,0 +1,65 @@
import React, { Dispatch, FormEvent, SetStateAction, useContext } from "react";
import { NextRouter, useRouter } from "next/router";
import ErrorMessage from "components/ErrorMessage";
import { UserContext, UserT } from "context/user";
import useErrorHandler from "hooks/ErrorHandler";
import { request } from "utils/index";
const dispatch = (err: Error) => "Error happened";
const setToken = async (
token: string,
setUserState: Dispatch<SetStateAction<UserT>>
) => {
localStorage.setItem("token", token);
try {
const user = await request("user", "GET");
setUserState(user);
} catch (err) {
console.log(err.message);
throw err;
}
};
const handleSubmit = (
resetError: () => void,
setUserState: Dispatch<SetStateAction<UserT>>,
gotError: (err: Error) => void,
router: NextRouter
) => async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
const formData = new FormData(e.currentTarget);
const jsonData = Object.fromEntries(formData);
resetError();
const res = await request("login", "POST", jsonData);
setToken(res.token, setUserState);
router.push("/user");
} catch (err) {
gotError(err.message);
}
};
const Login: React.FC = () => {
const router = useRouter();
const { error, gotError, resetError } = useErrorHandler(dispatch);
const { userState, setUserState } = useContext(UserContext);
return (
<form onSubmit={handleSubmit(resetError, setUserState, gotError, router)}>
<input type="email" name="email" id="email" />
<input type="password" name="password" id="password" autoComplete="on" />
<input type="submit" />
{error.has ? <ErrorMessage message={error.message} /> : ""}
</form>
);
};
export default Login;

View File

@ -0,0 +1,48 @@
import React, { FormEvent, useState } from "react";
import ErrorMessage from "components/ErrorMessage";
import useErrorHandler from "hooks/ErrorHandler";
import { request } from "utils/index";
const dispatch = (err: Error) => "Error happened";
const Register: React.FC = () => {
const [successfulAttempt, setSuccessfulAttempt] = useState<boolean>(false);
const { error, gotError, resetError } = useErrorHandler(dispatch);
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
const formData = new FormData(e.currentTarget);
const jsonData = Object.fromEntries(formData);
resetError();
const res = await request("register", "POST", jsonData);
if (!res.ok) throw new Error("Couldn't register");
setSuccessfulAttempt(true);
} catch (err) {
gotError(err.message);
}
};
return successfulAttempt ? (
<p>
Для продолжения регистрации перейдите по ссылке, отправленной вам на
введённую почту
</p>
) : (
<form onSubmit={handleSubmit}>
<input type="text" name="username" id="username" />
<input type="email" name="email" id="email" />
<input type="password" name="password" id="password" autoComplete="on" />
<input type="submit" />
{error.has ? <ErrorMessage message={error.message} /> : ""}
</form>
);
};
export default Register;

View File

@ -2,10 +2,12 @@ import React from "react";
import { IRouteView } from "types/user";
import RouteCard from "./RouteCard";
import styles from "styles/RouteView.module.css";
const RouteView: React.FC<IRouteView> = ({ header, routes }) => {
return (
<>
<h1>{header}</h1>
<h1 className={styles.header}>{header}</h1>
{routes.map((route) => (
<RouteCard key={route.id} route={route} />
))}

View File

@ -1,12 +1,13 @@
import React from "react";
import { UserContext } from "context/user";
import Link from "next/link";
import React, { useContext } from "react";
import { IHeaderProps } from "types/user";
const UserHeader: React.FC = () => {
const user = useContext(UserContext);
const Header: React.FC<IHeaderProps> = ({ points }) => {
return (
<header>
<div>Очки: {points}</div>
<>
<div>Очки: {user?.userState?.points || 0}</div>
<nav>
<ul>
<li>
@ -21,8 +22,8 @@ const Header: React.FC<IHeaderProps> = ({ points }) => {
</li>
</ul>
</nav>
</header>
</>
);
};
export default Header;
export default UserHeader;