Implement API integration for statistics, recent chat messages, and top players; remove mock data

This commit is contained in:
2025-10-04 16:50:23 +08:00
parent af676aaa9f
commit 0174ac83e9

View File

@@ -1,47 +1,126 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { useState, useEffect } from 'react'
import Layout from './components/Layout' import Layout from './components/Layout'
import './App.css' import './App.css'
interface ChatMessage {
steamID64: string
userName: string
message: string
timeStamp: number
}
interface TopPlayer {
steamID64: string
userName: string
playTime: number
}
interface Stats {
totalPlayers: number
totalConnects: number
totalPlayTime: number
totalKills: number
}
function App() { function App() {
const { t } = useTranslation() const { t } = useTranslation()
// Mock data - in real app, this would come from API const [stats, setStats] = useState<Stats>({
// API endpoints: /api/server/statistics/* totalPlayers: 0,
// To integrate real API, replace mock data with: totalConnects: 0,
// totalPlayTime: 0,
// const [stats, setStats] = useState({ totalPlayers: 0, totalConnects: 0, totalPlayTime: 0, totalKills: 0 }) totalKills: 0
// })
// useEffect(() => { const [recentChats, setRecentChats] = useState<ChatMessage[]>([])
// const timeRangeEnd = Date.now() const [topPlayers, setTopPlayers] = useState<TopPlayer[]>([])
// 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 = { // Fetch statistics data from API
totalPlayers: 1247, // from /api/server/statistics/total-player-count useEffect(() => {
totalConnects: 3456, // from /api/server/statistics/total-connect-count const timeRangeEnd = Date.now()
totalPlayTime: 8640000, // from /api/server/statistics/total-play-time (in seconds) const timeRangeStart = 0 // all time
totalKills: 15420 // from /api/server/statistics/total-kill-count const requestBody = { timeRangeStart, timeRangeEnd }
}
Promise.all([
fetch('/api/server/statistics/total-player-count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
}),
fetch('/api/server/statistics/total-connect-count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
}),
fetch('/api/server/statistics/total-play-time', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
}),
fetch('/api/server/statistics/total-kill-count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...requestBody,
headshotOnly: false,
weaponFilter: [],
playerFilter: []
})
})
])
.then(responses => Promise.all(responses.map(r => r.json())))
.then(([players, connects, playTime, kills]) => {
setStats({
totalPlayers: players.count || 0,
totalConnects: connects.totalConnectCount || 0,
totalPlayTime: playTime.totalPlayTime || 0,
totalKills: kills.totalKillCount || 0
})
})
.catch(error => console.error('Error fetching stats:', error))
}, [])
// Fetch recent chat messages (limit to top 5)
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 => {
// Limit to top 5 most recent messages
const messages = data.messages || []
const top5 = messages
.sort((a: ChatMessage, b: ChatMessage) => b.timeStamp - a.timeStamp)
.slice(0, 5)
setRecentChats(top5)
})
.catch(error => console.error('Error fetching chat messages:', error))
}, [])
// Fetch top players by playtime
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 => {
// Get top 3 players
const players = data.players || []
setTopPlayers(players.slice(0, 3))
})
.catch(error => console.error('Error fetching top players:', error))
}, [])
// Format playtime from seconds to hours // Format playtime from seconds to hours
const formatPlayTime = (seconds: number) => { const formatPlayTime = (seconds: number) => {
@@ -54,75 +133,6 @@ function App() {
return hours.toLocaleString() 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 = [
{
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 // Format time ago from timestamp
const formatTimeAgo = (timestamp: number) => { const formatTimeAgo = (timestamp: number) => {
const seconds = Math.floor((Date.now() - timestamp) / 1000) const seconds = Math.floor((Date.now() - timestamp) / 1000)