Refactor App component to integrate mock statistics and recent chat messages; update localization for stats and activity sections

This commit is contained in:
2025-10-04 13:23:40 +08:00
parent ff056c4c47
commit af676aaa9f
3 changed files with 165 additions and 46 deletions

View File

@@ -7,21 +7,139 @@ function App() {
const { t } = useTranslation()
// Mock data - in real app, this would come from API
// API endpoints: /api/server/statistics/*
// To integrate real API, replace mock data with:
//
// const [stats, setStats] = useState({ totalPlayers: 0, totalConnects: 0, totalPlayTime: 0, totalKills: 0 })
//
// useEffect(() => {
// const timeRangeEnd = Date.now()
// const timeRangeStart = 0 // or specific start time
// const requestBody = { timeRangeStart, timeRangeEnd, playerFilter: [] }
//
// Promise.all([
// fetch('/api/server/statistics/total-player-count', { method: 'POST', body: JSON.stringify(requestBody) }),
// fetch('/api/server/statistics/total-connect-count', { method: 'POST', body: JSON.stringify(requestBody) }),
// fetch('/api/server/statistics/total-play-time', { method: 'POST', body: JSON.stringify(requestBody) }),
// fetch('/api/server/statistics/total-kill-count', {
// method: 'POST',
// body: JSON.stringify({ ...requestBody, headshotOnly: false, weaponFilter: [] })
// })
// ]).then(responses => Promise.all(responses.map(r => r.json())))
// .then(([players, connects, playTime, kills]) => {
// setStats({
// totalPlayers: players.count,
// totalConnects: connects.totalConnectCount,
// totalPlayTime: playTime.totalPlayTime,
// totalKills: kills.totalKillCount
// })
// })
// }, [])
const stats = {
onlinePlayers: 1247,
totalServers: 89,
totalPlayTime: '2.4M',
activeGames: 23
totalPlayers: 1247, // from /api/server/statistics/total-player-count
totalConnects: 3456, // from /api/server/statistics/total-connect-count
totalPlayTime: 8640000, // from /api/server/statistics/total-play-time (in seconds)
totalKills: 15420 // from /api/server/statistics/total-kill-count
}
// Format playtime from seconds to hours
const formatPlayTime = (seconds: number) => {
const hours = Math.floor(seconds / 3600)
if (hours >= 1000000) {
return `${(hours / 1000000).toFixed(1)}M`
} else if (hours >= 1000) {
return `${(hours / 1000).toFixed(1)}K`
}
return hours.toLocaleString()
}
// Mock recent chat messages - from /api/server/statistics/recent-chat-message
// Response format: { messages: [{ steamID64, userName, message, timeStamp }] }
// To integrate real API:
// const [recentChats, setRecentChats] = useState([])
// useEffect(() => {
// fetch('/api/server/statistics/recent-chat-message', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({
// timeRangeStart: Date.now() - 3600000, // last hour
// timeRangeEnd: Date.now()
// })
// }).then(r => r.json())
// .then(data => setRecentChats(data.messages))
// }, [])
const recentChats = [
{ user: 'ProGamer99', message: 'GG everyone! Great match!', time: '2m ago' },
{ user: 'SniperElite', message: 'Anyone up for a quick match?', time: '5m ago' },
{ user: 'HeadshotKing', message: 'New server just went live!', time: '8m ago' },
{ user: 'TacticalNuke', message: 'Looking for team players', time: '12m ago' },
{ user: 'FragMaster', message: 'Server maintenance complete', time: '15m ago' }
{
steamID64: '76561198281616762',
userName: 'ProGamer99',
message: 'GG everyone! Great match!',
timeStamp: Date.now() - 120000 // 2 minutes ago
},
{
steamID64: '76561198281616763',
userName: 'SniperElite',
message: 'Anyone up for a quick match?',
timeStamp: Date.now() - 300000 // 5 minutes ago
},
{
steamID64: '76561198281616764',
userName: 'HeadshotKing',
message: 'New server just went live!',
timeStamp: Date.now() - 480000 // 8 minutes ago
},
{
steamID64: '76561198281616765',
userName: 'TacticalNuke',
message: 'Looking for team players',
timeStamp: Date.now() - 720000 // 12 minutes ago
},
{
steamID64: '76561198281616766',
userName: 'FragMaster',
message: 'Server maintenance complete',
timeStamp: Date.now() - 900000 // 15 minutes ago
}
]
// Mock top players - from /api/server/statistics/top-play-time
// Response format: { players: [{ steamID64, userName, playTime }] }
// To integrate real API:
// const [topPlayers, setTopPlayers] = useState([])
// useEffect(() => {
// fetch('/api/server/statistics/top-play-time', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({
// timeRangeStart: 0, // all time
// timeRangeEnd: Date.now()
// })
// }).then(r => r.json())
// .then(data => setTopPlayers(data.players.slice(0, 3))) // top 3
// }, [])
const topPlayers = [
{ steamID64: '76561198281616762', userName: 'ProGamer99', playTime: 882000 }, // 245 hours
{ steamID64: '76561198281616763', userName: 'SniperElite', playTime: 784800 }, // 218 hours
{ steamID64: '76561198281616764', userName: 'HeadshotKing', playTime: 702000 } // 195 hours
]
// Format time ago from timestamp
const formatTimeAgo = (timestamp: number) => {
const seconds = Math.floor((Date.now() - timestamp) / 1000)
if (seconds < 60) return `${seconds}s ago`
const minutes = Math.floor(seconds / 60)
if (minutes < 60) return `${minutes}m ago`
const hours = Math.floor(minutes / 60)
if (hours < 24) return `${hours}h ago`
const days = Math.floor(hours / 24)
return `${days}d ago`
}
// Format playtime to hours for leaderboard
const formatPlayTimeHours = (seconds: number) => {
return Math.floor(seconds / 3600)
}
return (
<Layout currentPage="home">
{/* Hero Section */}
@@ -57,23 +175,23 @@ function App() {
<div className="stats-container">
<div className="stat-card">
<div className="stat-icon">👥</div>
<div className="stat-number">{stats.onlinePlayers.toLocaleString()}</div>
<div className="stat-label">{t('stats.onlinePlayers')}</div>
<div className="stat-number">{stats.totalPlayers.toLocaleString()}</div>
<div className="stat-label">{t('stats.totalPlayers')}</div>
</div>
<div className="stat-card">
<div className="stat-icon">🖥</div>
<div className="stat-number">{stats.totalServers}</div>
<div className="stat-label">{t('stats.activeServers')}</div>
<div className="stat-icon"><EFBFBD></div>
<div className="stat-number">{stats.totalConnects.toLocaleString()}</div>
<div className="stat-label">{t('stats.totalConnects')}</div>
</div>
<div className="stat-card">
<div className="stat-icon"></div>
<div className="stat-number">{stats.totalPlayTime}</div>
<div className="stat-label">{t('stats.hoursPlayed')}</div>
<div className="stat-number">{formatPlayTime(stats.totalPlayTime)}</div>
<div className="stat-label">{t('stats.totalPlayTime')}</div>
</div>
<div className="stat-card">
<div className="stat-icon">🎯</div>
<div className="stat-number">{stats.activeGames}</div>
<div className="stat-label">{t('stats.liveMatches')}</div>
<div className="stat-number">{stats.totalKills.toLocaleString()}</div>
<div className="stat-label">{t('stats.totalKills')}</div>
</div>
</div>
</section>
@@ -125,9 +243,9 @@ function App() {
<div className="chat-feed">
{recentChats.map((chat, index) => (
<div key={index} className="chat-message">
<div className="chat-user">{chat.user}:</div>
<div className="chat-user">{chat.userName}:</div>
<div className="chat-text">{chat.message}</div>
<div className="chat-time">{chat.time}</div>
<div className="chat-time">{formatTimeAgo(chat.timeStamp)}</div>
</div>
))}
</div>
@@ -136,17 +254,19 @@ function App() {
<div className="sidebar-card">
<h3>{t('activity.topPlayers')}</h3>
<div className="leaderboard">
<div className="leader-item">1. ProGamer99 - 2,450 pts</div>
<div className="leader-item">2. SniperElite - 2,180 pts</div>
<div className="leader-item">3. HeadshotKing - 1,950 pts</div>
{topPlayers.map((player, index) => (
<div key={player.steamID64} className="leader-item">
{index + 1}. {player.userName} - {formatPlayTimeHours(player.playTime)}h
</div>
))}
</div>
</div>
<div className="sidebar-card">
<h3>{t('activity.quickStats')}</h3>
<h3>{t('activity.serverInfo')}</h3>
<div className="quick-stats">
<div>{t('activity.avgMatchTime')}</div>
<div>{t('activity.mostPopularMap')}</div>
<div>{t('activity.peakHours')}</div>
<div>{t('activity.serverStatus')}</div>
<div>{t('activity.currentMap')}</div>
<div>{t('activity.nextRestart')}</div>
</div>
</div>
</div>

View File

@@ -18,10 +18,10 @@
"viewStats": "📊 View Stats"
},
"stats": {
"onlinePlayers": "Online Players",
"activeServers": "Active Servers",
"hoursPlayed": "Hours Played",
"liveMatches": "Live Matches"
"totalPlayers": "Total Players",
"totalConnects": "Total Connections",
"totalPlayTime": "Hours Played",
"totalKills": "Total Kills"
},
"features": {
"title": "Community Features",
@@ -53,11 +53,11 @@
},
"activity": {
"title": "Recent Activity",
"topPlayers": "🏆 Top Players",
"quickStats": "🎯 Quick Stats",
"avgMatchTime": "Avg Match Time: 12m 34s",
"mostPopularMap": "Most Popular Map: Dust2",
"peakHours": "Peak Hours: 8-11 PM"
"topPlayers": "Top Players by Playtime",
"serverInfo": "Server Info",
"serverStatus": "Status: Online ✓",
"currentMap": "Map: de_dust2",
"nextRestart": "Restart: 6h 30m"
},
"footer": {
"community": "🎯 CS Community",

View File

@@ -1,6 +1,5 @@
{
"nav": {
"logo": "CS 社区",
"home": "首页",
"servers": "服务器",
"blog": "博客",
@@ -18,10 +17,10 @@
"viewStats": "📊 查看统计"
},
"stats": {
"onlinePlayers": "在线玩家",
"activeServers": "活跃服务器",
"hoursPlayed": "游戏时长",
"liveMatches": "实时比赛"
"totalPlayers": "玩家",
"totalConnects": "总连接数",
"totalPlayTime": "游戏时长",
"totalKills": "总击杀数"
},
"features": {
"title": "社区功能",
@@ -53,11 +52,11 @@
},
"activity": {
"title": "最近活动",
"topPlayers": "🏆 顶级玩家",
"quickStats": "🎯 快速统计",
"avgMatchTime": "平均比赛时长12分34秒",
"mostPopularMap": "最受欢迎地图Dust2",
"peakHours": "高峰时段晚上8-11点"
"topPlayers": "游戏时长排行榜",
"serverInfo": "服务器信息",
"serverStatus": "状态:在线 ✓",
"currentMap": "地图de_dust2",
"nextRestart": "重启6小时30分钟"
},
"footer": {
"community": "🎯 CS 社区",