@@ -26,9 +26,17 @@ import { Button } from "@/components/ui/button";
2626import { Card , CardContent , CardDescription , CardHeader , CardTitle } from "@/components/ui/card" ;
2727import { Input } from "@/components/ui/input" ;
2828import { Label } from "@/components/ui/label" ;
29+ import { authClient } from "@/lib/auth/client" ;
2930
3031const emailPattern = / ^ [ ^ \s @ ] + @ [ ^ \s @ ] + \. [ ^ \s @ ] + $ / ;
3132
33+ function getSocialAuthErrorMessage ( error : unknown , fallbackMessage : string ) {
34+ if ( error instanceof Error && error . message ) {
35+ return error . message ;
36+ }
37+ return fallbackMessage ;
38+ }
39+
3240export function RegisterForm ( ) {
3341 const router = useRouter ( ) ;
3442 const [ isLoading , setIsLoading ] = useState ( false ) ;
@@ -41,6 +49,7 @@ export function RegisterForm() {
4149 confirmPassword : "" ,
4250 } ) ;
4351 const t = useTranslations ( "auth.register" ) ;
52+ const tSocial = useTranslations ( "auth.social" ) ;
4453 const tValidation = useTranslations ( "auth.validation" ) ;
4554
4655 const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
@@ -130,6 +139,30 @@ export function RegisterForm() {
130139 }
131140 } ;
132141
142+ const handleSocialSignIn = async ( provider : "google" | "github" ) => {
143+ setFormError ( null ) ;
144+ setIsLoading ( true ) ;
145+
146+ try {
147+ const response = await authClient . signIn . social ( {
148+ provider,
149+ callbackURL : "/dashboard" ,
150+ } ) ;
151+ const socialError =
152+ response && typeof response === "object" && "error" in response
153+ ? response . error
154+ : null ;
155+
156+ if ( socialError ) {
157+ throw socialError ;
158+ }
159+ } catch ( error ) {
160+ setFormError ( getSocialAuthErrorMessage ( error , tSocial ( "error" ) ) ) ;
161+ } finally {
162+ setIsLoading ( false ) ;
163+ }
164+ } ;
165+
133166 return (
134167 < Card >
135168 < CardHeader >
@@ -217,6 +250,38 @@ export function RegisterForm() {
217250 { isLoading ? t ( "submitting" ) : t ( "submitButton" ) }
218251 </ Button >
219252
253+ < div className = "relative" >
254+ < div className = "absolute inset-0 flex items-center" >
255+ < span className = "w-full border-t" />
256+ </ div >
257+ < div className = "relative flex justify-center text-xs uppercase" >
258+ < span className = "bg-card px-2 text-muted-foreground" > { tSocial ( "or" ) } </ span >
259+ </ div >
260+ </ div >
261+
262+ < div className = "grid gap-2 sm:grid-cols-2" >
263+ < Button
264+ type = "button"
265+ variant = "outline"
266+ disabled = { isLoading }
267+ onClick = { ( ) => {
268+ void handleSocialSignIn ( "google" ) ;
269+ } }
270+ >
271+ { tSocial ( "google" ) }
272+ </ Button >
273+ < Button
274+ type = "button"
275+ variant = "outline"
276+ disabled = { isLoading }
277+ onClick = { ( ) => {
278+ void handleSocialSignIn ( "github" ) ;
279+ } }
280+ >
281+ { tSocial ( "github" ) }
282+ </ Button >
283+ </ div >
284+
220285 < p className = "text-center text-sm text-muted-foreground" >
221286 { t ( "hasAccount" ) }
222287 < Link className = "ml-1 text-primary hover:underline" href = "/login" >
0 commit comments