diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts
index 8233cd584..897271db9 100644
--- a/src/client/HostLobbyModal.ts
+++ b/src/client/HostLobbyModal.ts
@@ -3,12 +3,15 @@ import { customElement, property, state } from "lit/decorators.js";
import { Difficulty, GameMapType, GameType } from "../core/game/Game";
import { Lobby } from "../core/Schemas";
import { consolex } from "../core/Consolex";
+import "./components/Difficulties";
+import { DifficultyDescription } from "./components/Difficulties";
+import "./components/Maps";
@customElement("host-lobby-modal")
export class HostLobbyModal extends LitElement {
@state() private isModalOpen = false;
@state() private selectedMap: GameMapType = GameMapType.World;
- @state() private selectedDiffculty: Difficulty = Difficulty.Medium;
+ @state() private selectedDifficulty: Difficulty = Difficulty.Medium;
@state() private lobbyId = "";
@state() private copySuccess = false;
@state() private players: string[] = [];
@@ -25,16 +28,57 @@ export class HostLobbyModal extends LitElement {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
+ overflow-y: auto;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
.modal-content {
- background-color: white;
- margin: 15% auto;
+ background-color: rgb(35 35 35 / 0.8);
+ -webkit-backdrop-filter: blur(12px);
+ backdrop-filter: blur(12px);
+ color: white;
padding: 20px;
border-radius: 8px;
width: 80%;
- max-width: 500px;
+ max-width: 1280px;
+ max-height: 80vh;
+ overflow-y: auto;
text-align: center;
+ box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ backdrop-filter: blur(8px);
+ position: relative;
+ }
+
+ /* Add custom scrollbar styles */
+ .modal-content::-webkit-scrollbar {
+ width: 8px;
+ }
+
+ .modal-content::-webkit-scrollbar-track {
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ }
+
+ .modal-content::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 4px;
+ }
+
+ .modal-content::-webkit-scrollbar-thumb:hover {
+ background: rgba(255, 255, 255, 0.3);
+ }
+
+ .title {
+ font-size: 28px;
+ color: #fff;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 0 0 20px;
}
.close {
@@ -47,55 +91,183 @@ export class HostLobbyModal extends LitElement {
.close:hover,
.close:focus {
- color: black;
+ color: white;
text-decoration: none;
cursor: pointer;
}
- button {
- padding: 10px 20px;
+ .start-game-button {
+ width: 100%;
+ max-width: 300px;
+ padding: 15px 20px;
font-size: 16px;
cursor: pointer;
background-color: #007bff;
color: white;
border: none;
- border-radius: 4px;
+ border-radius: 8px;
transition: background-color 0.3s;
display: inline-block;
- margin-top: 20px;
+ margin: 0 0 20px 0;
}
- button:hover {
+ .start-game-button:not(:disabled):hover {
background-color: #0056b3;
}
- select {
- padding: 8px;
- font-size: 16px;
- margin-top: 10px;
- width: 200px;
+ .start-game-button:disabled {
+ background: linear-gradient(to right, #4a4a4a, #3d3d3d);
+ opacity: 0.7;
+ cursor: not-allowed;
}
- .lobby-id-container {
+ .options-layout {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 24px;
+ margin: 24px 0;
+ }
+
+ .options-section {
+ background: rgba(0, 0, 0, 0.2);
+ padding: 12px 24px 24px 24px;
+ border-radius: 12px;
+ }
+
+ .option-title {
+ margin: 0 0 16px 0;
+ font-size: 20px;
+ color: #fff;
+ text-align: center;
+ }
+
+ .option-cards {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 16px;
+ }
+
+ .option-card {
+ width: 100%;
+ min-width: 100px;
+ max-width: 120px;
+ padding: 4px 4px 0 4px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-between;
+ background: rgba(30, 30, 30, 0.95);
+ border: 2px solid rgba(255, 255, 255, 0.1);
+ border-radius: 12px;
+ cursor: pointer;
+ transition: all 0.2s ease-in-out;
+ }
+
+ .option-card:hover {
+ transform: translateY(-2px);
+ border-color: rgba(255, 255, 255, 0.3);
+ background: rgba(40, 40, 40, 0.95);
+ }
+
+ .option-card.selected {
+ border-color: #4a9eff;
+ background: rgba(74, 158, 255, 0.1);
+ }
+
+ .option-card-title {
+ font-size: 14px;
+ color: #aaa;
+ text-align: center;
+ margin: 0 0 4px 0;
+ }
+
+ .option-image {
+ width: 100%;
+ aspect-ratio: 4/2;
+ color: #aaa;
+ transition: transform 0.2s ease-in-out;
+ border-radius: 8px;
+ background-color: rgba(255, 255, 255, 0.1);
+ font-size: 14px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ /* HostLobbyModal css */
+ .clipboard-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ }
+
+ .copy-success {
+ position: relative;
+ transform: translateY(-10px);
+ color: green;
+ font-size: 14px;
+ margin-top: 5px;
+ }
+
+ .copy-success-icon {
+ width: 18px;
+ height: 18px;
+ color: #4caf50;
+ }
+
+ .lobby-id-box {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
+ margin: 8px 0px 0px 0px;
}
- .clipboard-icon {
+ .lobby-id-button {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ background: rgba(0, 0, 0, 0.2);
+ padding: 8px 16px;
+ border-radius: 6px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
cursor: pointer;
- transition: opacity 0.3s;
+ transition: all 0.2s ease-in-out;
}
- .clipboard-icon:hover {
- opacity: 0.7;
+ .lobby-id-button:hover {
+ background: rgba(0, 0, 0, 0.3);
+ border-color: rgba(255, 255, 255, 0.2);
+ transform: translateY(-1px);
}
- .copy-success {
- color: green;
+ .lobby-id {
font-size: 14px;
- margin-top: 5px;
+ color: #fff;
+ text-align: center;
+ }
+
+ .players-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+ padding: 0 16px;
+ }
+
+ .player-tag {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: rgba(255, 255, 255, 0.1);
+ padding: 4px 16px;
+ border-radius: 16px;
+ font-size: 14px;
+ color: #fff;
+ border: 1px solid rgba(255, 255, 255, 0.2);
}
`;
@@ -103,73 +275,109 @@ export class HostLobbyModal extends LitElement {
return html`
×
-
Private Lobby
-
-
Lobby ID: ${this.lobbyId}
-
+
- ${this.copySuccess
- ? html`
Copied to clipboard!
`
- : ""}
-
-
-
+
+
+
+
+
Map
+
+ ${Object.entries(GameMapType)
+ .filter(([key]) => isNaN(Number(key)))
+ .map(
+ ([key, value]) => html`
+
this.handleMapSelection(value)}>
+
+
+ `
+ )}
+
+
+
+
+
+
Difficulty
+
+ ${Object.entries(Difficulty)
+ .filter(([key]) => isNaN(Number(key)))
+ .map(
+ ([key, value]) => html`
+
this.handleDifficultySelection(value)}
+ >
+
+
+ ${DifficultyDescription[key]}
+
+
+ `
+ )}
+
+
+
+
+
+
+ ${this.players.length}
+ ${this.players.length === 1 ? "Player" : "Players"}
+
+
+
+ ${this.players.map(
+ (player) => html`${player}`
)}
-
-
-
-
-
-
-
-
-
Players: ${this.players.join(", ")}
-
+
+
+
`;
@@ -190,11 +398,11 @@ export class HostLobbyModal extends LitElement {
id: this.lobbyId,
},
map: this.selectedMap,
- difficulty: this.selectedDiffculty,
+ difficulty: this.selectedDifficulty,
},
bubbles: true,
composed: true,
- }),
+ })
);
});
this.isModalOpen = true;
@@ -210,19 +418,12 @@ export class HostLobbyModal extends LitElement {
}
}
- private async handleMapChange(e: Event) {
- this.selectedMap = String(
- (e.target as HTMLSelectElement).value,
- ) as GameMapType;
- consolex.log(`updating map to ${this.selectedMap}`);
+ private async handleMapSelection(value: GameMapType) {
+ this.selectedMap = value;
this.putGameConfig();
}
-
- private async handleDifficultyChange(e: Event) {
- this.selectedDiffculty = String(
- (e.target as HTMLSelectElement).value,
- ) as Difficulty;
- consolex.log(`updating difficulty to ${this.selectedDiffculty}`);
+ private async handleDifficultySelection(value: Difficulty) {
+ this.selectedDifficulty = value;
this.putGameConfig();
}
@@ -234,14 +435,14 @@ export class HostLobbyModal extends LitElement {
},
body: JSON.stringify({
gameMap: this.selectedMap,
- difficulty: this.selectedDiffculty,
+ difficulty: this.selectedDifficulty,
}),
});
}
private async startGame() {
consolex.log(
- `Starting private game with map: ${GameMapType[this.selectedMap]}`,
+ `Starting private game with map: ${GameMapType[this.selectedMap]}`
);
this.close();
const response = await fetch(`/start_private_lobby/${this.lobbyId}`, {
diff --git a/src/client/JoinPrivateLobbyModal.ts b/src/client/JoinPrivateLobbyModal.ts
index dede85d4e..09cfc6833 100644
--- a/src/client/JoinPrivateLobbyModal.ts
+++ b/src/client/JoinPrivateLobbyModal.ts
@@ -20,16 +20,58 @@ export class JoinPrivateLobbyModal extends LitElement {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
+ overflow-y: auto;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
.modal-content {
- background-color: white;
- margin: 15% auto;
+ background-color: rgb(35 35 35 / 0.8);
+ -webkit-backdrop-filter: blur(12px);
+ backdrop-filter: blur(12px);
+ color: white;
padding: 20px;
border-radius: 8px;
width: 80%;
max-width: 500px;
+ max-height: 80vh;
+ overflow-y: auto;
text-align: center;
+ box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ backdrop-filter: blur(8px);
+ position: relative;
}
+
+ /* Add custom scrollbar styles */
+ .modal-content::-webkit-scrollbar {
+ width: 8px;
+ }
+
+ .modal-content::-webkit-scrollbar-track {
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ }
+
+ .modal-content::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 4px;
+ }
+
+ .modal-content::-webkit-scrollbar-thumb:hover {
+ background: rgba(255, 255, 255, 0.3);
+ }
+
+ .title {
+ font-size: 28px;
+ color: #fff;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 0 0 20px;
+ }
+
.close {
color: #aaa;
float: right;
@@ -37,47 +79,41 @@ export class JoinPrivateLobbyModal extends LitElement {
font-weight: bold;
cursor: pointer;
}
+
.close:hover,
.close:focus {
- color: black;
+ color: white;
text-decoration: none;
cursor: pointer;
}
- button {
- padding: 10px 20px;
+
+ .start-game-button {
+ width: 100%;
+ max-width: 300px;
+ padding: 15px 20px;
font-size: 16px;
cursor: pointer;
background-color: #007bff;
color: white;
border: none;
- border-radius: 4px;
+ border-radius: 8px;
transition: background-color 0.3s;
+ display: inline-block;
+ margin: 0 0 20px 0;
}
- button:hover {
+
+ .start-game-button:not(:disabled):hover {
background-color: #0056b3;
}
- .lobby-id-container {
- display: flex;
- align-items: stretch;
- justify-content: center;
- gap: 10px;
- margin: 20px 0;
- }
- .lobby-id-container input {
- flex-grow: 1;
- max-width: 200px;
- padding: 10px;
- font-size: 16px;
- border: 1px solid #ccc;
- border-radius: 4px;
- }
- .lobby-id-container button {
- padding: 10px 15px;
- }
- .join-button {
- margin-top: 10px;
+
+ .start-game-button:disabled {
+ background: linear-gradient(to right, #4a4a4a, #3d3d3d);
+ opacity: 0.7;
+ cursor: not-allowed;
}
+ /* JoinPrivateLobbyModal css */
+
.message-area {
margin-top: 10px;
padding: 10px;
@@ -104,26 +140,84 @@ export class JoinPrivateLobbyModal extends LitElement {
background-color: #e8f5e9;
color: #2e7d32;
}
+
+ .lobby-id-box {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+ margin: 40px 0px 0px 0px;
+ }
+ .lobby-id-box input {
+ flex-grow: 1;
+ max-width: 200px;
+ padding: 10px;
+ font-size: 16px;
+ border: 1px solid #ccc;
+ border-radius: 8px;
+ }
+
+ .lobby-id-paste-button {
+ display: flex;
+ align-items: center;
+ background: rgba(0, 0, 0, 0.2);
+ padding: 10px 16px;
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ cursor: pointer;
+ transition: all 0.2s ease-in-out;
+ }
+
+ .lobby-id-paste-button:hover {
+ background: rgba(0, 0, 0, 0.3);
+ border-color: rgba(255, 255, 255, 0.2);
+ transform: translateY(-1px);
+ }
+
+ .lobby-id-paste-button-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ }
`;
render() {
return html`
×
-
Join Private Lobby
-
+
Join Private Lobby
+
${this.message}
${!this.hasJoined
- ? html`