import { LitElement, html, css } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { Difficulty, GameMap, GameType } from '../core/game/Game'; import { Lobby } from '../core/Schemas'; import { consolex } from '../core/Consolex'; @customElement('host-lobby-modal') export class HostLobbyModal extends LitElement { @state() private isModalOpen = false; @state() private selectedMap: GameMap = GameMap.World; @state() private selectedDiffculty: Difficulty = Difficulty.Medium; @state() private lobbyId = 'a345d'; @state() private copySuccess = false; static styles = css` .modal-overlay { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); } .modal-content { background-color: white; margin: 15% auto; padding: 20px; border-radius: 8px; width: 80%; max-width: 500px; text-align: center; } .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer; } .close:hover, .close:focus { color: black; text-decoration: none; cursor: pointer; } button { padding: 10px 20px; font-size: 16px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 4px; transition: background-color 0.3s; display: inline-block; margin-top: 20px; } button:hover { background-color: #0056b3; } select { padding: 8px; font-size: 16px; margin-top: 10px; width: 200px; } .lobby-id-container { display: flex; align-items: center; justify-content: center; gap: 10px; } .clipboard-icon { cursor: pointer; transition: opacity 0.3s; } .clipboard-icon:hover { opacity: 0.7; } .copy-success { color: green; font-size: 14px; margin-top: 5px; } `; render() { return html` `; } public open() { createLobby().then((lobby) => { this.lobbyId = lobby.id // join lobby }).then(() => { this.dispatchEvent(new CustomEvent('join-lobby', { detail: { gameType: GameType.Private, lobby: { id: this.lobbyId, }, map: this.selectedMap, difficulty: this.selectedDiffculty, }, bubbles: true, composed: true })); }) this.isModalOpen = true; } public close() { this.isModalOpen = false; this.copySuccess = false; } private async handleMapChange(e: Event) { this.selectedMap = String((e.target as HTMLSelectElement).value) as GameMap; consolex.log(`updating map to ${this.selectedMap}`) this.putGameConfig() } private async handleDifficultyChange(e: Event) { this.selectedDiffculty = String((e.target as HTMLSelectElement).value) as Difficulty; consolex.log(`updating difficulty to ${this.selectedDiffculty}`) this.putGameConfig() } private async putGameConfig() { const response = await fetch(`/private_lobby/${this.lobbyId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ gameMap: this.selectedMap, difficulty: this.selectedDiffculty }) }); } private async startGame() { consolex.log(`Starting private game with map: ${GameMap[this.selectedMap]}`); this.close(); const response = await fetch(`/start_private_lobby/${this.lobbyId}`, { method: 'POST', headers: { 'Content-Type': 'application/json', } }); } private async copyToClipboard() { try { await navigator.clipboard.writeText(this.lobbyId); this.copySuccess = true; setTimeout(() => { this.copySuccess = false; }, 2000); } catch (err) { consolex.error('Failed to copy text: ', err); } } } async function createLobby(): Promise { try { const response = await fetch('/private_lobby', { method: 'POST', headers: { 'Content-Type': 'application/json', }, // body: JSON.stringify(data), // Include this if you need to send data }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); consolex.log('Success:', data); // Assuming the server returns an object with an 'id' property const lobby: Lobby = { id: data.id, // Add other properties as needed }; return lobby; } catch (error) { consolex.error('Error creating lobby:', error); throw error; // Re-throw the error so the caller can handle it } }