refactor: 플레이어 통계 페이지 UI 개선

- 일반 통계 → 전투 통계로 변경 (Sword 아이콘)
- 이동 거리 → 이동 통계로 변경, StatCard 스타일 적용
- 점프 횟수를 이동 통계 섹션으로 이동
- 이동 통계 아이콘 다양화 (Footprints, Plane, Waves, ChevronsUp)
- 거리 표시 형식 변경: 1000m 이상은 km 단위 (소수점 둘째자리)
- Tooltip 제거 (불필요)
This commit is contained in:
caadiq 2025-12-24 16:47:07 +09:00
parent 3661de82ca
commit c82b24c989

View file

@ -1,10 +1,9 @@
import React, { useState, useEffect, useRef } from 'react';
import { useParams } from 'react-router-dom';
import { Activity, Skull, Heart, LocateFixed, Box, Sword, Clock, Calendar, RefreshCw, ImageOff } from 'lucide-react';
import { Activity, Skull, Heart, LocateFixed, Box, Sword, Clock, Calendar, RefreshCw, ImageOff, Footprints, Plane, Waves, ChevronsUp } from 'lucide-react';
import { motion } from 'framer-motion';
import { io } from 'socket.io-client';
import { formatDate, formatPlayTimeMs } from '../utils/formatters';
import Tooltip from '../components/Tooltip';
// 3D ( / )
@ -46,15 +45,8 @@ const DEFAULT_ICON = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA
// - 1 "1.2m"
const formatDistance = (meters) => {
if (meters >= 100000000) {
// 1
return `${(meters / 100000000).toFixed(1)}억m`;
} else if (meters >= 10000000) {
//
return `${(meters / 10000000).toFixed(1)}천만m`;
} else if (meters >= 10000) {
//
return `${(meters / 10000).toFixed(1)}만m`;
if (meters >= 1000) {
return `${(meters / 1000).toFixed(2)}km`;
}
return `${meters.toLocaleString()}m`;
};
@ -243,26 +235,25 @@ const PlayerStatsPage = ({ isMobile = false }) => {
</motion.section>
)}
{/* 일반 통계 */}
{/* 전투 통계 */}
<motion.section
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2, duration: 0.3 }}
>
<h2 className="text-xl font-bold text-white mb-4 flex items-center gap-2">
<Activity className="text-mc-green" />
일반 통계
<Sword className="text-orange-400" />
전투 통계
</h2>
<div className="grid grid-cols-2 md:grid-cols-5 gap-3">
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
<StatCard icon={Skull} label="사망 횟수" value={stats.general.deaths} color="text-red-400" />
<StatCard icon={Sword} label="몹 처치" value={stats.general.mobKills} color="text-orange-400" />
<StatCard icon={Sword} label="입힌 피해" value={stats.general.damageDealt} color="text-yellow-400" />
<StatCard icon={Heart} label="받은 피해" value={stats.general.damageTaken} color="text-pink-400" />
<StatCard icon={LocateFixed} label="점프 횟수" value={stats.general.jumps} color="text-blue-400" />
</div>
</motion.section>
{/* 이동 거리 */}
{/* 이동 통계 */}
<motion.section
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
@ -270,27 +261,33 @@ const PlayerStatsPage = ({ isMobile = false }) => {
>
<h2 className="text-xl font-bold text-white mb-4 flex items-center gap-2">
<LocateFixed className="text-blue-400" />
이동 거리
이동 통계
</h2>
<div className="grid grid-cols-3 gap-3">
<div className="glow-card rounded-xl p-4 flex flex-col items-center justify-center">
<p className="text-gray-400 text-sm mb-1">걸은 거리</p>
<p className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-2xl'}`}>
{isMobile ? formatDistance(stats.general.distanceWalked) : `${stats.general.distanceWalked.toLocaleString()}m`}
</p>
</div>
<div className="glow-card rounded-xl p-4 flex flex-col items-center justify-center">
<p className="text-gray-400 text-sm mb-1">비행 거리</p>
<p className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-2xl'}`}>
{isMobile ? formatDistance(stats.general.distanceFlown) : `${stats.general.distanceFlown.toLocaleString()}m`}
</p>
</div>
<div className="glow-card rounded-xl p-4 flex flex-col items-center justify-center">
<p className="text-gray-400 text-sm mb-1">수영 거리</p>
<p className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-2xl'}`}>
{isMobile ? formatDistance(stats.general.distanceSwum) : `${stats.general.distanceSwum.toLocaleString()}m`}
</p>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
<StatCard
icon={Footprints}
label="걸은 거리"
value={formatDistance(stats.general.distanceWalked)}
color="text-green-400"
/>
<StatCard
icon={Plane}
label="비행 거리"
value={formatDistance(stats.general.distanceFlown)}
color="text-purple-400"
/>
<StatCard
icon={Waves}
label="수영 거리"
value={formatDistance(stats.general.distanceSwum)}
color="text-cyan-400"
/>
<StatCard
icon={ChevronsUp}
label="점프 횟수"
value={stats.general.jumps}
color="text-blue-400"
/>
</div>
</motion.section>
@ -406,11 +403,9 @@ const ItemStatRow = ({ item, translate, icons }) => {
</div>
)}
<div className="flex-1 min-w-0">
<Tooltip content={translate(item.id)}>
<p className="text-white text-sm font-medium truncate">
{translate(item.id)}
</p>
</Tooltip>
<p className="text-white text-sm font-medium truncate">
{translate(item.id)}
</p>
<div className="flex flex-wrap gap-x-2 text-xs text-gray-400">
{item.mined > 0 && <span>채굴 <span className="text-yellow-400">{item.mined}</span></span>}
{item.used > 0 && <span>사용 <span className="text-blue-400">{item.used}</span></span>}
@ -461,11 +456,9 @@ const MobStatRow = ({ mob, translate, icons }) => {
</div>
)}
<div className="flex-1 min-w-0">
<Tooltip content={translate(mob.id)}>
<p className="text-white text-sm font-medium truncate">
{translate(mob.id)}
</p>
</Tooltip>
<p className="text-white text-sm font-medium truncate">
{translate(mob.id)}
</p>
<div className="flex flex-wrap gap-x-2 text-xs text-gray-400">
{mob.killed > 0 && <span>처치 <span className="text-red-400">{mob.killed}</span></span>}
{mob.killedBy > 0 && <span>죽음 <span className="text-gray-300">{mob.killedBy}</span></span>}