@@ -13,7 +13,7 @@ import { zodRequireEmail } from '@/lib/zod/email';
1313import { zodRequirePassword } from '@/lib/zod/password' ;
1414import { zodResolver } from '@hookform/resolvers/zod' ;
1515import { Link , useNavigate , useSearch } from '@tanstack/react-router' ;
16- import { useCallback , useEffect } from 'react' ;
16+ import { MouseEvent , useCallback , useEffect , useState } from 'react' ;
1717import { useForm } from 'react-hook-form' ;
1818import { z } from 'zod' ;
1919import { GitHubAuthenticationButton } from './components/GitHubAuthenticationButton' ;
@@ -56,6 +56,8 @@ const SignUpSchema = z.object({
5656export function SignUp ( ) {
5757 const navigate = useNavigate ( ) ;
5858 const { email : searchEmail , me : formPersistenceEmail } = useSearch ( { strict : false } ) ;
59+ const [ flashTerms , setFlashTerms ] = useState ( false ) ;
60+
5961 const methods = useForm ( {
6062 resolver : zodResolver ( SignUpSchema ) ,
6163 defaultValues : {
@@ -69,6 +71,7 @@ export function SignUp() {
6971 } ) ;
7072
7173 const email = methods . watch ( 'email' ) ;
74+ const acceptTerms = methods . watch ( 'acceptTerms' ) ;
7275 const { setFocus, control, handleSubmit } = methods ;
7376
7477 useEffect ( ( ) => {
@@ -95,18 +98,82 @@ export function SignUp() {
9598 } ) ;
9699 } , [ navigate , submitSignUpData ] ) ;
97100
101+ const onOAuthClick = useCallback ( ( e : MouseEvent ) => {
102+ if ( ! acceptTerms ) {
103+ setFlashTerms ( true ) ;
104+ setTimeout ( ( ) => setFlashTerms ( false ) , 1000 ) ;
105+ e . preventDefault ( ) ;
106+ return false ;
107+ }
108+ } , [ acceptTerms ] ) ;
109+
110+ const termsCheckbox = (
111+ < FormField
112+ control = { control }
113+ name = "acceptTerms"
114+ render = { ( { field } ) => (
115+ < FormItem
116+ className = { `flex flex-row items-start space-x-3 space-y-0 p-1 transition-colors duration-300 ${
117+ flashTerms ? 'bg-red-500/20 animate-pulse rounded' : ''
118+ } `}
119+ >
120+ < FormControl >
121+ < Input
122+ type = "checkbox"
123+ className = "size-4 rounded border-gray-300 bg-white text-purple-600 focus:ring-purple-500"
124+ checked = { field . value }
125+ onChange = { field . onChange }
126+ />
127+ </ FormControl >
128+ < div className = "space-y-1 leading-none" >
129+ < FormLabel className = "text-xs font-normal" >
130+ I accept the{ ' ' }
131+ < a
132+ href = "https://www.harper.fast/resources/privacy-policy"
133+ target = "_blank"
134+ rel = "noreferrer"
135+ className = "underline hover:text-blue-300"
136+ >
137+ Privacy Policy
138+ </ a > { ' ' }
139+ and{ ' ' }
140+ < a
141+ href = "https://www.harper.fast/resources/paas-terms-of-service"
142+ target = "_blank"
143+ rel = "noreferrer"
144+ className = "underline hover:text-blue-300"
145+ >
146+ Terms of Service
147+ </ a >
148+ </ FormLabel >
149+ < FormMessage />
150+ </ div >
151+ </ FormItem >
152+ ) }
153+ />
154+ ) ;
155+
98156 return (
99157 < div className = "text-white w-xs" >
100158 < h2 className = "text-2xl font-light" > Sign up for Harper Fabric</ h2 >
101159
102- < div className = "flex flex-col gap-2 my-6" >
103- < GoogleAuthenticationButton text = "Sign up with Google" />
104- < GitHubAuthenticationButton text = "Sign up with GitHub" />
105- </ div >
160+ < Form { ...methods } >
161+ < div className = "flex flex-col gap-2 my-6" >
162+ { termsCheckbox }
163+ < GoogleAuthenticationButton
164+ text = "Sign up with Google"
165+ disabled = { ! acceptTerms }
166+ onClick = { onOAuthClick }
167+ />
168+ < GitHubAuthenticationButton
169+ text = "Sign up with GitHub"
170+ disabled = { ! acceptTerms }
171+ onClick = { onOAuthClick }
172+ />
173+ </ div >
106174
107- < hr className = "border-gray-600" />
175+ < hr className = "border-gray-600" />
108176
109- < Form { ...methods } >
110177 < form
111178 id = "auth-signup-form"
112179 name = "auth-signup-form"
@@ -206,45 +273,7 @@ export function SignUp() {
206273 </ FormItem >
207274 ) }
208275 />
209- < FormField
210- control = { control }
211- name = "acceptTerms"
212- render = { ( { field } ) => (
213- < FormItem className = "flex flex-row items-start space-x-3 space-y-0 p-1" >
214- < FormControl >
215- < Input
216- type = "checkbox"
217- className = "size-4 rounded border-gray-300 bg-white text-purple-600 focus:ring-purple-500"
218- checked = { field . value }
219- onChange = { field . onChange }
220- />
221- </ FormControl >
222- < div className = "space-y-1 leading-none" >
223- < FormLabel className = "text-xs font-normal" >
224- I accept the{ ' ' }
225- < a
226- href = "https://www.harper.fast/resources/privacy-policy"
227- target = "_blank"
228- rel = "noreferrer"
229- className = "underline hover:text-blue-300"
230- >
231- Privacy Policy
232- </ a > { ' ' }
233- and{ ' ' }
234- < a
235- href = "https://www.harper.fast/resources/paas-terms-of-service"
236- target = "_blank"
237- rel = "noreferrer"
238- className = "underline hover:text-blue-300"
239- >
240- Terms of Service
241- </ a >
242- </ FormLabel >
243- < FormMessage />
244- </ div >
245- </ FormItem >
246- ) }
247- />
276+ { termsCheckbox }
248277
249278 < Button type = "submit" variant = "submit" className = "w-full rounded-full my-4" >
250279 Sign Up For Free
0 commit comments