diff --git a/apps/client/src/scenes/lobby/LobbyScene.tsx b/apps/client/src/scenes/lobby/LobbyScene.tsx index f46abfe..759e6d1 100644 --- a/apps/client/src/scenes/lobby/LobbyScene.tsx +++ b/apps/client/src/scenes/lobby/LobbyScene.tsx @@ -2,11 +2,18 @@ import { domain } from "@repo/shared"; import type { FieldSizePreset, StartGameRequestPayload, TeamAssignmentMode } from "@repo/shared"; import { config } from "@client/config"; + +/** ホスト側で管理するゲーム設定 */ +export type LobbyGameSettings = { + targetPlayerCount: number; + fieldSizePreset: FieldSizePreset; + teamAssignmentMode: TeamAssignmentMode; +}; import { socketManager } from "@client/network/SocketManager"; import { OVERLAY_BUTTON_STYLE } from "@client/scenes/shared/styles/overlayStyles"; import { GearIcon } from "./components/GearIcon"; import { LobbyRuleModal } from "./components/LobbyRuleModal"; -import { LobbySettingsModal } from "./components/LobbySettingsModal"; +import { LobbySettingsModal, toFieldPresetLabel } from "./components/LobbySettingsModal"; import { LobbyStartConfirmModal } from "./components/LobbyStartConfirmModal"; import { LOBBY_BACK_BUTTON_STYLE, @@ -79,33 +86,22 @@ return options; }, [minimumStartPlayerCount, maxStartPlayerCount]); - const [selectedStartPlayerCount, setSelectedStartPlayerCount] = useState( - minimumStartPlayerCount, - ); - const fieldPresetOptions = useMemo(() => { - return Object.keys( - config.GAME_CONFIG.FIELD_PRESETS, - ) as FieldSizePreset[]; - }, []); - const [selectedFieldSizePreset, setSelectedFieldSizePreset] = - useState(config.GAME_CONFIG.DEFAULT_FIELD_PRESET); - const [selectedTeamAssignmentMode, setSelectedTeamAssignmentMode] = - useState("random"); + const [gameSettings, setGameSettings] = useState({ + targetPlayerCount: minimumStartPlayerCount, + fieldSizePreset: config.GAME_CONFIG.DEFAULT_FIELD_PRESET, + teamAssignmentMode: "random", + }); const [teamFullMessage, setTeamFullMessage] = useState(null); const [isRuleModalOpen, setIsRuleModalOpen] = useState(false); const [isStartConfirmVisible, setIsStartConfirmVisible] = useState(false); const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false); useEffect(() => { - setSelectedStartPlayerCount((prev) => { - if (prev < minimumStartPlayerCount || prev > maxStartPlayerCount) { - return minimumStartPlayerCount; + setGameSettings((prev) => { + const count = prev.targetPlayerCount; + if (count < minimumStartPlayerCount || count > maxStartPlayerCount || count % teamUnit !== 0) { + return { ...prev, targetPlayerCount: minimumStartPlayerCount }; } - - if (prev % teamUnit !== 0) { - return minimumStartPlayerCount; - } - return prev; }); }, [minimumStartPlayerCount, maxStartPlayerCount]); @@ -117,11 +113,11 @@ } socketManager.lobby.updateLobbySettings({ - targetPlayerCount: selectedStartPlayerCount, - fieldSizePreset: selectedFieldSizePreset, - teamAssignmentMode: selectedTeamAssignmentMode, + targetPlayerCount: gameSettings.targetPlayerCount, + fieldSizePreset: gameSettings.fieldSizePreset, + teamAssignmentMode: gameSettings.teamAssignmentMode, }); - }, [isMeOwner, selectedStartPlayerCount, selectedFieldSizePreset, selectedTeamAssignmentMode]); + }, [isMeOwner, gameSettings.targetPlayerCount, gameSettings.fieldSizePreset, gameSettings.teamAssignmentMode]); const handleStartClick = () => { setIsStartConfirmVisible(true); @@ -130,8 +126,8 @@ const handleStartConfirm = () => { setIsStartConfirmVisible(false); onStart({ - targetPlayerCount: selectedStartPlayerCount, - fieldSizePreset: selectedFieldSizePreset, + targetPlayerCount: gameSettings.targetPlayerCount, + fieldSizePreset: gameSettings.fieldSizePreset, }); }; @@ -152,20 +148,6 @@ socketManager.lobby.selectTeam({ preferredTeamId }); }; - const toFieldPresetLabel = (preset: FieldSizePreset): string => { - const range = config.GAME_CONFIG.FIELD_PRESETS[preset].recommendedPlayers; - const baseLabel = - preset === "SMALL" - ? "小" - : preset === "MEDIUM" - ? "中" - : preset === "LARGE" - ? "大" - : "極大"; - - return `${baseLabel} (${range.min}-${range.max}人目安)`; - }; - // 自分のチーム選択状態を取得する const myPreferredTeamId = room.players.find((p) => p.id === myId)?.preferredTeamId ?? null; @@ -357,14 +339,8 @@ {isSettingsModalOpen && ( { setIsSettingsModalOpen(false); }} /> )} diff --git a/apps/client/src/scenes/lobby/components/LobbySettingsModal.tsx b/apps/client/src/scenes/lobby/components/LobbySettingsModal.tsx index 8e63589..5fd2bcb 100644 --- a/apps/client/src/scenes/lobby/components/LobbySettingsModal.tsx +++ b/apps/client/src/scenes/lobby/components/LobbySettingsModal.tsx @@ -3,8 +3,9 @@ * ホスト用のゲーム設定(人数・フィールドサイズ・チーム割り当て方式)を変更するモーダル */ import type { FieldSizePreset } from "@repo/shared"; -import type { TeamAssignmentMode } from "@repo/shared"; +import { config } from "@client/config"; import { OVERLAY_BUTTON_STYLE } from "@client/scenes/shared/styles/overlayStyles"; +import type { LobbyGameSettings } from "../LobbyScene"; import { LOBBY_SETTINGS_MODAL_BODY_STYLE, LOBBY_SETTINGS_MODAL_FIELD_STYLE, @@ -18,28 +19,31 @@ type LobbySettingsModalProps = { startPlayerCountOptions: number[]; - selectedStartPlayerCount: number; - onChangeStartPlayerCount: (count: number) => void; - fieldPresetOptions: FieldSizePreset[]; - selectedFieldSizePreset: FieldSizePreset; - onChangeFieldSizePreset: (preset: FieldSizePreset) => void; - toFieldPresetLabel: (preset: FieldSizePreset) => string; - selectedTeamAssignmentMode: TeamAssignmentMode; - onChangeTeamAssignmentMode: (mode: TeamAssignmentMode) => void; + settings: LobbyGameSettings; + onChangeSettings: (settings: LobbyGameSettings) => void; onClose: () => void; }; +const FIELD_PRESET_OPTIONS = Object.keys(config.GAME_CONFIG.FIELD_PRESETS) as FieldSizePreset[]; + +export const toFieldPresetLabel = (preset: FieldSizePreset): string => { + const range = config.GAME_CONFIG.FIELD_PRESETS[preset].recommendedPlayers; + const baseLabel = + preset === "SMALL" + ? "小" + : preset === "MEDIUM" + ? "中" + : preset === "LARGE" + ? "大" + : "極大"; + return `${baseLabel} (${range.min}-${range.max}人目安)`; +}; + /** ホスト用ゲーム設定ポップアップ */ export const LobbySettingsModal = ({ startPlayerCountOptions, - selectedStartPlayerCount, - onChangeStartPlayerCount, - fieldPresetOptions, - selectedFieldSizePreset, - onChangeFieldSizePreset, - toFieldPresetLabel, - selectedTeamAssignmentMode, - onChangeTeamAssignmentMode, + settings, + onChangeSettings, onClose, }: LobbySettingsModalProps) => { return ( @@ -57,9 +61,9 @@ { - onChangeFieldSizePreset(event.target.value as FieldSizePreset); + onChangeSettings({ ...settings, fieldSizePreset: event.target.value as FieldSizePreset }); }} style={LOBBY_SETTINGS_MODAL_SELECT_STYLE} > - {fieldPresetOptions.map((preset) => ( + {FIELD_PRESET_OPTIONS.map((preset) => ( @@ -103,9 +107,12 @@