Skip to content

Commit 60091f1

Browse files
authored
Merge pull request #248 from codeunia-dev/feature/oauth-profile-completion
Feature/oauth profile completion
2 parents 89457e2 + fa8abb7 commit 60091f1

2 files changed

Lines changed: 77 additions & 12 deletions

File tree

app/complete-profile/page.tsx

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { useState, useEffect, useCallback, useRef } from 'react';
3+
import { useState, useEffect, useCallback, useRef, Suspense } from 'react';
44
import { useRouter, useSearchParams } from 'next/navigation';
55
import Link from 'next/link';
66
import { createClient } from '@/lib/supabase/client';
@@ -22,7 +22,7 @@ interface User {
2222
};
2323
}
2424

25-
export default function CompleteProfile() {
25+
function CompleteProfileContent() {
2626
const router = useRouter();
2727
const searchParams = useSearchParams();
2828
const returnUrl = searchParams.get('returnUrl') || '/protected/dashboard';
@@ -36,6 +36,7 @@ export default function CompleteProfile() {
3636
const [usernameError, setUsernameError] = useState<string>('');
3737
const [user, setUser] = useState<User | null>(null);
3838
const [isValidating, setIsValidating] = useState(true);
39+
const [oauthProvider, setOauthProvider] = useState<string>('');
3940
const usernameCheckTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
4041

4142
const getSupabaseClient = () => {
@@ -82,15 +83,40 @@ export default function CompleteProfile() {
8283
// Continue with the form - profileService will handle creation if needed
8384
}
8485

85-
// Pre-fill from OAuth provider data if available
86+
// Pre-fill from OAuth provider data if available (prioritize OAuth data over existing profile data)
8687
if (user.user_metadata) {
8788
const metadata = user.user_metadata;
88-
if (!firstName && (metadata.first_name || metadata.given_name)) {
89-
setFirstName(metadata.first_name || metadata.given_name || '');
89+
90+
// Extract first name from various OAuth provider formats
91+
const oauthFirstName = metadata.first_name ||
92+
metadata.given_name ||
93+
metadata.name?.split(' ')[0] ||
94+
'';
95+
96+
// Extract last name from various OAuth provider formats
97+
const oauthLastName = metadata.last_name ||
98+
metadata.family_name ||
99+
metadata.name?.split(' ').slice(1).join(' ') ||
100+
'';
101+
102+
// Use OAuth data if available, otherwise keep existing profile data
103+
if (oauthFirstName) {
104+
setFirstName(oauthFirstName);
90105
}
91-
if (!lastName && (metadata.last_name || metadata.family_name)) {
92-
setLastName(metadata.last_name || metadata.family_name || '');
106+
if (oauthLastName) {
107+
setLastName(oauthLastName);
93108
}
109+
110+
// Set OAuth provider for UI display
111+
setOauthProvider(metadata.provider || 'unknown');
112+
113+
console.log('OAuth provider data:', {
114+
provider: metadata.provider || 'unknown',
115+
firstName: oauthFirstName,
116+
lastName: oauthLastName,
117+
fullName: metadata.name,
118+
metadata: metadata
119+
});
94120
}
95121

96122
} catch (error) {
@@ -99,7 +125,7 @@ export default function CompleteProfile() {
99125
} finally {
100126
setIsValidating(false);
101127
}
102-
}, [router, firstName, lastName]);
128+
}, [router, returnUrl]);
103129

104130
useEffect(() => {
105131
checkUser();
@@ -287,7 +313,11 @@ export default function CompleteProfile() {
287313
{/* First Name */}
288314
<div className="space-y-2">
289315
<label className="block text-sm font-semibold text-gray-700">
290-
First Name *
316+
First Name * {oauthProvider && firstName && (
317+
<span className="text-xs text-green-600 font-normal">
318+
(pre-filled from {oauthProvider})
319+
</span>
320+
)}
291321
</label>
292322
<input
293323
type="text"
@@ -302,7 +332,11 @@ export default function CompleteProfile() {
302332
{/* Last Name */}
303333
<div className="space-y-2">
304334
<label className="block text-sm font-semibold text-gray-700">
305-
Last Name *
335+
Last Name * {oauthProvider && lastName && (
336+
<span className="text-xs text-green-600 font-normal">
337+
(pre-filled from {oauthProvider})
338+
</span>
339+
)}
306340
</label>
307341
<input
308342
type="text"
@@ -456,3 +490,19 @@ export default function CompleteProfile() {
456490
</div>
457491
);
458492
}
493+
494+
export default function CompleteProfile() {
495+
return (
496+
<Suspense fallback={
497+
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-muted/30 to-muted/50">
498+
<div className="relative">
499+
<div className="animate-spin rounded-full h-12 w-12 border-4 border-primary border-t-transparent"></div>
500+
<div className="absolute inset-0 rounded-full border-4 border-primary/20 animate-ping"></div>
501+
</div>
502+
<span className="ml-4 text-lg text-muted-foreground">Loading...</span>
503+
</div>
504+
}>
505+
<CompleteProfileContent />
506+
</Suspense>
507+
);
508+
}

lib/services/profile.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,25 @@ export class ProfileService {
4141
// Generate a simple codeunia_id if needed
4242
const codeuniaId = `CU-${userId.slice(-8).toUpperCase()}-${Date.now().toString(36).toUpperCase()}`
4343

44+
// Extract name data from OAuth provider metadata
45+
const metadata = user.user?.user_metadata || {};
46+
47+
// Extract first name from various OAuth provider formats
48+
const firstName = metadata.first_name ||
49+
metadata.given_name ||
50+
metadata.name?.split(' ')[0] ||
51+
'';
52+
53+
// Extract last name from various OAuth provider formats
54+
const lastName = metadata.last_name ||
55+
metadata.family_name ||
56+
metadata.name?.split(' ').slice(1).join(' ') ||
57+
'';
58+
4459
const profileData = {
4560
id: userId,
46-
first_name: user.user?.user_metadata?.first_name || '',
47-
last_name: user.user?.user_metadata?.last_name || '',
61+
first_name: firstName,
62+
last_name: lastName,
4863
is_public: true,
4964
email_notifications: true,
5065
profile_completion_percentage: 0,

0 commit comments

Comments
 (0)