import { useNavigate, useParams } from 'react-router-dom' import { useEffect, useRef, useState, FormEvent, useCallback, Ref } from 'react' import SingleColumnLayout from '../../../layouts/SingleColumnLayout.tsx' import TextInput from '../../../components/inputs/TextInput.tsx' import Button from '../../../components/buttons/Button.tsx' import AnchorButton from '../../../components/buttons/AnchorButton.tsx' import { invalid, valid, Validation } from '../../../utils/validation.ts' import { AuthService } from '../authService.ts' import LinkButton from '../../../components/buttons/LinkButton.tsx' import NavBar from '../../../components/NavBar.tsx' import NavButton from '../../../components/buttons/NavButton.tsx' const SignupCodeKey = 'signupCode' interface SignupPageProps { authService: AuthService } export default function SignupPage({ authService }: SignupPageProps) { const { code } = useParams() const [signupCode, setSignupCode] = useState(null) const [isSubmitting, setIsSubmitting] = useState(false) const [rememberMe, setRememberMe] = useState(false) const [error, setError] = useState('') const [username, setUsername, usernameError, validateUsername] = useValidatedInput(isValidUsername) const [password, setPassword, passwordError, validatePassword] = useValidatedInput(isValidPassword) const userNameInputRef = useRef(null) const passwordInputRef = useRef(null) const dialogRef = useRef(null) const navigate = useNavigate() useEffect(() => { if (signupCode) return let theSignupCode: string | null if (code) { theSignupCode = code setSignupCode(theSignupCode) localStorage.setItem(SignupCodeKey, theSignupCode) } else { theSignupCode = localStorage.getItem(SignupCodeKey) setSignupCode(theSignupCode) } if (!theSignupCode) { dialogRef.current?.showModal() } }, [code, signupCode]) useEffect(() => {}, [signupCode]) const onSubmit = async (e: FormEvent) => { e.preventDefault() if (!signupCode) { throw new Error("there's no code") } const isUsernameValid = validateUsername() const isPasswordValid = validatePassword() if (!isPasswordValid) { passwordInputRef.current?.focus() } if (!isUsernameValid) { userNameInputRef.current?.focus() } if (!isUsernameValid || !isPasswordValid) { return } setIsSubmitting(true) try { await authService.signup(username, password, signupCode, rememberMe) navigate('/') } catch (e: unknown) { const err = e as Error setError(err.message) } finally { setIsSubmitting(false) } } return ( home } >
setRememberMe(e.target.checked)} className="h-4 w-4" />
login instead? {error}

STOP !!!

You need an invitation to sign up

I'm surprised you even found your way here without one and honestly I'd prefer it if you would leave

If you do want to create an account, you should know who to contact

I'm sorry I'll go somewhere else :(
) } interface FormInputProps { id: string value: string onInput: (value: string) => void error: string | null type?: 'text' | 'password' ref: Ref } function FormInput({ id, value, onInput, error, type = 'text', ref }: FormInputProps) { return (
{error}
) } type UseValidateInputReturn = [string, (value: string) => void, string | null, () => boolean] function useValidatedInput(validator: (value: string) => Validation): UseValidateInputReturn { const [value, setValue] = useState('') const [error, setError] = useState(null) const [keepValidating, setKeepValidating] = useState(false) const validate = useCallback(() => { const { isValid, error } = validator(value) if (isValid) { setError(null) } else { // We only want to validate on input after they have invalidly submitted once. // It's annoying if we set error messages before they've even finished typing. setKeepValidating(true) setError(error) } return isValid }, [validator, value]) useEffect(() => { if (keepValidating) { validate() } }, [keepValidating, validate]) return [value, setValue, error, validate] } function isValidUsername(username: string): Validation { if (!username) return invalid('you need to enter a username :/') if (username.length < 3) { return invalid('not long enough :(') } const usernameRegex = /^[a-zA-Z0-9_-]+$/ if (usernameRegex.test(username)) { return valid() } else { return invalid("that's not a good username :'(") } } function isValidPassword(password: string): Validation { if (password.length >= 6) { return valid() } else { return invalid("that isn't a good password :/") } }