1- import { useForm } from "@tanstack/react-form" ;
2- import { Link , useNavigate } from "@tanstack/react-router" ;
3- import { toast } from "sonner" ;
4- import { z } from "zod" ;
5-
6- import { authClient } from "@/lib/auth-client" ;
1+ import { Link } from "@tanstack/react-router" ;
72
83import { Button } from "./ui/button" ;
9- import { Input } from "./ui/input" ;
10- import { Label } from "./ui/label" ;
11-
12- function SignUpGoogleIcon ( ) {
13- return (
14- < svg width = "18" height = "18" viewBox = "0 0 18 18" fill = "none" >
15- < path
16- d = "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844a4.14 4.14 0 0 1-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615Z"
17- fill = "#4285F4"
18- />
19- < path
20- d = "M9 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18Z"
21- fill = "#34A853"
22- />
23- < path
24- d = "M3.964 10.706A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.706V4.962H.957A8.997 8.997 0 0 0 0 9c0 1.452.348 2.827.957 4.038l3.007-2.332Z"
25- fill = "#FBBC05"
26- />
27- < path
28- d = "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.962L3.964 7.294C4.672 5.166 6.656 3.58 9 3.58Z"
29- fill = "#EA4335"
30- />
31- </ svg >
32- ) ;
33- }
34-
35- function SignUpGithubIcon ( ) {
36- return (
37- < svg width = "18" height = "18" viewBox = "0 0 18 18" fill = "currentColor" >
38- < path
39- fillRule = "evenodd"
40- clipRule = "evenodd"
41- d = "M9 0C4.03 0 0 4.03 0 9c0 3.978 2.579 7.35 6.154 8.543.45.083.614-.195.614-.433 0-.213-.008-.78-.012-1.53-2.503.544-3.032-1.206-3.032-1.206-.41-1.04-1-1.317-1-1.317-.816-.558.062-.546.062-.546.903.063 1.378.927 1.378.927.802 1.374 2.105.977 2.617.747.082-.581.314-.977.571-1.201-1.998-.227-4.1-1-4.1-4.448 0-.983.351-1.786.927-2.416-.093-.228-.402-1.143.088-2.382 0 0 .756-.242 2.475.923A8.631 8.631 0 0 1 9 4.365a8.63 8.63 0 0 1 2.258.304c1.718-1.165 2.473-.923 2.473-.923.491 1.24.182 2.154.089 2.382.577.63.926 1.433.926 2.416 0 3.457-2.105 4.218-4.11 4.44.323.278.611.828.611 1.668 0 1.204-.01 2.175-.01 2.471 0 .24.162.52.619.432C15.424 16.347 18 12.975 18 9c0-4.97-4.03-9-9-9Z"
42- />
43- </ svg >
44- ) ;
45- }
464
475export function SignUpForm ( ) {
48- const navigate = useNavigate ( ) ;
49-
50- const form = useForm ( {
51- defaultValues : {
52- name : "" ,
53- email : "" ,
54- password : "" ,
55- } ,
56- onSubmit : async ( { value } ) => {
57- await authClient . signUp . email (
58- {
59- email : value . email ,
60- password : value . password ,
61- name : value . name ,
62- } ,
63- {
64- onSuccess : ( ) => {
65- navigate ( { to : "/office" } ) ;
66- toast . success ( "Account created successfully" ) ;
67- } ,
68- onError : ( error ) => {
69- toast . error ( error . error . message || error . error . statusText ) ;
70- } ,
71- } ,
72- ) ;
73- } ,
74- validators : {
75- onSubmit : z . object ( {
76- name : z . string ( ) . min ( 2 , "Name must be at least 2 characters" ) ,
77- email : z . email ( "Invalid email address" ) ,
78- password : z . string ( ) . min ( 8 , "Password must be at least 8 characters" ) ,
79- } ) ,
80- } ,
81- } ) ;
82-
83- const signUpSocialHandler = async ( provider : "google" | "github" ) => {
84- await authClient . signIn . social (
85- { provider, callbackURL : "/office" } ,
86- {
87- onError : ( error ) => {
88- toast . error ( error . error . message || error . error . statusText ) ;
89- } ,
90- } ,
91- ) ;
92- } ;
93-
946 return (
957 < div className = "flex min-h-svh items-center justify-center bg-background px-4" >
968 < div className = "w-full max-w-md" >
@@ -110,140 +22,28 @@ export function SignUpForm() {
11022 </ h1 >
11123 < p className = "mt-2 text-sm text-muted-foreground" > Sign up to get started.</ p >
11224
113- { /* Form */ }
114- < form
115- onSubmit = { ( e ) => {
116- e . preventDefault ( ) ;
117- e . stopPropagation ( ) ;
118- form . handleSubmit ( ) ;
119- } }
120- className = "mt-8 space-y-5"
121- >
122- < form . Field name = "name" >
123- { ( field ) => (
124- < div className = "space-y-2" >
125- < Label
126- htmlFor = { field . name }
127- className = "font-mono text-xs font-semibold uppercase tracking-widest text-muted-foreground"
128- >
129- Full Name
130- </ Label >
131- < Input
132- id = { field . name }
133- name = { field . name }
134- type = "text"
135- placeholder = "John Doe"
136- value = { field . state . value }
137- onBlur = { field . handleBlur }
138- onChange = { ( e ) => field . handleChange ( e . target . value ) }
139- className = "h-12 border-2 border-border bg-background px-4 text-sm text-foreground placeholder:text-muted-foreground/50"
140- />
141- { field . state . meta . errors . map ( ( error ) => (
142- < p key = { error ?. message } className = "font-mono text-xs text-destructive" >
143- { error ?. message }
144- </ p >
145- ) ) }
146- </ div >
147- ) }
148- </ form . Field >
149-
150- < form . Field name = "email" >
151- { ( field ) => (
152- < div className = "space-y-2" >
153- < Label
154- htmlFor = { field . name }
155- className = "font-mono text-xs font-semibold uppercase tracking-widest text-muted-foreground"
156- >
157- Email Address
158- </ Label >
159- < Input
160- id = { field . name }
161- name = { field . name }
162- type = "email"
163- placeholder = "paul@email.com"
164- value = { field . state . value }
165- onBlur = { field . handleBlur }
166- onChange = { ( e ) => field . handleChange ( e . target . value ) }
167- className = "h-12 border-2 border-border bg-background px-4 text-sm text-foreground placeholder:text-muted-foreground/50"
168- />
169- { field . state . meta . errors . map ( ( error ) => (
170- < p key = { error ?. message } className = "font-mono text-xs text-destructive" >
171- { error ?. message }
172- </ p >
173- ) ) }
174- </ div >
175- ) }
176- </ form . Field >
177-
178- < form . Field name = "password" >
179- { ( field ) => (
180- < div className = "space-y-2" >
181- < Label
182- htmlFor = { field . name }
183- className = "font-mono text-xs font-semibold uppercase tracking-widest text-muted-foreground"
184- >
185- Password
186- </ Label >
187- < Input
188- id = { field . name }
189- name = { field . name }
190- type = "password"
191- placeholder = "••••••••"
192- value = { field . state . value }
193- onBlur = { field . handleBlur }
194- onChange = { ( e ) => field . handleChange ( e . target . value ) }
195- className = "h-12 border-2 border-border bg-background px-4 text-sm text-foreground placeholder:text-muted-foreground/50"
196- />
197- { field . state . meta . errors . map ( ( error ) => (
198- < p key = { error ?. message } className = "font-mono text-xs text-destructive" >
199- { error ?. message }
200- </ p >
201- ) ) }
202- </ div >
203- ) }
204- </ form . Field >
205-
206- < form . Subscribe >
207- { ( state ) => (
208- < Button
209- type = "submit"
210- variant = "default"
211- size = "lg"
212- disabled = { ! state . canSubmit || state . isSubmitting }
213- className = "h-12 w-full border-foreground bg-foreground font-mono text-sm font-semibold uppercase tracking-widest text-background"
214- >
215- { state . isSubmitting ? "Creating account..." : "Sign up" }
216- </ Button >
217- ) }
218- </ form . Subscribe >
219- </ form >
220-
221- { /* Separator */ }
222- < div className = "my-6 border-t-2 border-border" />
223-
224- { /* Social login buttons */ }
225- < div className = "space-y-3" >
226- < Button
227- type = "button"
228- variant = "outline"
229- size = "lg"
230- onClick = { ( ) => signUpSocialHandler ( "google" ) }
231- className = "h-12 w-full font-mono text-sm tracking-wide"
232- >
233- < SignUpGoogleIcon />
234- < span className = "ml-3" > Sign up with Google</ span >
235- </ Button >
25+ { /* Disabled notice */ }
26+ < div className = "mt-8 border-2 border-border bg-muted/50 p-6 text-center" >
27+ < p className = "font-mono text-sm font-semibold text-foreground" >
28+ Sign-ups are currently disabled
29+ </ p >
30+ < p className = "mt-2 text-sm text-muted-foreground" >
31+ Only existing users can sign in. Registration is closed.
32+ </ p >
33+ </ div >
23634
237- < Button
238- type = "button"
239- variant = "outline"
240- size = "lg"
241- onClick = { ( ) => signUpSocialHandler ( "github" ) }
242- className = "h-12 w-full font-mono text-sm tracking-wide"
243- >
244- < SignUpGithubIcon />
245- < span className = "ml-3" > Sign up with GitHub</ span >
246- </ Button >
35+ { /* Sign in redirect */ }
36+ < div className = "mt-6" >
37+ < Link to = "/sign-in" >
38+ < Button
39+ type = "button"
40+ variant = "default"
41+ size = "lg"
42+ className = "h-12 w-full border-foreground bg-foreground font-mono text-sm font-semibold uppercase tracking-widest text-background"
43+ >
44+ Go to sign in
45+ </ Button >
46+ </ Link >
24747 </ div >
24848 </ div >
24949
0 commit comments