@@ -28,28 +28,78 @@ export class LearnersService {
2828 return this . mapToDto ( data ) ;
2929 }
3030
31+ async getCompletionStatus ( wallet : string ) : Promise < { complete : boolean ; missingFields : string [ ] } > {
32+ let profile ;
33+ try {
34+ profile = await this . getProfile ( wallet ) ;
35+ } catch ( err ) {
36+ return { complete : false , missingFields : [ 'fullName' , 'country' , 'financeGoals' ] } ;
37+ }
38+
39+ const requiredFields = [ 'fullName' , 'country' , 'financeGoals' ] ;
40+ const missingFields = requiredFields . filter ( field => {
41+ const val = profile [ field as keyof LearnerResponseDto ] ;
42+ if ( Array . isArray ( val ) ) return val . length === 0 ;
43+ return ! val ;
44+ } ) ;
45+
46+ return {
47+ complete : missingFields . length === 0 ,
48+ missingFields,
49+ } ;
50+ }
51+
3152 async upsertProfile (
3253 wallet : string ,
3354 dto : UpdateLearnerProfileDto ,
3455 ) : Promise < LearnerResponseDto > {
3556 const client = this . supabaseService . getServiceRoleClient ( ) ;
3657
58+ const { data : existing } = await client
59+ . from ( 'learner_profiles' )
60+ . select ( '*' )
61+ . eq ( 'wallet_address' , wallet )
62+ . single ( ) ;
63+
64+ const fullName = dto . full_name !== undefined ? dto . full_name : existing ?. full_name ;
65+ const country = dto . country !== undefined ? dto . country : existing ?. country ;
66+ const financeGoals = dto . finance_goals !== undefined ? dto . finance_goals : existing ?. finance_goals ;
67+
68+ const isComplete = ! ! (
69+ fullName &&
70+ country &&
71+ Array . isArray ( financeGoals ) && financeGoals . length > 0
72+ ) ;
73+
74+ const wasComplete = existing ?. profile_complete === true ;
75+ const isNewlyComplete = isComplete && ! wasComplete ;
76+
77+ const onboardingCompletedAt = isNewlyComplete ? new Date ( ) . toISOString ( ) : existing ?. onboarding_completed_at ;
78+
79+ const updatePayload : any = {
80+ wallet_address : wallet ,
81+ profile_complete : isComplete ,
82+ onboarding_completed_at : onboardingCompletedAt ,
83+ updated_at : new Date ( ) . toISOString ( ) ,
84+ } ;
85+
86+ if ( dto . full_name !== undefined ) updatePayload . full_name = dto . full_name ;
87+ if ( dto . bio !== undefined ) updatePayload . bio = dto . bio ;
88+ if ( dto . country !== undefined ) updatePayload . country = dto . country ;
89+ if ( dto . city !== undefined ) updatePayload . city = dto . city ;
90+ if ( dto . current_role !== undefined ) updatePayload . current_role = dto . current_role ;
91+ if ( dto . institution !== undefined ) updatePayload . institution = dto . institution ;
92+ if ( dto . program !== undefined ) updatePayload . program = dto . program ;
93+ if ( dto . graduation_year !== undefined ) updatePayload . graduation_year = dto . graduation_year ;
94+ if ( dto . skills !== undefined ) updatePayload . skills = dto . skills ;
95+ if ( dto . finance_goals !== undefined ) updatePayload . finance_goals = dto . finance_goals ;
96+ if ( dto . monthly_income_range !== undefined ) updatePayload . monthly_income_range = dto . monthly_income_range ;
97+ if ( dto . github_url !== undefined ) updatePayload . github_url = dto . github_url ;
98+ if ( dto . linkedin_url !== undefined ) updatePayload . linkedin_url = dto . linkedin_url ;
99+
37100 const { data, error } = await client
38101 . from ( 'learner_profiles' )
39- . upsert (
40- {
41- wallet_address : wallet ,
42- school : dto . school ,
43- program : dto . program ,
44- program_type : dto . programType ,
45- income_type : dto . incomeType ,
46- monthly_income : dto . monthlyIncome ,
47- country : dto . country ,
48- city : dto . city ,
49- updated_at : new Date ( ) . toISOString ( ) ,
50- } ,
51- { onConflict : 'wallet_address' } ,
52- )
102+ . upsert ( updatePayload , { onConflict : 'wallet_address' } )
53103 . select ( )
54104 . single ( ) ;
55105
@@ -66,14 +116,21 @@ export class LearnersService {
66116 return {
67117 id : data . id ,
68118 walletAddress : data . wallet_address ,
69- school : data . school ,
70- program : data . program ,
71- programType : data . program_type ,
72- incomeType : data . income_type ,
73- monthlyIncome : data . monthly_income ,
119+ fullName : data . full_name ,
120+ bio : data . bio ,
74121 country : data . country ,
75122 city : data . city ,
76- deviceOwned : data . device_owned ,
123+ currentRole : data . current_role ,
124+ institution : data . institution ,
125+ program : data . program ,
126+ graduationYear : data . graduation_year ,
127+ skills : data . skills ,
128+ financeGoals : data . finance_goals ,
129+ monthlyIncomeRange : data . monthly_income_range ,
130+ githubUrl : data . github_url ,
131+ linkedinUrl : data . linkedin_url ,
132+ profileComplete : data . profile_complete ,
133+ onboardingCompletedAt : data . onboarding_completed_at ,
77134 createdAt : data . created_at ,
78135 updatedAt : data . updated_at ,
79136 } ;
0 commit comments