import {
useState,
useEffect,
useRef,
SyntheticEvent,
MouseEventHandler,
} from "react";
import { useLocation, Link, Navigate } from "react-router-dom";
import { useAuth } from "../useAuth";
import { unauthenticatedEndpoint, useUnauthenticatedRequest } from "../util";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition } from "@fortawesome/free-brands-svg-icons";
import { faSignInAlt } from "@fortawesome/free-solid-svg-icons";
interface OAuthProviders {
providers: string[];
}
export default function Register() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState<boolean>(false);
const [complete, setComplete] = useState<boolean>(false);
const handleSubmit = async (evt: SyntheticEvent) => {
evt.preventDefault();
setError("");
setLoading(true);
try {
let res = await fetch(unauthenticatedEndpoint("auth/register/password"), {
method: "POST",
headers: {
"Content-Type": "application/json",
"User-Agent": window.navigator.userAgent,
},
body: JSON.stringify({ username, password }),
});
let json = await res.json();
if (json.error) {
throw new Error(json.error);
} else if (!json.success) {
throw new Error("Failed to register, please try again later.");
} else {
setComplete(true);
}
} catch (e: any) {
setError(e.message);
} finally {
setLoading(false);
}
};
if (complete) {
return (
<Navigate
to="/login"
state={{
prompt: {
message: "Successfully registered, please login.",
kind: "success",
},
}}
/>
);
}
return (
<div className="p-4 min-vh-100 d-flex justify-content-center align-items-center">
<div>
<h1>chartered ✈️</h1>
<h6>a private, authenticated cargo registry</h6>
<div
className="card border-0 shadow-sm text-black p-2"
style={{ width: "40rem" }}
>
<div className="card-body">
<div
className="alert alert-danger alert-dismissible"
role="alert"
style={{ display: error ? "block" : "none" }}
>
{error}
<button
type="button"
className="btn-close"
aria-label="Close"
onClick={() => setError("")}
/>
</div>
<form onSubmit={handleSubmit}>
<div className="form-floating">
<input
type="text"
className="form-control"
placeholder="john.smith"
id="username"
disabled={loading}
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<label htmlFor="username" className="form-label">
Username
</label>
</div>
<div className="form-floating mt-2">
<input
type="password"
className="form-control"
placeholder="••••••••••••"
id="password"
disabled={loading}
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<label htmlFor="password" className="form-label">
Password
</label>
</div>
<ButtonOrSpinner
type="submit"
variant="primary"
disabled={loading}
showSpinner={loading}
text={`Register`}
icon={faSignInAlt}
onClick={handleSubmit}
/>
</form>
</div>
</div>
</div>
</div>
);
}
function ButtonOrSpinner({
type,
variant,
disabled,
showSpinner,
text,
icon,
background,
onClick,
}: {
type: "button" | "submit";
variant: string;
disabled: boolean;
showSpinner: boolean;
text: string;
icon?: IconDefinition;
background?: string;
onClick: MouseEventHandler<HTMLButtonElement>;
}) {
if (showSpinner) {
return (
<div
className="spinner-border text-primary mt-3 m-auto d-block"
role="status"
>
<span className="visually-hidden">Logging in...</span>
</div>
);
}
if (type) {
return (
<button
type={type}
disabled={disabled}
onClick={onClick}
className={`btn btn-lg mt-2 btn-${variant} w-100`}
style={{ background, borderColor: background }}
>
{icon ? <FontAwesomeIcon icon={icon} className="me-2" /> : <></>}
{text}
</button>
);
}
return <></>;
}