minor refactoring, light bug fixes
This commit is contained in:
@@ -1,20 +1,16 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAuthContext } from "../../context/AuthContext";
|
||||
import { IUserAuth } from "../../schemas";
|
||||
import { attemptLogin } from "../../util/apiUtils";
|
||||
import { Button, Page, Panel } from "../ui";
|
||||
import Form, { FormConfig } from "../ui/Form";
|
||||
import { IUserAuth } from "../../schemas";
|
||||
import { Button, Form, Page, Panel } from "../ui";
|
||||
|
||||
export default function Login() {
|
||||
// setup and local state
|
||||
const authContext = useAuthContext();
|
||||
const navigate = useNavigate();
|
||||
const [form, setForm] = useState<JSX.Element[]>();
|
||||
const [input, setInput] = useState<IUserAuth>({
|
||||
email: '',
|
||||
password: ''
|
||||
})
|
||||
const [input, setInput] = useState<IUserAuth>({ email: '', password: '' });
|
||||
|
||||
// retrieve and store state from form
|
||||
const getFormState = useCallback((received: IUserAuth) => {
|
||||
@@ -29,18 +25,19 @@ export default function Login() {
|
||||
navigate('/');
|
||||
}
|
||||
|
||||
const formConfig: FormConfig<IUserAuth> = {
|
||||
parent: 'login',
|
||||
keys: Object.keys(input),
|
||||
labels: ["Email", "Password"],
|
||||
dataTypes: Object.keys(input),
|
||||
initialState: input,
|
||||
getState: getFormState
|
||||
}
|
||||
|
||||
// check for logged in user and mount form
|
||||
useEffect(() => {
|
||||
if (authContext.user) navigate('/');
|
||||
setForm(new Form<IUserAuth>(formConfig).mount())
|
||||
setForm(
|
||||
new Form<IUserAuth>({
|
||||
parent: 'login',
|
||||
keys: Object.keys(input),
|
||||
labels: ["Email", "Password"],
|
||||
dataTypes: Object.keys(input),
|
||||
initialState: input,
|
||||
getState: getFormState
|
||||
}).mount()
|
||||
);
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
||||
@@ -22,7 +22,6 @@ export default class Form<T>{
|
||||
public labels: string[];
|
||||
public keys: string[];
|
||||
public dataTypes: any[]
|
||||
public length: number;
|
||||
public state: T;
|
||||
public getState: (received: T) => void
|
||||
|
||||
@@ -30,7 +29,6 @@ export default class Form<T>{
|
||||
this.parent = config.parent;
|
||||
this.keys = config.keys;
|
||||
this.labels = config.labels || this.keys;
|
||||
this.length = config.keys.length;
|
||||
this.dataTypes = config.dataTypes || new Array(this.keys.length).fill('text');
|
||||
this.state = config.initialState;
|
||||
this.getState = config.getState;
|
||||
@@ -49,7 +47,7 @@ export default class Form<T>{
|
||||
mount() {
|
||||
let output = new Array<JSX.Element>();
|
||||
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
for (let i = 0; i < this.keys.length; i++) {
|
||||
output.push(
|
||||
<div id={`${this.parent}-row-${i}`} key={v4()}>
|
||||
<label htmlFor={`${this.parent}-${this.keys[i]}`}>{this.labels[i]}</label>
|
||||
|
||||
@@ -1,70 +1,36 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { LoggedIn, NotLoggedIn, Registering } from "./variants";
|
||||
import { useAuthContext } from "../../../context/AuthContext";
|
||||
import { attemptLogout } from "../../../util/apiUtils";
|
||||
import { IUser } from "../../../schemas";
|
||||
import Button from "../Button";
|
||||
import "/src/sass/components/Navbar.scss";
|
||||
|
||||
const Navbar = () => {
|
||||
// setup and local state
|
||||
const navigate = useNavigate();
|
||||
const authContext = useAuthContext();
|
||||
const [received, setReceived] = useState<IUser>();
|
||||
const [received, setReceived] = useState<IUser | undefined>();
|
||||
const [displayed, setDisplayed] = useState<JSX.Element>();
|
||||
|
||||
// helper to unwrap async result
|
||||
const handleLogout = async () => {
|
||||
const success = await attemptLogout();
|
||||
if (success) setReceived(undefined);
|
||||
// lift and store state from navbar variants
|
||||
const liftChange = useCallback((newValue: IUser | undefined) => {
|
||||
authContext.user = newValue;
|
||||
setReceived(newValue);
|
||||
}, [])
|
||||
|
||||
const variants = {
|
||||
loggedin: <LoggedIn navigate={navigate} received={received} liftChange={liftChange} />,
|
||||
notloggedin: <NotLoggedIn navigate={navigate} received={received} />,
|
||||
registering: <Registering navigate={navigate} received={received} />
|
||||
}
|
||||
|
||||
// jsx variations
|
||||
const navbarLoggedIn = (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {received?.firstname}.</p>
|
||||
<span id="search-icon"></span>
|
||||
<Button onClick={() => navigate('/profile')}>Profile</Button>
|
||||
<Button onClick={handleLogout}>Log Out</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const navbarNotLoggedIn = (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className='navbar-block'>
|
||||
<button onClick={() => navigate('/login')}>LOG IN</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const navbarRegistering = (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {received?.firstname}.</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
// side effects for live rendering
|
||||
useEffect(() => {
|
||||
console.log(authContext);
|
||||
authContext && setReceived(authContext.user);
|
||||
}, [authContext])
|
||||
|
||||
useEffect(() => {
|
||||
console.log(received);
|
||||
setDisplayed(received ? navbarLoggedIn : navbarNotLoggedIn);
|
||||
setDisplayed(received ? variants.loggedin : variants.notloggedin);
|
||||
}, [received, setReceived]);
|
||||
|
||||
return displayed || <p>Loading...</p>;
|
||||
|
||||
53
client/src/components/ui/Navbar/variants.tsx
Normal file
53
client/src/components/ui/Navbar/variants.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { attemptLogout } from "../../../util/apiUtils";
|
||||
import { NavbarType } from "../../../util/types";
|
||||
import Button from "../Button";
|
||||
|
||||
const LoggedIn: NavbarType = ({ received, liftChange, navigate }) => {
|
||||
const handleLogout = async () => {
|
||||
const success = await attemptLogout();
|
||||
if (success) liftChange!(undefined);
|
||||
navigate('/');
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {received?.firstname}.</p>
|
||||
<span id="search-icon"></span>
|
||||
<Button onClick={() => navigate('/profile')}>Profile</Button>
|
||||
<Button onClick={handleLogout}>Log Out</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const NotLoggedIn: NavbarType = ({ navigate }) => {
|
||||
return (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className='navbar-block'>
|
||||
<button onClick={() => navigate('/login')}>LOG IN</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Registering: NavbarType = ({ received, navigate }) => {
|
||||
return (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {received?.firstname}.</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { LoggedIn, NotLoggedIn, Registering }
|
||||
@@ -1,9 +1,19 @@
|
||||
import Button from "./Button";
|
||||
import Card from "./Card";
|
||||
import Divider from "./Divider";
|
||||
import Form from "./Form";
|
||||
import Navbar from "./Navbar";
|
||||
import Page from "./Page";
|
||||
import Panel from "./Panel";
|
||||
import UserCard from "./UserCard";
|
||||
|
||||
export {
|
||||
Button,
|
||||
Card,
|
||||
Divider,
|
||||
Form,
|
||||
Navbar,
|
||||
Page,
|
||||
Panel
|
||||
Panel,
|
||||
UserCard
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { FC, ReactNode } from "react";
|
||||
import { Dispatch, FC, ReactNode, SetStateAction } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { IUser } from "../schemas";
|
||||
|
||||
interface PortalBase {
|
||||
@@ -18,8 +19,15 @@ interface UserCardProps extends PortalBase {
|
||||
user: IUser
|
||||
}
|
||||
|
||||
interface NavbarProps {
|
||||
received: IUser | undefined
|
||||
navigate: (path: string) => void
|
||||
liftChange?: (newValue: IUser | undefined) => void
|
||||
}
|
||||
|
||||
export type PageComponent = FC<PortalBase>
|
||||
export type PanelComponent = FC<PortalBase>
|
||||
export type ButtonComponent = FC<ButtonParams>
|
||||
export type ProtectPortal = FC<MultiChildPortal>
|
||||
export type UserCardType = FC<UserCardProps>
|
||||
export type UserCardType = FC<UserCardProps>
|
||||
export type NavbarType = FC<NavbarProps>
|
||||
Reference in New Issue
Block a user