Skip to content

Commit 3361be7

Browse files
committed
feat: Fix game leaderboard scores and add avatar/badge sync
- Fix username resolution in game score submission (InfiniteRunner, EscrowPuzzleMaster) - Add proper fallback chain for display names to prevent 'Anonymous' scores - Support both UserAccount and legacy Account types - Add dynamic badge display in RewardsSidebar Overview tab - Badge name and styling now changes with avatar phase navigation - Add visual badge card with icons (🌱/🚀/⭐) for each phase - Implement smooth transitions between phases - Phases: Trustless Scout (L1+), Blockchain Explorer (L5+), Stellar Expert (L10+) - Update GameSidebar with improved leaderboard loading - Add documentation for avatar/badge synchronization feature
1 parent 878fc8d commit 3361be7

File tree

5 files changed

+367
-104
lines changed

5 files changed

+367
-104
lines changed

AVATAR_BADGE_SYNC_UPDATE.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Avatar and Badge Synchronization Update
2+
3+
## Feature Enhancement
4+
5+
Added dynamic badge display that changes in sync with the avatar phase navigation on the Nexus Account RewardsSidebar Overview tab.
6+
7+
## Changes Made
8+
9+
### 1. Dynamic Phase Badge Label (Line 242-245)
10+
11+
**Before:**
12+
```typescript
13+
<div className='absolute -top-6 -right-3 bg-gradient-to-r from-yellow-400 to-orange-500 text-black text-sm font-bold px-3 py-1 rounded-full shadow-lg border-2 border-white/20'>
14+
{level < 5 ? 'Trustless Scout' : level < 10 ? 'Blockchain Explorer' : 'Stellar Expert'}
15+
</div>
16+
```
17+
18+
**After:**
19+
```typescript
20+
<div className='absolute -top-6 -right-3 bg-gradient-to-r from-yellow-400 to-orange-500 text-black text-sm font-bold px-3 py-1 rounded-full shadow-lg border-2 border-white/20 transition-all duration-300'>
21+
{currentPhase?.name || 'Trustless Scout'}
22+
</div>
23+
```
24+
25+
**Result:** The badge label now changes when using the arrow buttons, not just based on level.
26+
27+
### 2. New Badge Display Component (Lines 267-294)
28+
29+
Added a visual badge card below the avatar that displays:
30+
- **Badge icon** that changes per phase:
31+
- 🌱 for Trustless Scout (Phase 0)
32+
- 🚀 for Blockchain Explorer (Phase 1)
33+
- ⭐ for Stellar Expert (Phase 2)
34+
35+
- **Badge name** synchronized with arrow navigation
36+
- **Level requirement** shown for each phase
37+
- **Color-coded borders and backgrounds**:
38+
- Green gradient for Trustless Scout
39+
- Blue gradient for Blockchain Explorer
40+
- Purple gradient for Stellar Expert
41+
42+
- **Smooth transitions** when switching between phases
43+
44+
### 3. Enhanced Phase Navigation (Lines 171-185)
45+
46+
Updated the arrow navigation handlers with better structure for future enhancements.
47+
48+
## How It Works
49+
50+
### Avatar Phases
51+
The avatar has three phases that unlock based on player level:
52+
53+
| Phase | Name | Image | Min Level | Icon | Color |
54+
|-------|------|-------|-----------|------|-------|
55+
| 0 | Trustless Scout | baby.png | 1 | 🌱 | Green |
56+
| 1 | Blockchain Explorer | teen.png | 5 | 🚀 | Blue |
57+
| 2 | Stellar Expert | nexus-prime-chat.png | 10 || Purple |
58+
59+
### Navigation Flow
60+
1. User opens the Nexus Account (RewardsSidebar)
61+
2. Clicks on the Overview tab
62+
3. Sees their current avatar with navigation arrows (if multiple phases unlocked)
63+
4. Clicks left/right arrows to cycle through unlocked phases
64+
5. **Badge changes automatically** to match the selected phase:
65+
- Badge label above avatar updates
66+
- Badge card below avatar updates with new icon, name, and colors
67+
68+
### Visual Feedback
69+
- **Avatar image** changes with smooth transition
70+
- **Top badge label** changes with fade transition
71+
- **Badge card** changes colors and icons with smooth animation
72+
- **Phase indicators** (dots) show which phase is selected
73+
74+
## User Experience Improvements
75+
76+
### Before
77+
- Badge label was fixed based on current level
78+
- No visual badge representation
79+
- Unclear what phase you were viewing when using arrows
80+
81+
### After
82+
- Badge label changes dynamically with arrow navigation
83+
- Visual badge card with icon and styling
84+
- Clear indication of which phase is being viewed
85+
- Color-coded system makes phases easily distinguishable
86+
- Smooth transitions provide polished feel
87+
88+
## Testing Checklist
89+
90+
To test the new feature:
91+
92+
- [ ] Open Nexus Account sidebar (user profile dropdown)
93+
- [ ] Click Overview tab
94+
- [ ] If Level 5+: Use right arrow to cycle through phases
95+
- [ ] Verify badge label above avatar changes (Trustless Scout → Blockchain Explorer → Stellar Expert)
96+
- [ ] Verify badge card below avatar changes:
97+
- [ ] Icon changes (🌱 → 🚀 → ⭐)
98+
- [ ] Name changes
99+
- [ ] Colors change (Green → Blue → Purple)
100+
- [ ] Level requirement updates
101+
- [ ] Use left arrow to go backward
102+
- [ ] Verify changes are smooth with transitions
103+
- [ ] Check phase indicator dots highlight correctly
104+
105+
## Code Structure
106+
107+
### Component: RewardsSidebar.tsx
108+
109+
**State:**
110+
- `selectedCharacterPhase` (0-2): Tracks which phase is currently selected
111+
112+
**Functions:**
113+
- `getAvailableCharacterPhases()`: Returns phases unlocked based on level
114+
- `handlePreviousPhase()`: Cycles to previous phase
115+
- `handleNextPhase()`: Cycles to next phase
116+
117+
**Display:**
118+
- `currentPhase`: The phase object for currently selected phase
119+
- `availablePhases`: Array of unlocked phases
120+
121+
### Badge Display Structure
122+
123+
```
124+
Avatar Container
125+
├── Navigation Arrows (Previous/Next)
126+
├── Avatar Image (changes with phase)
127+
├── Top Badge Label (shows phase name)
128+
├── Phase Indicator Dots
129+
└── Badge Card (NEW)
130+
├── Icon (🌱/🚀/⭐)
131+
├── Phase Name
132+
└── Level Requirement
133+
```
134+
135+
## Visual Design
136+
137+
### Trustless Scout (Phase 0)
138+
- **Background:** Green gradient (`from-green-500/20 to-emerald-500/20`)
139+
- **Border:** Green (`border-green-400/50`)
140+
- **Text:** Green (`text-green-300`)
141+
- **Icon:** 🌱 (Seedling)
142+
- **Level:** 1+
143+
144+
### Blockchain Explorer (Phase 1)
145+
- **Background:** Blue gradient (`from-blue-500/20 to-indigo-500/20`)
146+
- **Border:** Blue (`border-blue-400/50`)
147+
- **Text:** Blue (`text-blue-300`)
148+
- **Icon:** 🚀 (Rocket)
149+
- **Level:** 5+
150+
151+
### Stellar Expert (Phase 2)
152+
- **Background:** Purple gradient (`from-purple-500/20 to-pink-500/20`)
153+
- **Border:** Purple (`border-purple-400/50`)
154+
- **Text:** Purple (`text-purple-300`)
155+
- **Icon:** ⭐ (Star)
156+
- **Level:** 10+
157+
158+
## Future Enhancements
159+
160+
Potential improvements for future updates:
161+
162+
1. **Sound effects** when changing phases
163+
2. **Animation effects** (sparkles, particles) when cycling
164+
3. **Badge unlock animations** when reaching new level thresholds
165+
4. **Hover tooltips** with phase descriptions
166+
5. **Achievement tracking** for phase milestones
167+
6. **Share phase** on social media
168+
7. **Phase-specific rewards** or perks
169+
170+
## Files Modified
171+
172+
1. `components/ui/RewardsSidebar.tsx` - Main component with badge sync functionality
173+
2. `AVATAR_BADGE_SYNC_UPDATE.md` - This documentation
174+
175+
## Related Components
176+
177+
- `PixelArtAvatar.tsx` - Avatar display component
178+
- `Badge3D.tsx` - 3D badge rendering
179+
- `UserProfile.tsx` - User profile dropdown
180+
- `Header.tsx` - Contains user profile button
181+
182+
## Summary
183+
184+
Users can now cycle through their unlocked avatar phases using the arrow buttons, and the badge display will change in real-time to show the corresponding badge (Trustless Scout, Blockchain Explorer, or Stellar Expert) with proper visual styling, icons, and colors. This provides a more interactive and engaging experience when exploring character progression!
185+

