diff --git a/apps/client/src/scenes/result/ResultScene.tsx b/apps/client/src/scenes/result/ResultScene.tsx index 71772ce..69f90e1 100644 --- a/apps/client/src/scenes/result/ResultScene.tsx +++ b/apps/client/src/scenes/result/ResultScene.tsx @@ -8,6 +8,7 @@ import { config } from "../../config"; import { ResultActionBar } from "./components/ResultActionBar"; import { ResultBackground } from "./components/ResultBackground"; +import { ResultPlayerStatsTable } from "./components/ResultPlayerStatsTable"; import { ResultRankingTable } from "./components/ResultRankingTable"; import { RESULT_BACKGROUND_DARK_OVERLAY_STYLE, @@ -100,6 +101,10 @@ formatPaintRate={formatPaintRate} /> )} + + {isRankingVisible && result.playerStats && result.playerStats.length > 0 && ( + + )} ); diff --git a/apps/client/src/scenes/result/components/ResultPlayerStatsTable.tsx b/apps/client/src/scenes/result/components/ResultPlayerStatsTable.tsx new file mode 100644 index 0000000..4ef41c3 --- /dev/null +++ b/apps/client/src/scenes/result/components/ResultPlayerStatsTable.tsx @@ -0,0 +1,64 @@ +/** + * ResultPlayerStatsTable + * リザルト画面のプレイヤー個人スタッツ表を表示する + * 各プレイヤーの塗り回数と爆弾ヒット回数の一覧描画を担当する + */ +import type { PlayerGameStats } from "@repo/shared"; +import { config } from "@client/config"; +import { + RESULT_PLAYER_STATS_HEADER_ROW_STYLE, + RESULT_PLAYER_STATS_SCROLL_BODY_STYLE, + RESULT_TABLE_STYLE, + RESULT_RIGHT_ALIGN_STYLE, + RESULT_TEAM_CELL_STYLE, + getResultPlayerStatsBodyRowStyle, + getResultTeamColorDotStyle, + RESULT_PLAYER_STATS_SECTION_TITLE_STYLE, + RESULT_PLAYER_STATS_VALUE_STYLE, +} from "../styles/resultStyles"; + +type Props = { + playerStats: PlayerGameStats[]; +}; + +/** プレイヤー個人スタッツ表を描画するコンポーネント */ +export const ResultPlayerStatsTable = ({ playerStats }: Props) => { + const sorted = [...playerStats].sort((a, b) => b.paintCount - a.paintCount); + + return ( + <> +

個人スタッツ

+
+
+ プレイヤー + 塗り回数 + ヒット数 +
+ +
+ {sorted.map((player, index) => ( +
+ + + {player.playerName} + + + {player.paintCount.toLocaleString()} + + + {player.bombHitCount} + +
+ ))} +
+
+ + ); +}; diff --git a/apps/client/src/scenes/result/styles/resultStyles.ts b/apps/client/src/scenes/result/styles/resultStyles.ts index 8df9dad..7e8d8b8 100644 --- a/apps/client/src/scenes/result/styles/resultStyles.ts +++ b/apps/client/src/scenes/result/styles/resultStyles.ts @@ -209,6 +209,49 @@ background: index % 2 === 0 ? "#171717" : "#1d1d1d", }); +/** プレイヤースタッツ表のグリッド列定義 */ +export const RESULT_PLAYER_STATS_ROW_GRID_TEMPLATE = "1fr 120px 120px"; + +/** プレイヤースタッツセクションタイトルのスタイル */ +export const RESULT_PLAYER_STATS_SECTION_TITLE_STYLE: CSSProperties = { + margin: "24px 0 10px 0", + fontSize: "clamp(1rem, 2.6vw, 1.3rem)", + fontWeight: 700, + letterSpacing: "0.08em", + color: "rgba(255, 255, 255, 0.88)", + textShadow: "0 2px 8px rgba(0, 0, 0, 0.4)", +}; + +/** プレイヤースタッツ表ヘッダー行のスタイル */ +export const RESULT_PLAYER_STATS_HEADER_ROW_STYLE: CSSProperties = { + display: "grid", + gridTemplateColumns: RESULT_PLAYER_STATS_ROW_GRID_TEMPLATE, + background: "#222", + padding: "12px 16px", + fontWeight: "bold", +}; + +/** プレイヤースタッツ表本文スクロール領域のスタイル */ +export const RESULT_PLAYER_STATS_SCROLL_BODY_STYLE: CSSProperties = { + maxHeight: "min(36dvh, 320px)", + overflowY: "auto", +}; + +/** プレイヤースタッツ数値セルのスタイル */ +export const RESULT_PLAYER_STATS_VALUE_STYLE: CSSProperties = { + textAlign: "right", + fontVariantNumeric: "tabular-nums", +}; + +/** プレイヤースタッツ表本文行のスタイルを返す */ +export const getResultPlayerStatsBodyRowStyle = (index: number): CSSProperties => ({ + display: "grid", + gridTemplateColumns: RESULT_PLAYER_STATS_ROW_GRID_TEMPLATE, + padding: "12px 16px", + borderTop: "1px solid #333", + background: index % 2 === 0 ? "#171717" : "#1d1d1d", +}); + /** 紙吹雪1片のスタイルを返す */ export const getResultConfettiStyle = ( index: number,