11"use client" ;
22
3- import { login , signup } from "./actions " ;
3+ import { useActionState , useState , Suspense } from "react " ;
44import { useSearchParams } from "next/navigation" ;
5- import { Suspense , useState } from "react " ;
5+ import { login , signup , type ActionState } from "./actions " ;
66import {
77 Card ,
88 CardContent ,
@@ -14,12 +14,28 @@ import { Input } from "@/components/ui/input";
1414import { Label } from "@/components/ui/label" ;
1515import { Button } from "@/components/ui/button" ;
1616
17+ function FieldError ( { errors } : { errors ?: string [ ] } ) {
18+ if ( ! errors ?. length ) return null ;
19+ return < p className = "text-sm text-destructive" > { errors [ 0 ] } </ p > ;
20+ }
21+
1722function LoginForm ( ) {
1823 const searchParams = useSearchParams ( ) ;
1924 const message = searchParams . get ( "message" ) ;
20- const error = searchParams . get ( "error" ) ;
2125 const [ mode , setMode ] = useState < "login" | "signup" > ( "login" ) ;
2226
27+ const [ loginState , loginAction ] = useActionState < ActionState , FormData > (
28+ login ,
29+ null
30+ ) ;
31+ const [ signupState , signupAction ] = useActionState < ActionState , FormData > (
32+ signup ,
33+ null
34+ ) ;
35+
36+ const state = mode === "login" ? loginState : signupState ;
37+ const action = mode === "login" ? loginAction : signupAction ;
38+
2339 return (
2440 < div className = "flex min-h-screen items-center justify-center p-4" >
2541 < Card className = "w-full max-w-md" >
@@ -34,67 +50,61 @@ function LoginForm() {
3450 </ CardDescription >
3551 </ CardHeader >
3652 < CardContent >
37- { error && (
38- < div className = "mb-4 rounded-md bg-destructive/10 p-3 text-sm text-destructive" >
39- { error }
40- </ div >
41- ) }
4253 { message && (
4354 < div className = "mb-4 rounded-md bg-green-500/10 p-3 text-sm text-green-700 dark:text-green-400" >
4455 { message }
4556 </ div >
4657 ) }
4758
48- < form className = "space-y-4" >
59+ < form action = { action } className = "space-y-4" noValidate >
4960 { mode === "signup" && (
5061 < div className = "flex gap-3" >
51- < div className = "space-y-2 flex-1" >
62+ < div className = "space-y-1 flex-1" >
5263 < Label htmlFor = "first_name" > First name</ Label >
5364 < Input
5465 id = "first_name"
5566 name = "first_name"
5667 type = "text"
57- required
5868 placeholder = "Jane"
5969 />
70+ < FieldError errors = { signupState ?. errors ?. firstName } />
6071 </ div >
61- < div className = "space-y-2 flex-1" >
72+ < div className = "space-y-1 flex-1" >
6273 < Label htmlFor = "last_name" > Last name</ Label >
6374 < Input
6475 id = "last_name"
6576 name = "last_name"
6677 type = "text"
67- required
6878 placeholder = "Doe"
6979 />
80+ < FieldError errors = { signupState ?. errors ?. lastName } />
7081 </ div >
7182 </ div >
7283 ) }
73- < div className = "space-y-2 " >
84+ < div className = "space-y-1 " >
7485 < Label htmlFor = "email" > Email</ Label >
7586 < Input
7687 id = "email"
7788 name = "email"
7889 type = "email"
79- required
8090 placeholder = "you@example.com"
8191 />
92+ < FieldError errors = { state ?. errors ?. email } />
8293 </ div >
83- < div className = "space-y-2 " >
94+ < div className = "space-y-1 " >
8495 < Label htmlFor = "password" > Password</ Label >
8596 < Input
8697 id = "password"
8798 name = "password"
8899 type = "password"
89- required
90- minLength = { 6 }
91100 placeholder = "••••••••"
92101 />
102+ < FieldError errors = { state ?. errors ?. password } />
93103 </ div >
94104 < div className = "flex flex-col gap-2 pt-2" >
95105 { mode === "login" ? (
96106 < >
97- < Button formAction = { login } > Log in</ Button >
107+ < Button type = "submit" > Log in</ Button >
98108 < Button
99109 type = "button"
100110 variant = "outline"
@@ -105,7 +115,7 @@ function LoginForm() {
105115 </ >
106116 ) : (
107117 < >
108- < Button formAction = { signup } > Sign up</ Button >
118+ < Button type = "submit" > Sign up</ Button >
109119 < Button
110120 type = "button"
111121 variant = "outline"
0 commit comments