@@ -12,15 +12,44 @@ export default function SettingsPage() {
1212 const [ cleared , setCleared ] = useState ( false )
1313 const [ isRefreshing , setIsRefreshing ] = useState ( false )
1414 const [ refreshError , setRefreshError ] = useState ( false )
15- const handleSave = ( ) => {
16- savePat ( draft . trim ( ) )
17- setSaved ( true )
18- setTimeout ( ( ) => setSaved ( false ) , 2000 )
15+ const [ isValidating , setIsValidating ] = useState ( false )
16+ const [ tokenError , setTokenError ] = useState ( '' )
17+
18+ const handleSave = async ( ) => {
19+ const token = draft . trim ( ) ;
20+ if ( ! token ) return ;
21+
22+ setIsValidating ( true ) ;
23+ setTokenError ( '' ) ;
24+
25+ try {
26+ const response = await fetch ( 'https://api.github.com/rate_limit' , {
27+ headers : {
28+ Accept : 'application/vnd.github.v3+json' ,
29+ Authorization : `token ${ token } `
30+ }
31+ } ) ;
32+
33+ if ( ! response . ok ) {
34+ setTokenError ( 'Invalid Personal Access Token' ) ;
35+ setIsValidating ( false ) ;
36+ return ;
37+ }
38+
39+ savePat ( token ) ;
40+ setSaved ( true ) ;
41+ setTimeout ( ( ) => setSaved ( false ) , 2000 ) ;
42+ } catch ( err ) {
43+ setTokenError ( 'Network error verifying token' ) ;
44+ } finally {
45+ setIsValidating ( false ) ;
46+ }
1947 }
2048
2149 const handleDelete = ( ) => {
2250 savePat ( '' )
2351 setDraft ( '' )
52+ setTokenError ( '' )
2453 }
2554
2655 const handleClear = async ( ) => {
@@ -131,7 +160,10 @@ export default function SettingsPage() {
131160 < input
132161 type = { show ? 'text' : 'password' }
133162 value = { draft }
134- onChange = { e => setDraft ( e . target . value ) }
163+ onChange = { e => {
164+ setDraft ( e . target . value )
165+ setTokenError ( '' )
166+ } }
135167 placeholder = "ghp_xxxxxxxxxxxxxxxxxxxx"
136168 style = { { ...C . input , flex : 1 } }
137169 onKeyDown = { e => e . key === 'Enter' && handleSave ( ) }
@@ -143,17 +175,22 @@ export default function SettingsPage() {
143175 { show ? < FiEyeOff size = { 14 } /> : < FiEye size = { 14 } /> }
144176 </ button >
145177 </ div >
178+ { tokenError && (
179+ < div style = { { color : 'var(--red)' , fontSize : 13 , marginBottom : 10 , marginTop : - 2 } } >
180+ { tokenError }
181+ </ div >
182+ ) }
146183 < div style = { { display : 'flex' , gap : 8 } } >
147184 < button
148185 onClick = { handleSave }
149- disabled = { ! draft . trim ( ) }
186+ disabled = { ! draft . trim ( ) || isValidating }
150187 style = { { ...C . btn ( 'primary' ) , display : 'flex' , alignItems : 'center' , gap : 5 , fontSize : 13 } }
151188 >
152- < FiSave size = { 13 } /> { saved ? 'Saved' : 'Save' }
189+ < FiSave size = { 13 } /> { isValidating ? 'Validating...' : saved ? 'Saved' : 'Save' }
153190 </ button >
154191 < button
155192 onClick = { handleDelete }
156- disabled = { ! draft . trim ( ) }
193+ disabled = { ! draft . trim ( ) || isValidating }
157194 style = { { ...C . btn ( 'danger' ) , display : 'flex' , alignItems : 'center' , gap : 5 , fontSize : 13 } }
158195 >
159196 < FiTrash2 size = { 13 } /> Delete
0 commit comments