refactor: 플레이어 통계 페이지 UI 개선
- 일반 통계 → 전투 통계로 변경 (Sword 아이콘) - 이동 거리 → 이동 통계로 변경, StatCard 스타일 적용 - 점프 횟수를 이동 통계 섹션으로 이동 - 이동 통계 아이콘 다양화 (Footprints, Plane, Waves, ChevronsUp) - 거리 표시 형식 변경: 1000m 이상은 km 단위 (소수점 둘째자리) - Tooltip 제거 (불필요)
This commit is contained in:
parent
3661de82ca
commit
c82b24c989
1 changed files with 40 additions and 47 deletions
|
|
@ -1,10 +1,9 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
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 { motion } from 'framer-motion';
|
||||||
import { io } from 'socket.io-client';
|
import { io } from 'socket.io-client';
|
||||||
import { formatDate, formatPlayTimeMs } from '../utils/formatters';
|
import { formatDate, formatPlayTimeMs } from '../utils/formatters';
|
||||||
import Tooltip from '../components/Tooltip';
|
|
||||||
|
|
||||||
|
|
||||||
// 스티브 3D 스킨 기본 이미지 (로딩 전/실패 시 사용)
|
// 스티브 3D 스킨 기본 이미지 (로딩 전/실패 시 사용)
|
||||||
|
|
@ -46,15 +45,8 @@ const DEFAULT_ICON = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA
|
||||||
|
|
||||||
// 거리 포맷 함수 - 1만 이상이면 "1.2만m" 형식으로 표시
|
// 거리 포맷 함수 - 1만 이상이면 "1.2만m" 형식으로 표시
|
||||||
const formatDistance = (meters) => {
|
const formatDistance = (meters) => {
|
||||||
if (meters >= 100000000) {
|
if (meters >= 1000) {
|
||||||
// 1억 이상
|
return `${(meters / 1000).toFixed(2)}km`;
|
||||||
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`;
|
|
||||||
}
|
}
|
||||||
return `${meters.toLocaleString()}m`;
|
return `${meters.toLocaleString()}m`;
|
||||||
};
|
};
|
||||||
|
|
@ -243,26 +235,25 @@ const PlayerStatsPage = ({ isMobile = false }) => {
|
||||||
</motion.section>
|
</motion.section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 일반 통계 */}
|
{/* 전투 통계 */}
|
||||||
<motion.section
|
<motion.section
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ delay: 0.2, duration: 0.3 }}
|
transition={{ delay: 0.2, duration: 0.3 }}
|
||||||
>
|
>
|
||||||
<h2 className="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
<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>
|
</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={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.mobKills} color="text-orange-400" />
|
||||||
<StatCard icon={Sword} label="입힌 피해" value={stats.general.damageDealt} color="text-yellow-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={Heart} label="받은 피해" value={stats.general.damageTaken} color="text-pink-400" />
|
||||||
<StatCard icon={LocateFixed} label="점프 횟수" value={stats.general.jumps} color="text-blue-400" />
|
|
||||||
</div>
|
</div>
|
||||||
</motion.section>
|
</motion.section>
|
||||||
|
|
||||||
{/* 이동 거리 */}
|
{/* 이동 통계 */}
|
||||||
<motion.section
|
<motion.section
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
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">
|
<h2 className="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
||||||
<LocateFixed className="text-blue-400" />
|
<LocateFixed className="text-blue-400" />
|
||||||
이동 거리
|
이동 통계
|
||||||
</h2>
|
</h2>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||||
<div className="glow-card rounded-xl p-4 flex flex-col items-center justify-center">
|
<StatCard
|
||||||
<p className="text-gray-400 text-sm mb-1">걸은 거리</p>
|
icon={Footprints}
|
||||||
<p className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-2xl'}`}>
|
label="걸은 거리"
|
||||||
{isMobile ? formatDistance(stats.general.distanceWalked) : `${stats.general.distanceWalked.toLocaleString()}m`}
|
value={formatDistance(stats.general.distanceWalked)}
|
||||||
</p>
|
color="text-green-400"
|
||||||
</div>
|
/>
|
||||||
<div className="glow-card rounded-xl p-4 flex flex-col items-center justify-center">
|
<StatCard
|
||||||
<p className="text-gray-400 text-sm mb-1">비행 거리</p>
|
icon={Plane}
|
||||||
<p className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-2xl'}`}>
|
label="비행 거리"
|
||||||
{isMobile ? formatDistance(stats.general.distanceFlown) : `${stats.general.distanceFlown.toLocaleString()}m`}
|
value={formatDistance(stats.general.distanceFlown)}
|
||||||
</p>
|
color="text-purple-400"
|
||||||
</div>
|
/>
|
||||||
<div className="glow-card rounded-xl p-4 flex flex-col items-center justify-center">
|
<StatCard
|
||||||
<p className="text-gray-400 text-sm mb-1">수영 거리</p>
|
icon={Waves}
|
||||||
<p className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-2xl'}`}>
|
label="수영 거리"
|
||||||
{isMobile ? formatDistance(stats.general.distanceSwum) : `${stats.general.distanceSwum.toLocaleString()}m`}
|
value={formatDistance(stats.general.distanceSwum)}
|
||||||
</p>
|
color="text-cyan-400"
|
||||||
</div>
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={ChevronsUp}
|
||||||
|
label="점프 횟수"
|
||||||
|
value={stats.general.jumps}
|
||||||
|
color="text-blue-400"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</motion.section>
|
</motion.section>
|
||||||
|
|
||||||
|
|
@ -406,11 +403,9 @@ const ItemStatRow = ({ item, translate, icons }) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<Tooltip content={translate(item.id)}>
|
<p className="text-white text-sm font-medium truncate">
|
||||||
<p className="text-white text-sm font-medium truncate">
|
{translate(item.id)}
|
||||||
{translate(item.id)}
|
</p>
|
||||||
</p>
|
|
||||||
</Tooltip>
|
|
||||||
<div className="flex flex-wrap gap-x-2 text-xs text-gray-400">
|
<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.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>}
|
{item.used > 0 && <span>사용 <span className="text-blue-400">{item.used}</span></span>}
|
||||||
|
|
@ -461,11 +456,9 @@ const MobStatRow = ({ mob, translate, icons }) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<Tooltip content={translate(mob.id)}>
|
<p className="text-white text-sm font-medium truncate">
|
||||||
<p className="text-white text-sm font-medium truncate">
|
{translate(mob.id)}
|
||||||
{translate(mob.id)}
|
</p>
|
||||||
</p>
|
|
||||||
</Tooltip>
|
|
||||||
<div className="flex flex-wrap gap-x-2 text-xs text-gray-400">
|
<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.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>}
|
{mob.killedBy > 0 && <span>죽음 <span className="text-gray-300">{mob.killedBy}</span></span>}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue