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
 35// Sync rules with protocol.go.
 36export function LoginForm(props: LoginFormProps) {
 37    const classes = useStyles();
 38    const { control, handleSubmit, errors, setValue, register } = useForm<LoginFormData>({});
 39    React.useEffect(() => register({ name: formName('create') }), [register]);
 40    const doSubmit = handleSubmit(props.onSubmit);
 41
 42    return (
 43        <form onSubmit={(e) => e.preventDefault()}>
 44            {props.existingRoom ? (
 45                <div>
 46                    <em>Joining existing game; please choose a nickname.</em>
 47                </div>
 48            ) : null}
 49
 50            <div className={props.existingRoom ? classes.padBottom : undefined}>
 51                <Controller
 52                    control={control}
 53                    as={TextField}
 54                    name={formName('nickname')}
 55                    label="Nickname"
 56                    defaultValue=""
 57                    error={!!errors.nickname}
 58                    rules={{ required: true, minLength: 1, maxLength: 16 }}
 59                    fullWidth={true}
 60                    inputProps={noComplete}
 61                    autoFocus
 62                />
 63            </div>
 64
 65            {props.existingRoom ? null : (
 66                <>
 67                    <div>
 68                        <Controller
 69                            control={control}
 70                            as={TextField}
 71                            name={formName('roomName')}
 72                            label="Room name"
 73                            defaultValue=""
 74                            error={!!errors.roomName}
 75                            rules={{ required: true, minLength: 1, maxLength: 20 }}
 76                            fullWidth={true}
 77                            inputProps={noComplete}
 78                        />
 79                    </div>
 80
 81                    <div className={classes.padBottom}>
 82                        <Controller
 83                            control={control}
 84                            as={TextField}
 85                            name={formName('roomPass')}
 86                            label="Password"
 87                            defaultValue=""
 88                            type="password"
 89                            error={!!errors.roomPass}
 90                            rules={{ required: true, minLength: 1 }}
 91                            fullWidth={true}
 92                            inputProps={noComplete}
 93                        />
 94                    </div>
 95                </>
 96            )}
 97
 98            {props.errorMessage && (
 99                <div className={classes.padBottom}>
100                    <em>{props.errorMessage}</em>
101                </div>
102            )}
103
104            <div>
105                <ButtonGroup variant="contained">
106                    <Button
107                        type="submit"
108                        onClick={() => {
109                            setValue(formName('create'), false);
110                            doSubmit();
111                        }}
112                    >
113                        Join game
114                    </Button>
115
116                    {props.existingRoom ? null : (
117                        <Button
118                            type="button"
119                            onClick={() => {
120                                setValue(formName('create'), true);
121                                doSubmit();
122                            }}
123                        >
124                            Create new game
125                        </Button>
126                    )}
127                </ButtonGroup>
128            </div>
129        </form>
130    );
131}