Feat: User Relationships and Session Members.

This commit is contained in:
2026-02-28 19:53:50 +00:00
parent c7db290aaf
commit e8e9a02e7b
73 changed files with 3818 additions and 571 deletions

View File

@@ -417,6 +417,12 @@ class API {
}
// MTG Game API methods
static async getIsGameDataOutdated(game) {
const url = `/mtg/api/game/${game[attrGameId]}/is-outdated`;
let dataRequest = {};
dataRequest[flagGame] = game;
return await API.request(url, 'POST', dataRequest);
}
static async saveGame(game, formFilters, comment) {
let dataRequest = {};
dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);
@@ -1616,6 +1622,7 @@ class PageMtgDecks extends TableBasePage {
class PageMtgGame extends TableBasePage {
static hash = hashPageMtgGame;
static attrIdRowObject = attrGameId;
@@ -1630,6 +1637,9 @@ class PageMtgGame extends TableBasePage {
hookupFilters() {
// this.sharedHookupFilters();
}
callFilterTableContent() {
window.location.reload();
}
loadRowTable(rowJson) {
return;
}
@@ -1667,6 +1677,8 @@ class PageMtgGame extends TableBasePage {
this.hookupPlayerLifeIncrementButtons();
this.hookupCommanderDamageIncrementButtons();
*/
PageMtgGame.hookupOverlayGameOutdated();
PageMtgGame.hookupGameUpdateCheck();
}
static hookupResetButton() {
const resetGameButton = document.querySelector('header.game-header .header-right .btn-tcg.btn-tcg-secondary');
@@ -1722,7 +1734,55 @@ class PageMtgGame extends TableBasePage {
}
}
*/
static hookupGameUpdateCheck() {
const intervalId = setInterval(async () => {
const isGameDataOutdated = await PageMtgGame.checkLastGameUpdate();
if (isGameDataOutdated) {
clearInterval(intervalId);
}
}, 30000);
}
static async checkLastGameUpdate() {
try {
// Fetch players, rounds, and damage records from API
const isGameDataOutdatedResponse = await API.getIsGameDataOutdated(game);
const isGameDataOutdated = isGameDataOutdatedResponse[flagData];
console.log({
isGameDataOutdatedResponse,
isGameDataOutdated
});
if (isGameDataOutdated) {
// const gameDataOutdatedLabel = document.querySelector(gameDataOutdatedLabelId);
// gameDataOutdatedLabel.classList.remove(flagIsCollapsed);
const pageTitleElement = document.querySelector('.topnav .tcg-title');
pageTitleElement.classList.add(flagDirty);
PageMtgGame.showOverlayGameOutdated();
}
return isGameDataOutdated;
} catch (error) {
console.error('Error checking for game update from server:', error);
}
}
static hookupOverlayGameOutdated() {
Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagCancel, flagInitialised, buttonCancel => {
buttonCancel.addEventListener('click', () => {
let overlay = document.querySelector(idOverlayGameOutdated);
overlay.style.visibility = 'hidden';
});
});
Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagSubmit, flagInitialised, buttonConfirm => {
buttonConfirm.addEventListener('click', () => {
let overlay = document.querySelector(idOverlayGameOutdated);
overlay.style.visibility = 'hidden';
window.location.reload();
});
});
}
static showOverlayGameOutdated() {
let overlay = document.querySelector(idOverlayGameOutdated);
overlay.classList.remove(flagIsCollapsed);
overlay.style.visibility = 'visible';
}
async loadGameFromServer() {
console.log("loading game from server");
try {
@@ -1805,7 +1865,7 @@ class PageMtgGame extends TableBasePage {
maxCommanderDamageReceived = Math.max(maxCommanderDamageReceived, damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId && damage[attrReceivedFromCommanderPlayerId] != null && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss]).reduce((a, b) => a + b, 0));
});
const totalDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss] - damage[flagLifeGain]).reduce((a, b) => a + b, 0);
let life = startingLife - totalDamage;
let life = game[flagStartingLife] - totalDamage;
let isEliminatedByForce = damageRecords.filter(damage => damage[attrPlayerId] == playerId && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagIsEliminated]).some(Boolean);
console.log("renderPlayers");
console.log({
@@ -1887,7 +1947,6 @@ class PageMtgGame extends TableBasePage {
if (damage[flagActive] && (damage[flagCommanderDeaths] > 0 || damage[flagLifeGain] != 0 || damage[flagLifeLoss] != 0 || damage[flagIsEliminated])
// && rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder
&& previousRoundIds.includes(damage[attrRoundId])) {
debugger;
let round = rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0];
let player = players.filter(p => p[attrPlayerId] == damage[attrPlayerId])[0];
let receivedFromPlayer = damage[attrReceivedFromCommanderPlayerId] == null ? {
@@ -2020,7 +2079,6 @@ class PageMtgGame extends TableBasePage {
// Life gain buttons
let lifeGainButtonSelector = '.life-gain-btn';
Events.hookupEventHandler("click", lifeGainButtonSelector, (event, button) => {
debugger;
const playerId = parseInt(button.dataset.playerId);
const amount = parseInt(button.dataset.amount);
const activeRoundId = PageMtgGame.getActiveRoundId();
@@ -2120,7 +2178,7 @@ class PageMtgGame extends TableBasePage {
damageRecords[damageIndex][flagLifeLoss] += amount;
let isLifeGainNotLoss = false;
this.changeLife(playerId // playerId
, -amount // amount
, amount // amount
, isLifeGainNotLoss // isLifeGainNotLoss
, false // updateDamage
, damageIndex // damageIndex
@@ -2228,7 +2286,7 @@ class PageMtgGame extends TableBasePage {
maxDamageFromOtherCommander,
totalDamageTaken
});
return hasDamageWithIsEliminated || maxDamageFromOtherCommander >= 21 || totalDamageTaken >= startingLife;
return hasDamageWithIsEliminated || maxDamageFromOtherCommander >= 21 || totalDamageTaken >= game[flagStartingLife];
}
static updatePlayerSetup() {
const playerCountInput = document.getElementById('playerCount');
@@ -2384,6 +2442,19 @@ class PageMtgGame extends TableBasePage {
alert(message);
}
}
updateAndToggleShowButtonsSaveCancel() {
// let pageBody = document.querySelector(idPageBody);
let isDirty = DOM.hasDirtyChildrenContainer(pageBody);
let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;
let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);
let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);
console.log({
pageBody,
isDirty,
areVisibleSaveCancelButtons
});
this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);
}
leave() {
super.leave();
}