1
- import type {
2
- ActionFunction ,
3
- LinksFunction ,
4
- MetaFunction ,
5
- } from "@remix-run/node" ;
6
- import { json } from "@remix-run/node" ;
7
- import { Form , Link , useActionData , useSearchParams } from "@remix-run/react" ;
1
+ import type { ActionArgs , LinksFunction , MetaFunction } from "@remix-run/node" ;
2
+ import { Link , useActionData , useSearchParams } from "@remix-run/react" ;
8
3
9
- import { login , createUserSession , register } from "~/utils/session.server " ;
4
+ import stylesUrl from "~/styles/login.css " ;
10
5
import { db } from "~/utils/db.server" ;
6
+ import { badRequest } from "~/utils/request.server" ;
7
+ import { createUserSession , login , register } from "~/utils/session.server" ;
11
8
12
- import stylesUrl from "../styles/login.css" ;
9
+ export const meta : MetaFunction = ( ) => ( {
10
+ description : "Login to submit your own jokes to Remix Jokes!" ,
11
+ title : "Remix Jokes | Login" ,
12
+ } ) ;
13
13
14
- export const meta : MetaFunction = ( ) => {
15
- return {
16
- title : "Remix Jokes | Login" ,
17
- description : "Login to submit your own jokes to Remix Jokes!" ,
18
- } ;
19
- } ;
20
-
21
- export const links : LinksFunction = ( ) => {
22
- return [ { rel : "stylesheet" , href : stylesUrl } ] ;
23
- } ;
14
+ export const links : LinksFunction = ( ) => [
15
+ { rel : "stylesheet" , href : stylesUrl } ,
16
+ ] ;
24
17
25
18
function validateUsername ( username : unknown ) {
26
19
if ( typeof username !== "string" || username . length < 3 ) {
@@ -34,28 +27,15 @@ function validatePassword(password: unknown) {
34
27
}
35
28
}
36
29
37
- function validateUrl ( url : any ) {
30
+ function validateUrl ( url : string ) {
38
31
const urls = [ "/jokes" , "/" , "https://remix.run" ] ;
39
32
if ( urls . includes ( url ) ) {
40
33
return url ;
41
34
}
42
35
return "/jokes" ;
43
36
}
44
37
45
- type ActionData = {
46
- formError ?: string ;
47
- fieldErrors ?: { username : string | undefined ; password : string | undefined } ;
48
- fields ?: { loginType : string ; username : string ; password : string } ;
49
- } ;
50
-
51
- /**
52
- * This helper function gives us typechecking for our ActionData return
53
- * statements, while still returning the accurate HTTP status, 400 Bad Request,
54
- * to the client.
55
- */
56
- const badRequest = ( data : ActionData ) => json ( data , { status : 400 } ) ;
57
-
58
- export const action : ActionFunction = async ( { request } ) => {
38
+ export const action = async ( { request } : ActionArgs ) => {
59
39
const form = await request . formData ( ) ;
60
40
const loginType = form . get ( "loginType" ) ;
61
41
const username = form . get ( "username" ) ;
@@ -67,7 +47,11 @@ export const action: ActionFunction = async ({ request }) => {
67
47
typeof password !== "string" ||
68
48
typeof redirectTo !== "string"
69
49
) {
70
- return badRequest ( { formError : `Form not submitted correctly.` } ) ;
50
+ return badRequest ( {
51
+ fieldErrors : null ,
52
+ fields : null ,
53
+ formError : `Form not submitted correctly.` ,
54
+ } ) ;
71
55
}
72
56
73
57
const fields = { loginType, username, password } ;
@@ -76,14 +60,15 @@ export const action: ActionFunction = async ({ request }) => {
76
60
password : validatePassword ( password ) ,
77
61
} ;
78
62
if ( Object . values ( fieldErrors ) . some ( Boolean ) ) {
79
- return badRequest ( { fieldErrors, fields } ) ;
63
+ return badRequest ( { fieldErrors, fields, formError : null } ) ;
80
64
}
81
65
82
66
switch ( loginType ) {
83
67
case "login" : {
84
68
const user = await login ( { username, password } ) ;
85
69
if ( ! user ) {
86
70
return badRequest ( {
71
+ fieldErrors : null ,
87
72
fields,
88
73
formError : `Username/Password combination is incorrect` ,
89
74
} ) ;
@@ -94,33 +79,39 @@ export const action: ActionFunction = async ({ request }) => {
94
79
const userExists = await db . user . findFirst ( { where : { username } } ) ;
95
80
if ( userExists ) {
96
81
return badRequest ( {
82
+ fieldErrors : null ,
97
83
fields,
98
84
formError : `User with username ${ username } already exists` ,
99
85
} ) ;
100
86
}
101
87
const user = await register ( { username, password } ) ;
102
88
if ( ! user ) {
103
89
return badRequest ( {
90
+ fieldErrors : null ,
104
91
fields,
105
92
formError : `Something went wrong trying to create a new user.` ,
106
93
} ) ;
107
94
}
108
95
return createUserSession ( user . id , redirectTo ) ;
109
96
}
110
97
default : {
111
- return badRequest ( { fields, formError : `Login type invalid` } ) ;
98
+ return badRequest ( {
99
+ fieldErrors : null ,
100
+ fields,
101
+ formError : `Login type invalid` ,
102
+ } ) ;
112
103
}
113
104
}
114
105
} ;
115
106
116
107
export default function Login ( ) {
117
- const actionData = useActionData < ActionData > ( ) ;
108
+ const actionData = useActionData < typeof action > ( ) ;
118
109
const [ searchParams ] = useSearchParams ( ) ;
119
110
return (
120
111
< div className = "container" >
121
112
< div className = "content" data-light = "" >
122
113
< h1 > Login</ h1 >
123
- < Form method = "post" >
114
+ < form method = "post" >
124
115
< input
125
116
type = "hidden"
126
117
name = "redirectTo"
@@ -204,7 +195,7 @@ export default function Login() {
204
195
< button type = "submit" className = "button" >
205
196
Submit
206
197
</ button >
207
- </ Form >
198
+ </ form >
208
199
</ div >
209
200
< div className = "links" >
210
201
< ul >
0 commit comments