1- import { useState } from 'react' ;
1+ import { useState , useEffect , useRef } from 'react' ;
22import { motion , AnimatePresence } from 'motion/react' ;
3- import { Github , X , User } from 'lucide-react' ;
3+ import { Github , X } from 'lucide-react' ;
44
55interface GitHubAuthModalProps {
66 isOpen : boolean ;
@@ -9,22 +9,51 @@ interface GitHubAuthModalProps {
99}
1010
1111export function GitHubAuthModal ( { isOpen, onClose, onAuth } : GitHubAuthModalProps ) {
12- const [ username , setUsername ] = useState ( '' ) ;
1312 const [ isLoading , setIsLoading ] = useState ( false ) ;
13+ const hasFetched = useRef ( false ) ; // Prevents duplicate API calls with the same code
1414
15- const handleSubmit = ( e : React . FormEvent ) => {
16- e . preventDefault ( ) ;
17- if ( ! username . trim ( ) ) return ;
18-
15+ // Function to initiate the GitHub OAuth flow
16+ const handleGitHubLogin = ( ) => {
1917 setIsLoading ( true ) ;
20- // Simulate authentication delay
21- setTimeout ( ( ) => {
22- onAuth ( username . trim ( ) ) ;
23- setIsLoading ( false ) ;
24- setUsername ( '' ) ;
25- } , 1500 ) ;
18+ const clientId = 'CLIENT_ID_HERE' ; // Replace with your GitHub OAuth App Client ID
19+ const redirectUri = 'http://localhost:3000/github/callback' ;
20+ const githubAuthUrl = `https://github.com/login/oauth/authorize?client_id=${ clientId } &redirect_uri=${ redirectUri } &scope=read:user` ;
21+
22+ window . location . href = githubAuthUrl ;
2623 } ;
2724
25+ useEffect ( ( ) => {
26+ const urlParams = new URLSearchParams ( window . location . search ) ;
27+ const code = urlParams . get ( 'code' ) ;
28+
29+ if ( code && ! hasFetched . current ) {
30+ hasFetched . current = true ; // Mark as fetched immediately
31+ setIsLoading ( true ) ;
32+
33+ fetch ( 'http://localhost:5000/github/callback' , {
34+ method : 'POST' ,
35+ headers : { 'Content-Type' : 'application/json' } ,
36+ body : JSON . stringify ( { code } ) ,
37+ } )
38+ . then ( ( res ) => res . json ( ) )
39+ . then ( ( data ) => {
40+ if ( data . user ) {
41+ console . log ( 'GitHub Login Success:' , data ) ;
42+ // This triggers the handleAuth logic in your App.tsx
43+ onAuth ( data . user . login ) ;
44+
45+ // Clean the URL so the code doesn't stay in the address bar
46+ window . history . replaceState ( { } , document . title , "/" ) ;
47+ }
48+ } )
49+ . catch ( ( err ) => {
50+ console . error ( 'GitHub Login Error:' , err ) ;
51+ hasFetched . current = false ; // Allow retry on error
52+ } )
53+ . finally ( ( ) => setIsLoading ( false ) ) ;
54+ }
55+ } , [ onAuth ] ) ;
56+
2857 return (
2958 < AnimatePresence >
3059 { isOpen && (
@@ -64,65 +93,43 @@ export function GitHubAuthModal({ isOpen, onClose, onAuth }: GitHubAuthModalProp
6493 Sign in with GitHub
6594 </ h2 >
6695 < p className = "text-gray-400" >
67- Enter your GitHub username to start your career
96+ Authenticate to start your career and save your progress.
6897 </ p >
6998 </ div >
7099
71- { /* Form */ }
72- < form onSubmit = { handleSubmit } className = "space-y-6" >
73- < div >
74- < label htmlFor = "username" className = "block text-sm text-gray-300 mb-2" >
75- GitHub Username
76- </ label >
77- < div className = "relative" >
78- < User className = "absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
79- < input
80- id = "username"
81- type = "text"
82- value = { username }
83- onChange = { ( e ) => setUsername ( e . target . value ) }
84- placeholder = "your-username"
85- className = "w-full pl-12 pr-4 py-3 bg-black/50 border border-gray-700 rounded-lg focus:outline-none focus:border-blue-500 text-white placeholder-gray-500 transition-colors"
86- required
87- autoFocus
88- disabled = { isLoading }
100+ { /* GitHub Login Button */ }
101+ < motion . button
102+ onClick = { handleGitHubLogin }
103+ disabled = { isLoading }
104+ whileHover = { { scale : 1.02 } }
105+ whileTap = { { scale : 0.98 } }
106+ className = "w-full py-3 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg hover:from-blue-500 hover:to-purple-500 transition-all duration-300 shadow-[0_0_20px_rgba(59,130,246,0.5)] disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 text-white font-medium"
107+ >
108+ { isLoading ? (
109+ < >
110+ < motion . div
111+ animate = { { rotate : 360 } }
112+ transition = { { duration : 1 , repeat : Infinity , ease : 'linear' } }
113+ className = "w-5 h-5 border-2 border-white/30 border-t-white rounded-full"
89114 />
90- </ div >
91- </ div >
92-
93- < motion . button
94- type = "submit"
95- disabled = { isLoading || ! username . trim ( ) }
96- whileHover = { { scale : 1.02 } }
97- whileTap = { { scale : 0.98 } }
98- className = "w-full py-3 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg hover:from-blue-500 hover:to-purple-500 transition-all duration-300 shadow-[0_0_20px_rgba(59,130,246,0.5)] disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
99- >
100- { isLoading ? (
101- < >
102- < motion . div
103- animate = { { rotate : 360 } }
104- transition = { { duration : 1 , repeat : Infinity , ease : 'linear' } }
105- className = "w-5 h-5 border-2 border-white/30 border-t-white rounded-full"
106- />
107- Authenticating...
108- </ >
109- ) : (
110- < >
111- < Github className = "w-5 h-5" />
112- Continue with GitHub
113- </ >
114- ) }
115- </ motion . button >
116- </ form >
115+ Authenticating...
116+ </ >
117+ ) : (
118+ < >
119+ < Github className = "w-5 h-5" />
120+ Continue with GitHub
121+ </ >
122+ ) }
123+ </ motion . button >
117124
118125 { /* Note */ }
119126 < p className = "text-xs text-gray-500 text-center mt-6" >
120- This is a demo authentication. In production, this would use real GitHub OAuth .
127+ This will redirect you to GitHub for authentication .
121128 </ p >
122129 </ div >
123130 </ motion . div >
124131 </ >
125132 ) }
126133 </ AnimatePresence >
127134 ) ;
128- }
135+ }
0 commit comments