import { FormEvent, useEffect, useState } from "react" import { Button, Input, Text, Note } from "@geist-ui/core" import styles from "./auth.module.css" import { useRouter } from "next/router" import Link from "../Link" import Cookies from "js-cookie" import useSignedIn from "@lib/hooks/use-signed-in" const NO_EMPTY_SPACE_REGEX = /^\S*$/ const ERROR_MESSAGE = "Provide a non empty username and a password with at least 6 characters" const Auth = ({ page }: { page: "signup" | "signin" }) => { const router = useRouter() const [username, setUsername] = useState("") const [password, setPassword] = useState("") const [serverPassword, setServerPassword] = useState("") const [errorMsg, setErrorMsg] = useState("") const [requiresServerPassword, setRequiresServerPassword] = useState(false) const signingIn = page === "signin" const { signin } = useSignedIn() useEffect(() => { async function fetchRequiresPass() { if (!signingIn) { const resp = await fetch("/server-api/auth/requires-passcode", { method: "GET" }) if (resp.ok) { const res = await resp.json() setRequiresServerPassword(res.requiresPasscode) } else { setErrorMsg("Something went wrong. Is the server running?") } } } fetchRequiresPass() }, [page, signingIn]) const handleJson = (json: any) => { signin(json.token) Cookies.set("drift-userid", json.userId) router.push("/new") } const handleSubmit = async (e: FormEvent<HTMLFormElement>) => { e.preventDefault() if ( !signingIn && (!NO_EMPTY_SPACE_REGEX.test(username) || password.length < 6) ) return setErrorMsg(ERROR_MESSAGE) if ( !signingIn && requiresServerPassword && !NO_EMPTY_SPACE_REGEX.test(serverPassword) ) return setErrorMsg(ERROR_MESSAGE) else setErrorMsg("") const reqOpts = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username, password, serverPassword }) } try { const signUrl = signingIn ? "/server-api/auth/signin" : "/server-api/auth/signup" const resp = await fetch(signUrl, reqOpts) const json = await resp.json() if (!resp.ok) throw new Error(json.error.message) handleJson(json) } catch (err: any) { setErrorMsg(err.message ?? "Something went wrong") } } return ( <div className={styles.container}> <div className={styles.form}> <div className={styles.formContentSpace}> <h1>{signingIn ? "Sign In" : "Sign Up"}</h1> </div> <form onSubmit={handleSubmit}> <div className={styles.formGroup}> <Input htmlType="text" id="username" value={username} onChange={(event) => setUsername(event.target.value)} placeholder="Username" required scale={4 / 3} /> <Input htmlType="password" id="password" value={password} onChange={(event) => setPassword(event.target.value)} placeholder="Password" required scale={4 / 3} /> {requiresServerPassword && ( <Input htmlType="password" id="server-password" value={serverPassword} onChange={(event) => setServerPassword(event.target.value)} placeholder="Server Password" required scale={4 / 3} /> )} <Button type="success" htmlType="submit"> {signingIn ? "Sign In" : "Sign Up"} </Button> </div> <div className={styles.formContentSpace}> {signingIn ? ( <Text> Don't have an account?{" "} <Link color href="/signup"> Sign up </Link> </Text> ) : ( <Text> Already have an account?{" "} <Link color href="/signin"> Sign in </Link> </Text> )} </div> {errorMsg && ( <Note scale={0.75} type="error"> {errorMsg} </Note> )} </form> </div> </div> ) } export default Auth