fix: Fix player profile loading with API transformer and improve UI layout
- Add LegacyPlayerProfile transformer to handle API response format mismatch - Transform avatar hashes to full Steam CDN URLs - Map team IDs correctly (API 1/2 -> Schema 2/3) - Calculate aggregate stats (avg_kills, avg_deaths, win_rate) from matches - Reduce featured matches on homepage from 6 to 3 - Show 4 recent matches on player profile instead of 10 - Display recent matches in 4-column grid on desktop (side-by-side) Fixes "Player not found" error for all player profiles. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -161,3 +161,101 @@ export function transformMatchDetail(legacy: LegacyMatchDetail): Match {
|
||||
players: legacy.stats?.map(transformPlayerStats)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy player profile format from API
|
||||
*/
|
||||
export interface LegacyPlayerProfile {
|
||||
steamid64: string;
|
||||
name: string;
|
||||
avatar: string; // Hash, not full URL
|
||||
vac: boolean;
|
||||
vac_date: number; // Unix timestamp
|
||||
game_ban: boolean;
|
||||
game_ban_date: number; // Unix timestamp
|
||||
tracked: boolean;
|
||||
match_stats?: {
|
||||
win: number;
|
||||
loss: number;
|
||||
};
|
||||
matches?: Array<{
|
||||
match_id: string;
|
||||
map: string;
|
||||
date: number;
|
||||
score: [number, number];
|
||||
duration: number;
|
||||
match_result: number;
|
||||
max_rounds: number;
|
||||
parsed: boolean;
|
||||
vac: boolean;
|
||||
game_ban: boolean;
|
||||
stats: {
|
||||
team_id: number;
|
||||
kills: number;
|
||||
deaths: number;
|
||||
assists: number;
|
||||
headshot: number;
|
||||
mvp: number;
|
||||
score: number;
|
||||
rank: Record<string, unknown>;
|
||||
multi_kills?: Record<string, number>;
|
||||
dmg?: Record<string, unknown>;
|
||||
};
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform legacy player profile to schema-compatible format
|
||||
*/
|
||||
export function transformPlayerProfile(legacy: LegacyPlayerProfile) {
|
||||
// Unix timestamp -62135596800 represents "no date" (year 0)
|
||||
const hasVacDate = legacy.vac_date && legacy.vac_date > 0;
|
||||
const hasGameBanDate = legacy.game_ban_date && legacy.game_ban_date > 0;
|
||||
|
||||
return {
|
||||
id: legacy.steamid64,
|
||||
name: legacy.name,
|
||||
avatar: `https://avatars.steamstatic.com/${legacy.avatar}_full.jpg`,
|
||||
steam_updated: new Date().toISOString(), // Not provided by API
|
||||
vac_count: legacy.vac ? 1 : 0,
|
||||
vac_date: hasVacDate ? new Date(legacy.vac_date * 1000).toISOString() : null,
|
||||
game_ban_count: legacy.game_ban ? 1 : 0,
|
||||
game_ban_date: hasGameBanDate ? new Date(legacy.game_ban_date * 1000).toISOString() : null,
|
||||
wins: legacy.match_stats?.win,
|
||||
losses: legacy.match_stats?.loss,
|
||||
matches: legacy.matches?.map((match) => ({
|
||||
match_id: match.match_id,
|
||||
map: match.map || 'unknown',
|
||||
date: new Date(match.date * 1000).toISOString(),
|
||||
score_team_a: match.score[0],
|
||||
score_team_b: match.score[1],
|
||||
duration: match.duration,
|
||||
match_result: match.match_result,
|
||||
max_rounds: match.max_rounds,
|
||||
demo_parsed: match.parsed,
|
||||
vac_present: match.vac,
|
||||
gameban_present: match.game_ban,
|
||||
tick_rate: 64, // Not provided by API
|
||||
stats: {
|
||||
id: legacy.steamid64,
|
||||
name: legacy.name,
|
||||
avatar: `https://avatars.steamstatic.com/${legacy.avatar}_full.jpg`,
|
||||
// Fix team_id: API returns 1/2, but schema expects min 2
|
||||
// Map: 1 -> 2 (Terrorists), 2 -> 3 (Counter-Terrorists)
|
||||
team_id:
|
||||
match.stats.team_id === 1 ? 2 : match.stats.team_id === 2 ? 3 : match.stats.team_id,
|
||||
kills: match.stats.kills,
|
||||
deaths: match.stats.deaths,
|
||||
assists: match.stats.assists,
|
||||
headshot: match.stats.headshot,
|
||||
mvp: match.stats.mvp,
|
||||
score: match.stats.score,
|
||||
kast: 0,
|
||||
mk_2: match.stats.multi_kills?.duo,
|
||||
mk_3: match.stats.multi_kills?.triple,
|
||||
mk_4: match.stats.multi_kills?.quad,
|
||||
mk_5: match.stats.multi_kills?.ace
|
||||
}
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user