diff --git a/src/Login.tsx b/src/Login.tsx new file mode 100644 index 0000000..31ae4ea --- /dev/null +++ b/src/Login.tsx @@ -0,0 +1,86 @@ +import { FormEvent, useContext, useState } from "react"; +import { useNavigate } from "react-router"; +import { currentUser, login, LoginRequest, User } from "./api"; + +export interface LoginProps { + onLogin: (user: User) => void; +} + +export const Login = ({ onLogin }: LoginProps) => { + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + async function doLogin() { + setLoading(true); + setError(null); + const timeout = new Promise((r) => setTimeout(r, 1500)); + let user: User; + try { + login({ username, password }); + user = await currentUser(); + } catch (e) { + await timeout; + setError(e); + setLoading(false); + return + } + + await timeout; + onLogin(user); + } + + function handleClick() { + doLogin(); + } + + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + doLogin(); + } + + return ( +
+
+ setUsername(evt.target.value)} /> +
+
+ setPassword(evt.target.value)} /> +
+ + {loading && } + + ) +} + +/* +export default function Login(props: { onLogin: (user: User) => void }) { + const { onLogin } = props; + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + + async function handleLogin(e: FormEvent) { + e.preventDefault() + const timeout = new Promise((r) => setTimeout(r, 1500)); + let user: User; + try { + login({ username, password }) + user = await currentUser() + } catch (e) { await timeout; return } + await timeout; + onLogin(user); + } + + return
+
+
+ setUsername(evt.target.value)} /> +
+
+ setPassword(evt.target.value)} /> +
+ +
+
+} */ diff --git a/src/Session.tsx b/src/Session.tsx new file mode 100644 index 0000000..4b080bb --- /dev/null +++ b/src/Session.tsx @@ -0,0 +1,40 @@ +import { createContext, ReactNode, useContext, useLayoutEffect, useState } from "react"; +import { currentUser, User } from "./api"; +import { Login } from "./Login"; + +export interface SessionProviderProps { + children: ReactNode; +} + +const sessionContext = createContext(null); + +export function SessionProvider(props: SessionProviderProps) { + const { children } = props; + + const [user, setUser] = useState(null); + const [err, setErr] = useState(null); + + function loadUser() { + currentUser() + .then((user) => { setUser(user); setErr(null); }) + .catch((err) => { setUser(null); setErr(err); }); + } + + useLayoutEffect(() => { loadUser(); }, [err]); + + function onLogin(user: User) { + setUser(user); + setErr(null); + } + + let content: ReactNode; + if (!err && !user) content = ; + else if (err) content = ; + else content = {children}; + + return content; +} + +export function useSession() { + return useContext(sessionContext); +}