@@ -246,9 +246,29 @@ export const AccountSettings = () => {
246246 const [ storageUsed , setStorageUsed ] = useState < number > ( 0 ) ;
247247 const STORAGE_QUOTA = 5 * 1024 * 1024 * 1024 ; // 5 GB default quota
248248
249- // UI Toggles
250- const [ emailNotifs , setEmailNotifs ] = useState ( true ) ;
251- const [ publicProfile , setPublicProfile ] = useState ( false ) ;
249+ // UI Toggles & Prefs
250+ const [ language , setLanguage ] = useState ( user ?. user_metadata ?. language || 'English (US)' ) ;
251+ const [ timezone , setTimezone ] = useState ( user ?. user_metadata ?. timezone || 'Coordinated Universal Time (UTC)' ) ;
252+ const [ emailNotifs , setEmailNotifs ] = useState ( user ?. user_metadata ?. email_notifications ?? true ) ;
253+ const [ publicProfile , setPublicProfile ] = useState ( user ?. user_metadata ?. public_profile ?? false ) ;
254+
255+ // Connections
256+ const [ ghConnected , setGhConnected ] = useState ( user ?. user_metadata ?. github_connected || false ) ;
257+ const [ orcidConnected , setOrcidConnected ] = useState ( user ?. user_metadata ?. orcid_connected || false ) ;
258+ const [ connectingTo , setConnectingTo ] = useState < string | null > ( null ) ;
259+
260+ const updatePreference = async ( key : string , value : any ) => {
261+ await supabase . auth . updateUser ( { data : { [ key ] : value } } ) ;
262+ } ;
263+
264+ const handleConnect = async ( provider : string ) => {
265+ setConnectingTo ( provider ) ;
266+ await new Promise ( r => setTimeout ( r , 800 ) ) ; // Simulate OAuth handoff
267+ await updatePreference ( `${ provider } _connected` , true ) ;
268+ if ( provider === 'github' ) setGhConnected ( true ) ;
269+ if ( provider === 'orcid' ) setOrcidConnected ( true ) ;
270+ setConnectingTo ( null ) ;
271+ } ;
252272
253273 // Fetch storage
254274 useEffect ( ( ) => {
@@ -424,7 +444,10 @@ export const AccountSettings = () => {
424444 { /* Language */ }
425445 < div >
426446 < label className = "block text-sm font-medium text-[var(--text-secondary)] mb-1.5" > Language</ label >
427- < select className = "w-full px-3 py-2 bg-[var(--bg-header)] border border-[var(--border-main)] rounded-lg text-sm text-[var(--text-primary)] outline-none focus:border-blue-500" >
447+ < select
448+ value = { language }
449+ onChange = { e => { setLanguage ( e . target . value ) ; updatePreference ( 'language' , e . target . value ) ; } }
450+ className = "w-full px-3 py-2 bg-[var(--bg-header)] border border-[var(--border-main)] rounded-lg text-sm text-[var(--text-primary)] outline-none focus:border-blue-500" >
428451 < option > English (US)</ option >
429452 < option > Spanish (ES)</ option >
430453 < option > French (FR)</ option >
@@ -434,7 +457,10 @@ export const AccountSettings = () => {
434457 { /* Timezone */ }
435458 < div >
436459 < label className = "block text-sm font-medium text-[var(--text-secondary)] mb-1.5" > Timezone</ label >
437- < select className = "w-full px-3 py-2 bg-[var(--bg-header)] border border-[var(--border-main)] rounded-lg text-sm text-[var(--text-primary)] outline-none focus:border-blue-500" >
460+ < select
461+ value = { timezone }
462+ onChange = { e => { setTimezone ( e . target . value ) ; updatePreference ( 'timezone' , e . target . value ) ; } }
463+ className = "w-full px-3 py-2 bg-[var(--bg-header)] border border-[var(--border-main)] rounded-lg text-sm text-[var(--text-primary)] outline-none focus:border-blue-500" >
438464 < option > Pacific Time (PT)</ option >
439465 < option > Eastern Time (ET)</ option >
440466 < option > Central European Time (CET)</ option >
@@ -451,7 +477,7 @@ export const AccountSettings = () => {
451477 < p className = "text-xs text-[var(--text-muted)] mt-0.5" > Receive product updates and weekly digests.</ p >
452478 </ div >
453479 < div className = { `relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors ${ emailNotifs ? 'bg-blue-600' : 'bg-neutral-600' } ` }
454- onClick = { ( ) => setEmailNotifs ( ! emailNotifs ) } >
480+ onClick = { ( ) => { const v = ! emailNotifs ; setEmailNotifs ( v ) ; updatePreference ( 'email_notifications' , v ) ; } } >
455481 < span className = { `pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out ${ emailNotifs ? 'translate-x-2' : '-translate-x-2' } ` } />
456482 </ div >
457483 </ label >
@@ -461,7 +487,7 @@ export const AccountSettings = () => {
461487 < p className = "text-xs text-[var(--text-muted)] mt-0.5" > Allow other platform users to find your public collections via your username.</ p >
462488 </ div >
463489 < div className = { `relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors ${ publicProfile ? 'bg-blue-600' : 'bg-neutral-600' } ` }
464- onClick = { ( ) => setPublicProfile ( ! publicProfile ) } >
490+ onClick = { ( ) => { const v = ! publicProfile ; setPublicProfile ( v ) ; updatePreference ( 'public_profile' , v ) ; } } >
465491 < span className = { `pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out ${ publicProfile ? 'translate-x-2' : '-translate-x-2' } ` } />
466492 </ div >
467493 </ label >
@@ -500,7 +526,14 @@ export const AccountSettings = () => {
500526 < p className = "text-xs text-[var(--text-muted)]" > Import repositories and scripts</ p >
501527 </ div >
502528 </ div >
503- < button className = "text-xs font-medium px-4 py-1.5 bg-[var(--input-bg)] text-[var(--text-primary)] border border-[var(--border-main)] hover:bg-[var(--border-main)] rounded-md transition-colors" > Connect</ button >
529+ { ghConnected ? (
530+ < span className = "text-xs font-medium px-2.5 py-1 bg-green-500/10 text-green-400 border border-green-500/20 rounded-md" > Connected</ span >
531+ ) : (
532+ < button onClick = { ( ) => handleConnect ( 'github' ) } disabled = { connectingTo === 'github' }
533+ className = "text-xs font-medium px-4 py-1.5 bg-[var(--input-bg)] text-[var(--text-primary)] border border-[var(--border-main)] hover:bg-[var(--border-main)] rounded-md transition-colors disabled:opacity-50 flex items-center gap-1.5" >
534+ { connectingTo === 'github' && < Loader2 className = "w-3.5 h-3.5 animate-spin" /> } Connect
535+ </ button >
536+ ) }
504537 </ div >
505538 { /* ORCID */ }
506539 < div className = "flex items-center justify-between p-5 hover:bg-[var(--input-bg)]/50 transition-colors" >
@@ -513,7 +546,14 @@ export const AccountSettings = () => {
513546 < p className = "text-xs text-[var(--text-muted)]" > Link researcher identity</ p >
514547 </ div >
515548 </ div >
516- < button className = "text-xs font-medium px-4 py-1.5 bg-[var(--input-bg)] text-[var(--text-primary)] border border-[var(--border-main)] hover:bg-[var(--border-main)] rounded-md transition-colors" > Connect</ button >
549+ { orcidConnected ? (
550+ < span className = "text-xs font-medium px-2.5 py-1 bg-green-500/10 text-green-400 border border-green-500/20 rounded-md" > Connected</ span >
551+ ) : (
552+ < button onClick = { ( ) => handleConnect ( 'orcid' ) } disabled = { connectingTo === 'orcid' }
553+ className = "text-xs font-medium px-4 py-1.5 bg-[var(--input-bg)] text-[var(--text-primary)] border border-[var(--border-main)] hover:bg-[var(--border-main)] rounded-md transition-colors disabled:opacity-50 flex items-center gap-1.5" >
554+ { connectingTo === 'orcid' && < Loader2 className = "w-3.5 h-3.5 animate-spin" /> } Connect
555+ </ button >
556+ ) }
517557 </ div >
518558 </ div >
519559 </ div >
0 commit comments