feat: Add player profile performance charts and visualizations
Implemented comprehensive performance analysis for player profiles with interactive charts and detailed statistics visualization. Key Features: - Performance Trend Chart (K/D and KAST over last 15 matches) - Map Performance Chart (win rate per map with color coding) - Utility Effectiveness Stats (flash assists, enemies blinded, HE/flame damage) - Responsive charts using Chart.js LineChart and BarChart components Technical Updates: - Enhanced page loader to fetch 15 detailed matches with player stats - Fixed DataTable Svelte 5 compatibility and type safety - Updated MatchCard and PlayerCard to use PlayerMeta properties - Proper error handling and typed data structures 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,19 +13,50 @@ export const load: PageLoad = async ({ params }) => {
|
||||
// Fetch player profile and recent matches in parallel
|
||||
const [profile, matchesData] = await Promise.all([
|
||||
api.players.getPlayerMeta(playerId),
|
||||
api.matches.getMatches({ player_id: playerId, limit: 10 })
|
||||
api.matches.getMatches({ player_id: playerId, limit: 20 })
|
||||
]);
|
||||
|
||||
// Fetch full match details with player stats for performance charts
|
||||
// Limit to first 15 matches to avoid too many API calls
|
||||
const matchDetailsPromises = matchesData.matches
|
||||
.slice(0, 15)
|
||||
.map((match) => api.matches.getMatch(match.match_id));
|
||||
|
||||
const matchesWithDetails = await Promise.all(matchDetailsPromises);
|
||||
|
||||
// Extract player stats from each match
|
||||
const playerStats = matchesWithDetails
|
||||
.map((match) => {
|
||||
const playerData = match.players?.find((p) => p.id === playerId);
|
||||
if (!playerData) return null;
|
||||
|
||||
return {
|
||||
match_id: match.match_id,
|
||||
map: match.map,
|
||||
date: match.date,
|
||||
...playerData,
|
||||
// Add match result (did player win?)
|
||||
won:
|
||||
(playerData.team_id === 2 && match.score_team_a > match.score_team_b) ||
|
||||
(playerData.team_id === 3 && match.score_team_b > match.score_team_a)
|
||||
};
|
||||
})
|
||||
.filter((stat): stat is NonNullable<typeof stat> => stat !== null);
|
||||
|
||||
return {
|
||||
profile,
|
||||
recentMatches: matchesData.matches,
|
||||
recentMatches: matchesData.matches.slice(0, 10), // Show 10 in recent matches section
|
||||
playerStats, // Full stats for charts
|
||||
meta: {
|
||||
title: `${profile.name} - Player Profile | CS2.WTF`,
|
||||
description: `View ${profile.name}'s CS2 statistics, match history, and performance metrics.`
|
||||
}
|
||||
};
|
||||
} catch (err) {
|
||||
console.error(`Failed to load player ${playerId}:`, err);
|
||||
console.error(
|
||||
`Failed to load player ${playerId}:`,
|
||||
err instanceof Error ? err.message : String(err)
|
||||
);
|
||||
throw error(404, `Player ${playerId} not found`);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user