Skip to content

Commit 4efdd48

Browse files
committed
fix(account): ensure account creation matches Firebase structure exactly
- Add profile and stats fields to Account interface - Update firebase-service.ts createAccount to include profile and stats - Update account-service.ts to create simple structure (no demos/badges/rewards objects) - Network field now uppercase (TESTNET) to match Firebase example - addExperienceAndPoints now updates both root and nested fields: - Root: level, experience, totalPoints - Nested: profile.level, stats.totalPoints, stats.lastActiveDate - createOrUpdateAccount initializes profile and stats if missing - Remove complex UserAccount structure from new accounts - All accounts now follow consistent Firebase structure - Maintains backward compatibility with existing accounts
1 parent 42a3fcf commit 4efdd48

File tree

3 files changed

+60
-102
lines changed

3 files changed

+60
-102
lines changed

lib/firebase/firebase-service.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,23 @@ export const accountService = {
3737
// Create or update account
3838
async createOrUpdateAccount(accountData: Partial<Account>): Promise<void> {
3939
const accountRef = doc(db, COLLECTIONS.ACCOUNTS, accountData.id!);
40+
41+
// Get existing account to preserve fields
42+
const existingDoc = await getDoc(accountRef);
43+
const existingData = existingDoc.exists() ? existingDoc.data() : {};
44+
4045
const accountDoc = {
4146
...accountData,
42-
// Initialize new fields if they don't exist
43-
completedQuests: accountData.completedQuests || [],
44-
questProgress: accountData.questProgress || {},
47+
// Initialize new fields if they don't exist (match Firebase example structure)
48+
completedQuests: accountData.completedQuests || existingData.completedQuests || [],
49+
questProgress: accountData.questProgress || existingData.questProgress || {},
50+
profile: accountData.profile || existingData.profile || {
51+
level: accountData.level || 1,
52+
},
53+
stats: accountData.stats || existingData.stats || {
54+
totalPoints: accountData.totalPoints || 0,
55+
lastActiveDate: new Date().toISOString().split('T')[0],
56+
},
4557
updatedAt: serverTimestamp(),
4658
lastLoginAt: serverTimestamp(),
4759
};
@@ -143,10 +155,16 @@ export const accountService = {
143155
const newTotalPoints = account.totalPoints + points;
144156
const newLevel = Math.floor(newExperience / 1000) + 1;
145157

146-
await this.updateAccountProgress(walletAddress, {
158+
// Update both root-level and nested fields (match Firebase structure)
159+
const accountRef = doc(db, COLLECTIONS.ACCOUNTS, walletAddress);
160+
await updateDoc(accountRef, {
147161
experience: newExperience,
148162
totalPoints: newTotalPoints,
149163
level: newLevel,
164+
'profile.level': newLevel, // Update nested profile.level
165+
'stats.totalPoints': newTotalPoints, // Update nested stats.totalPoints
166+
'stats.lastActiveDate': new Date().toISOString().split('T')[0], // Update last active date
167+
updatedAt: serverTimestamp(),
150168
});
151169
}
152170
},
@@ -660,7 +678,7 @@ export const firebaseUtils = {
660678
return Math.floor(experience / 1000) + 1;
661679
},
662680

663-
// Create account
681+
// Create account - matches exact Firebase structure from example
664682
async createAccount(
665683
walletAddress: string,
666684
displayName: string,
@@ -670,13 +688,15 @@ export const firebaseUtils = {
670688
id: walletAddress,
671689
displayName,
672690
walletAddress,
673-
network,
691+
network: network.toUpperCase(), // Match "TESTNET" format
674692
level: 1,
675693
experience: 0,
676694
totalPoints: 0,
677695
demosCompleted: [],
678696
badgesEarned: [],
679697
clappedDemos: [],
698+
completedQuests: [],
699+
questProgress: {},
680700
createdAt: new Date(),
681701
updatedAt: new Date(),
682702
lastLoginAt: new Date(),

lib/firebase/firebase-types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ export interface Account {
4848
completedQuests: string[]; // Array of quest IDs completed
4949
questProgress: Record<string, number>; // Progress tracking for multi-step quests
5050

51+
// Profile (nested object for additional user data)
52+
profile?: {
53+
level?: number;
54+
totalPoints?: number;
55+
experience?: number;
56+
displayName?: string;
57+
username?: string;
58+
};
59+
60+
// Stats (nested object for tracking statistics)
61+
stats?: {
62+
totalPoints?: number;
63+
lastActiveDate?: string; // Format: "YYYY-MM-DD"
64+
totalDemosCompleted?: number;
65+
totalPointsEarned?: number;
66+
totalTimeSpent?: number;
67+
streakDays?: number;
68+
};
5169

5270
// Transaction history - now stored in separate collection
5371
}

lib/services/account-service.ts

Lines changed: 16 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -31,121 +31,41 @@ export class AccountService {
3131
return AccountService.instance;
3232
}
3333

34-
// Create new account
34+
// Create new account - matches the structure used in firebase-service.ts
3535
async createAccount(
3636
walletAddress: string,
3737
publicKey: string,
3838
network: string
39-
): Promise<UserAccount> {
40-
// Use wallet address as account ID (not auto-generated UUID)
39+
): Promise<any> {
40+
// Use wallet address as account ID (matches Firebase example structure)
4141
const accountId = walletAddress;
4242

4343
const now = Timestamp.now();
4444

45-
const newAccount: UserAccount = {
45+
// Match the exact structure from firebase-service.ts and Firebase example
46+
const newAccount = {
4647
id: accountId,
48+
displayName: publicKey.slice(0, 6) + '...' + publicKey.slice(-4), // Default display name
4749
walletAddress,
48-
publicKey,
49-
network,
50+
network: network.toUpperCase(), // Match "TESTNET" format from example
51+
level: 1,
52+
experience: 0,
53+
totalPoints: 0,
54+
demosCompleted: [],
55+
badgesEarned: [],
56+
clappedDemos: [],
57+
completedQuests: [],
58+
questProgress: {},
5059
createdAt: now,
5160
updatedAt: now,
5261
lastLoginAt: now,
53-
level: 1, // Root level for backward compatibility
54-
experience: 150, // Experience points
55-
totalPoints: 150, // Account creation bonus (100) + Welcome Explorer (10) + margin
56-
5762
profile: {
5863
level: 1,
59-
totalPoints: 150, // Account creation bonus (100) + Trust Guardian (50)
60-
experience: 150, // Experience points (same as points for now)
61-
},
62-
63-
demos: {
64-
demo1: {
65-
demoId: 'demo1',
66-
demoName: 'Baby Steps to Riches',
67-
status: 'locked',
68-
attempts: 0,
69-
pointsEarned: 0,
70-
},
71-
'hello-milestone': {
72-
demoId: 'hello-milestone',
73-
demoName: 'Baby Steps to Riches',
74-
status: 'available',
75-
attempts: 0,
76-
pointsEarned: 0,
77-
},
78-
demo2: {
79-
demoId: 'demo2',
80-
demoName: 'Milestone Voting',
81-
status: 'locked',
82-
attempts: 0,
83-
pointsEarned: 0,
84-
},
85-
'milestone-voting': {
86-
demoId: 'milestone-voting',
87-
demoName: 'Democracy in Action',
88-
status: 'locked',
89-
attempts: 0,
90-
pointsEarned: 0,
91-
},
92-
demo3: {
93-
demoId: 'demo3',
94-
demoName: 'Dispute Resolution',
95-
status: 'locked',
96-
attempts: 0,
97-
pointsEarned: 0,
98-
},
99-
'dispute-resolution': {
100-
demoId: 'dispute-resolution',
101-
demoName: 'Drama Queen Escrow',
102-
status: 'locked',
103-
attempts: 0,
104-
pointsEarned: 0,
105-
},
106-
demo4: {
107-
demoId: 'demo4',
108-
demoName: 'Micro Task Marketplace',
109-
status: 'locked',
110-
attempts: 0,
111-
pointsEarned: 0,
112-
},
113-
'micro-marketplace': {
114-
demoId: 'micro-marketplace',
115-
demoName: 'Gig Economy Madness',
116-
status: 'locked',
117-
attempts: 0,
118-
pointsEarned: 0,
119-
},
12064
},
121-
122-
badges: [
123-
// Award Welcome Explorer badge for account creation
124-
{
125-
id: uuidv4(),
126-
name: 'Welcome Explorer',
127-
description: 'Joined the Nexus Experience community',
128-
imageUrl: '🌟',
129-
rarity: 'common' as const,
130-
earnedAt: now,
131-
pointsValue: 10,
132-
},
133-
],
134-
rewards: [],
135-
13665
stats: {
137-
totalDemosCompleted: 0,
138-
totalPointsEarned: 110, // Account creation bonus (100) + Welcome Explorer (10)
139-
totalTimeSpent: 0,
140-
streakDays: 1, // Start with 1 day streak
66+
totalPoints: 0, // Will be updated when badges are earned
14167
lastActiveDate: new Date().toISOString().split('T')[0],
14268
},
143-
144-
settings: {
145-
notifications: true,
146-
publicProfile: false,
147-
shareProgress: true,
148-
},
14969
};
15070

15171
await setDoc(doc(db, 'accounts', accountId), newAccount);

0 commit comments

Comments
 (0)