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}