components/games/EscrowPuzzleMaster.tsx

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
import { useState, useEffect } from 'react';
44
import Image from 'next/image';
5+
import { useAccount } from '@/contexts/auth/AccountContext';
6+
import { useToast } from '@/contexts/ui/ToastContext';
7+
import { gameScoresService } from '@/lib/firebase/firebase-service';
8+
import GameSidebar from './GameSidebar';
59

610
interface Puzzle {
711
id: number;
@@ -65,13 +69,20 @@ const puzzles: Puzzle[] = [
6569
];
6670

6771
export default function EscrowPuzzleMaster() {
72+
const { account } = useAccount();
73+
const { addToast } = useToast();
74+
6875
const [currentPuzzle, setCurrentPuzzle] = useState(0);
6976
const [selectedAnswer, setSelectedAnswer] = useState<number | null>(null);
7077
const [showResult, setShowResult] = useState(false);
7178
const [score, setScore] = useState(0);
7279
const [gameState, setGameState] = useState<'intro' | 'playing' | 'completed'>('intro');
7380
const [timeLeft, setTimeLeft] = useState(60);
7481
const [achievements, setAchievements] = useState<string[]>([]);
82+
const [scoreSaved, setScoreSaved] = useState(false);
83+
84+
const gameId = 'escrow-puzzle-master';
85+
const gameTitle = 'Escrow Puzzle Master';
7586

7687
useEffect(() => {
7788
if (gameState === 'playing' && timeLeft > 0) {
@@ -119,14 +130,57 @@ export default function EscrowPuzzleMaster() {
119130
}
120131
};
121132

133+
const saveScoreToLeaderboard = async (finalScore: number) => {
134+
if (!account || scoreSaved) return;
135+
136+
try {
137+
await gameScoresService.submitScore(
138+
gameId,
139+
account.id,
140+
account.profile?.displayName || account.profile?.username || account.displayName || 'Anonymous',
141+
finalScore,
142+
1, // Level not applicable for puzzle game
143+
{
144+
puzzlesSolved: currentPuzzle + 1,
145+
achievementsUnlocked: achievements.length,
146+
}
147+
);
148+
149+
setScoreSaved(true);
150+
151+
addToast({
152+
type: 'success',
153+
title: '🏆 Score Saved!',
154+
message: `Your score of ${finalScore} has been recorded!`,
155+
duration: 3000,
156+
});
157+
} catch (error) {
158+
console.error('Failed to save score:', error);
159+
addToast({
160+
type: 'error',
161+
title: 'Save Failed',
162+
message: 'Could not save your score to the leaderboard.',
163+
duration: 3000,
164+
});
165+
}
166+
};
167+
122168
const resetGame = () => {
123169
setGameState('intro');
124170
setScore(0);
125171
setCurrentPuzzle(0);
126172
setSelectedAnswer(null);
127173
setShowResult(false);
128174
setAchievements([]);
175+
setScoreSaved(false);
129176
};
177+
178+
// Save score when game completes
179+
useEffect(() => {
180+
if (gameState === 'completed' && !scoreSaved && account) {
181+
saveScoreToLeaderboard(score);
182+
}
183+
}, [gameState, scoreSaved, score, account]);
130184

131185
if (gameState === 'intro') {
132186
return (
@@ -356,5 +410,9 @@ export default function EscrowPuzzleMaster() {
356410
);
357411
}
358412

359-
return null;
413+
return (
414+
<>
415+
<GameSidebar gameId={gameId} gameTitle={gameTitle} currentScore={score} currentLevel={1} />
416+
</>
417+
);
360418
}

0 commit comments

Comments
 (0)