loginForm.tsx

  1import { Button, ButtonGroup, createStyles, makeStyles, TextField, Theme } from '@material-ui/core';
  2import * as React from 'react';
  3import { Controller, useForm } from 'react-hook-form';
  4
  5import { nameofFactory } from '../common';
  6
  7export interface LoginFormData {
  8    nickname: string;
  9    roomName: string;
 10    roomPass: string;
 11    create: boolean;
 12}
 13
 14const formName = nameofFactory<LoginFormData>();
 15
 16const noComplete = {
 17    autoComplete: 'off',
 18    'data-lpignore': 'true',
 19};
 20
 21const useStyles = makeStyles((theme: Theme) =>
 22    createStyles({
 23        padBottom: {
 24            marginBottom: theme.spacing(2),
 25        },
 26    })
 27);
 28
 29export interface LoginFormProps {
 30    existingRoom: boolean;
 31    onSubmit: (data: LoginFormData) => Promise<void>;
 32    errorMessage?: string;
 33}
 34
 35export function LoginForm(props: LoginFormProps) {
 36    const classes = useStyles();
 37    const { control, handleSubmit, errors, setValue, register } = useForm<LoginFormData>({});
 38    React.useEffect(() => register({ name: formName('create') }), [register]);
 39    const doSubmit = handleSubmit(props.onSubmit);
 40
 41    return (
 42        <form onSubmit={(e) => e.preventDefault()}>
 43            {props.existingRoom ? (
 44                <div>
 45                    <em>Joining existing game; please choose a nickname.</em>
 46                </div>
 47            ) : null}
 48
 49            <div className={props.existingRoom ? classes.padBottom : undefined}>
 50                <Controller
 51                    control={control}
 52                    as={TextField}
 53                    name={formName('nickname')}
 54                    label="Nickname"
 55                    defaultValue=""
 56                    error={!!errors.nickname}
 57                    rules={{ required: true, minLength: 3, maxLength: 16 }}
 58                    fullWidth={true}
 59                    inputProps={noComplete}
 60                    autoFocus
 61                />
 62            </div>
 63
 64            {props.existingRoom ? null : (
 65                <>
 66                    <div>
 67                        <Controller
 68                            control={control}
 69                            as={TextField}
 70                            name={formName('roomName')}
 71                            label="Room name"
 72                            defaultValue=""
 73                            error={!!errors.roomName}
 74                            rules={{ required: true, minLength: 3, maxLength: 16 }}
 75                            fullWidth={true}
 76                            inputProps={noComplete}
 77                        />
 78                    </div>
 79
 80                    <div className={classes.padBottom}>
 81                        <Controller
 82                            control={control}
 83                            as={TextField}
 84                            name={formName('roomPass')}
 85                            label="Password"
 86                            defaultValue=""
 87                            type="password"
 88                            error={!!errors.roomPass}
 89                            rules={{ required: true, minLength: 1 }}
 90                            fullWidth={true}
 91                            inputProps={noComplete}
 92                        />
 93                    </div>
 94                </>
 95            )}
 96
 97            {props.errorMessage && (
 98                <div className={classes.padBottom}>
 99                    <em>{props.errorMessage}</em>
100                </div>
101            )}
102
103            <div>
104                <ButtonGroup variant="contained">
105                    <Button
106                        type="submit"
107                        onClick={() => {
108                            setValue(formName('create'), false);
109                            doSubmit();
110                        }}
111                    >
112                        Join game
113                    </Button>
114
115                    {props.existingRoom ? null : (
116                        <Button
117                            type="button"
118                            onClick={() => {
119                                setValue(formName('create'), true);
120                                doSubmit();
121                            }}
122                        >
123                            Create new game
124                        </Button>
125                    )}
126                </ButtonGroup>
127            </div>
128        </form>
129    );
130}