feat(ui): Modals vue

Readded modals with vue syntax. Removed not working alert component. Cleaned up.
This commit is contained in:
LQ63
2025-12-04 02:26:02 +01:00
parent ecb9d91991
commit 2bd5feaaab
2 changed files with 63 additions and 157 deletions

View File

@@ -1,54 +1,4 @@
var canPlayCard = false;
var isInitialized = false;
const AlertsComponent = {
template: `
<div class="fixed-top d-flex flex-column align-items-center mt-3" style="z-index: 1050; pointer-events: none;">
<div v-for="alert in alerts" :key="alert.id" class="alert-item">
<div
class="alert alert-primary d-flex align-items-center p-2 mb-2 w-auto shadow-sm"
role="alert"
style="width: 25rem; pointer-events: all;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="bi flex-shrink-0 me-2" viewBox="0 0 16 16" role="img" aria-label="Warning:">
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
</svg>
<div class="small">
<small>{{ alert.message }}</small>
</div>
</div>
</div>
</div>
`,
data() {
return {
alerts: []
};
},
methods: {
alertMessage(message) {
const alertData = {
id: Date.now(),
message: message,
isVisible: true,
};
this.alerts.push(alertData);
setTimeout(() => {
this.removeAlert(alertData.id);
}, 5000);
},
removeAlert(id) {
const index = this.alerts.findIndex(alert => alert.id === id);
if (index !== -1) {
this.alerts.splice(index, 1);
}
}
}
};
const PlayerHandComponent = {
data() {
return {
@@ -230,11 +180,7 @@ const ScoreBoardComponent = {
this.playerScores = this.calculateNewScores(playersin, tricklist);
if (typeof globalThis.alertMessage === 'function') {
globalThis.alertMessage(`${playerwon} won the trick!`);
} else {
console.error("ALERT MESSAGE FAILED: globalThis.alertMessage is NOT a function.");
}
}
}
};
@@ -370,13 +316,23 @@ const LobbyComponent = {
isHost: false,
maxPlayers: 0,
players: [],
showKickedModal: false,
kickedEventData: null,
showSessionClosedModal: false,
sessionClosedEventData: null,
};
},
template: `
<main class="lobby-background vh-100" id="lobbybackground">
<div class="modal fade" data-backdrop="static" data-keyboard="false" data-focus="true" id="kickedModal" tabindex="-1" role="dialog" aria-labelledby="kickedModalTitle">
<div v-if="showKickedModal" class="modal fade show d-block"
tabindex="-1"
role="dialog"
aria-labelledby="kickedModalTitle"
aria-modal="true"
style="background-color: rgba(0,0,0,0.5);">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
@@ -384,12 +340,19 @@ const LobbyComponent = {
</div>
<div class="modal-body">
<p>You've been kicked from the lobby.</p>
<p class="text-muted small">You'll get redirected to the mainmenu in 5 seconds...</p>
</div>
</div>
</div>
</div>
<div class="modal fade" data-backdrop="static" data-keyboard="false" data-focus="true" id="sessionClosed" tabindex="-1" role="dialog" aria-labelledby="sessionClosedModalTitle">
<div v-if="showSessionClosedModal" class="modal fade show d-block"
tabindex="-1"
role="dialog"
aria-labelledby="sessionClosedModalTitle"
aria-modal="true"
style="background-color: rgba(0,0,0,0.5);">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
@@ -397,6 +360,7 @@ const LobbyComponent = {
</div>
<div class="modal-body">
<p>The session was closed.</p>
<p class="text-muted small">You'll get redirected to the mainmenu in 5 seconds...</p>
</div>
</div>
</div>
@@ -499,18 +463,40 @@ const LobbyComponent = {
},
handleKickPlayer(playerId) {
globalThis.handleKickPlayer(playerId)
},
showKickModal(eventData) {
this.showKickedModal = true;
setTimeout(() => {
this.kickedEventData = eventData;
this.showKickedModal = false;
if (typeof globalThis.receiveGameStateChange === 'function') {
globalThis.receiveGameStateChange(this.kickedEventData);
} else {
console.error("FATAL: receiveGameStateChange ist nicht global definiert.");
}
}, 5000);
},
showSessionClosedModal(eventData) {
this.sessionClosedEventData = eventData;
this.showSessionClosedModal = true;
setTimeout(() => {
this.showSessionClosedModal = false;
if (typeof globalThis.receiveGameStateChange === 'function') {
globalThis.receiveGameStateChange(this.sessionClosedEventData);
} else {
console.error("FATAL: receiveGameStateChange ist nicht global definiert.");
}
}, 5000);
}
}
};
function requestCardEvent(eventData) {
const player = eventData.player;
const handElement = $('#card-slide')
handElement.removeClass('inactive');
canPlayCard = true;
//TODO: Needs correct implementation of setting the inactive class in the PlayerHandComponent
}
function receiveGameStateChange(eventData) {
const content = eventData.content;
const title = eventData.title || 'Knockout Whist';
@@ -518,77 +504,8 @@ function receiveGameStateChange(eventData) {
exchangeBody(content, title, url);
}
function receiveLobbyUpdateEvent(eventData) {
const host = eventData.host;
const maxPlayers = eventData.maxPlayers;
const players = eventData.players;
const lobbyPlayersContainer = $('#players');
const playerAmountBox = $('#playerAmount');
let newHtml = ''
if (host) {
players.forEach(user => {
const inner = user.self ? `<h5 class="card-title">${user.name} (You)</h5>
<a href="#" class="btn btn-danger disabled" aria-disabled="true" tabindex="-1">Remove</a>`
: ` <h5 class="card-title">${user.name}</h5>
<div class="btn btn-danger" onclick="handleKickPlayer('${user.id}')">Remove</div>`
newHtml += `<div class="col-auto my-auto m-3">
<div class="card" style="width: 18rem;">
<img src="/assets/images/profile.png" alt="Profile" class="card-img-top w-50 mx-auto mt-3" />
<div class="card-body">
${inner}
</div>
</div>
</div>`
})
} else {
players.forEach(user => {
const inner = user.self ? `<h5 class="card-title">${user.name} (You)</h5>` : ` <h5 class="card-title">${user.name}</h5>`
newHtml += `<div class="col-auto my-auto m-3">
<div class="card" style="width: 18rem;">
<img src="/assets/images/profile.png" alt="Profile" class="card-img-top w-50 mx-auto mt-3" />
<div class="card-body">
${inner}
</div>
</div>
</div>`
})
}
lobbyPlayersContainer.html(newHtml);
playerAmountBox.text(`Players: ${players.length} / ${maxPlayers}`);
}
function receiveKickEvent(eventData) {
$('#kickedModal').modal({
backdrop: 'static',
keyboard: false
}).modal('show');
setTimeout(() => {
receiveGameStateChange(eventData)
}, 5000);
}
function receiveSessionClosedEvent(eventData) {
$('#sessionClosed').modal({
backdrop: 'static',
keyboard: false
}).modal('show');
setTimeout(() => {
receiveGameStateChange(eventData)
}, 5000);
}
function receiveRoundEndEvent(eventData) {
const player = eventData.player
const tricks = eventData.tricks
alertMessage(`${player} won this round with ${tricks} tricks!`)
//TODO: When alert is working, set an alert that shows how won the round and with how much tricks.
}
let playerHandApp = null;
let scoreBoardApp = null;
@@ -596,19 +513,7 @@ let gameInfoApp = null;
let trickDisplayApp = null;
let turnApp = null;
globalThis.initGameVueComponents = function() {
// --- 1. CLEANUP (If already initialized) ---
if (playerHandApp) {
console.log("Updating Hand View. Unmounting previous instance.");
playerHandApp.unmount();
globalThis.updatePlayerHand = undefined;
onEvent("ReceivedHandEvent", null);
}
// --- 2. INITIALIZATION/RE-INITIALIZATION ---
// Initializing PlayerHandComponent
const app = Vue.createApp(PlayerHandComponent);
playerHandApp = app;
@@ -622,7 +527,7 @@ globalThis.initGameVueComponents = function() {
console.error("FATAL ERROR: PlayerHandComponent mount failed. Check if #player-hand-container exists.");
}
// --- 3. Initialize Scoreboard ---
// Initializing Scoreboard
if (scoreBoardApp) return
const app2 = Vue.createApp(ScoreBoardComponent)
@@ -638,7 +543,7 @@ globalThis.initGameVueComponents = function() {
} else {
console.error("FATAL ERROR: Scoreboard mount failed. Check if #score-table exists.");
}
// --- 4. Initialize Gameinfo ---
// Initializing Gameinfo
if (gameInfoApp) return
const app3 = Vue.createApp(GameInfoComponent)
@@ -654,7 +559,7 @@ globalThis.initGameVueComponents = function() {
console.error("FATAL ERROR: GameInfo mount failed. Check if #score-table exists.");
}
// -- 5. Initialize TrickCardContainer ---
// Initializing TrickCardContainer
if (trickDisplayApp) return;
const app4 = Vue.createApp(TrickDisplayComponent);
trickDisplayApp = app4;
@@ -669,7 +574,7 @@ globalThis.initGameVueComponents = function() {
console.error("FATAL ERROR: TrickDisplay mount failed. Check if #trick-cards-container exists.");
}
// --- 6. Initialize TurnContainer ---
// Initializing TurnContainer
if (turnApp) return;
const app5 = Vue.createApp(TurnComponent)
turnApp = app5;
@@ -695,6 +600,7 @@ globalThis.initLobbyVueComponents = function(initialLobbyName, initialLobbyId, i
if (mountedLobby) {
mountedLobby.setInitialData(initialLobbyName, initialLobbyId);
//Damit beim erstmaligen Betreten der Lobby die Spieler etc. angezeigt werden.
mountedLobby.updateLobbyData({
host: initialIsHost,
maxPlayers: initialMaxPlayers,
@@ -702,9 +608,11 @@ globalThis.initLobbyVueComponents = function(initialLobbyName, initialLobbyId, i
});
globalThis.updateLobbyData = mountedLobby.updateLobbyData;
globalThis.showKickModal = mountedLobby.showKickModal;
globalThis.showSessionClosedModal = mountedLobby.showSessionClosedModal;
onEvent("LobbyUpdateEvent", globalThis.updateLobbyData);
onEvent("KickEvent", globalThis.showKickModal);
onEvent("SessionClosed", globalThis.showSessionClosedModal);
console.log("LobbyComponent successfully mounted and registered events.");
} else {
console.error("FATAL ERROR: LobbyComponent mount failed.");
@@ -740,8 +648,6 @@ function handleNewRoundEvent(eventData) {
}
onEvent("GameStateChangeEvent", receiveGameStateChange)
onEvent("RequestCardEvent", requestCardEvent)
onEvent("LeftEvent", receiveGameStateChange)
onEvent("KickEvent", receiveKickEvent)
onEvent("SessionClosed", receiveSessionClosedEvent)
onEvent("RequestCardEvent", requestCardEvent)
onEvent("RoundEndEvent", receiveRoundEndEvent)

View File

@@ -1,7 +1,7 @@
/*
function handlePlayCard(cardidx) {
//TODO: Needs implementation
}
*/
function handleSkipDogLife(button) {
// TODO needs implementation
}