fix: prevent multiple P2 actions on same offer and improve UI consistency
- Add server validation to prevent P2 from taking multiple actions on the same offer - Hide P2 action buttons after an action is taken (using \!state.p2Action condition) - Add offer details display to G3, G4, and G5 (was missing) - Fix G2 to show offer details instead of just 'Oferta activa' - Reset game status to PLAYING when changing variant from FINISHED state - Ensure P2 can only make one decision per offer in all variants
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<div class="g">
|
||||
<h3>G1 – Sin derechos de propiedad</h3>
|
||||
<OfferControls v-if="myRole==='P1' && !state.offer?.active" @propose="onPropose" @no-offer="onNoOffer"/>
|
||||
<div v-if="state.offer?.active" class="controls">
|
||||
<div v-if="state.offer?.active && !state.p2Action" class="controls">
|
||||
<div class="offer-view">Oferta: 🦃 {{ state.offer.offerPavo }} / 🌽 {{ state.offer.offerElote }} | Pedido: 🦃 {{ state.offer.requestPavo }} / 🌽 {{ state.offer.requestElote }}</div>
|
||||
<div v-if="myRole === 'P2'">
|
||||
<button class="btn" @click="$emit('p2Action', 'accept')">P2: Aceptar</button>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<label><input type="checkbox" :checked="state.forcedByP2" @change="$emit('p2Force', ($event.target as HTMLInputElement).checked)"/> Forzar oferta</label>
|
||||
</div>
|
||||
<OfferControls v-if="myRole==='P1' && !state.offer?.active" :disable-no-offer="state.forcedByP2" @propose="onPropose" @no-offer="onNoOffer"/>
|
||||
<div v-if="state.offer?.active" class="note">Oferta activa</div>
|
||||
<div v-if="state.offer?.active" class="controls">
|
||||
<div v-if="state.offer?.active && !state.p2Action" class="controls">
|
||||
<div class="offer-view">Oferta: 🦃 {{ state.offer.offerPavo }} / 🌽 {{ state.offer.offerElote }} | Pedido: 🦃 {{ state.offer.requestPavo }} / 🌽 {{ state.offer.requestElote }}</div>
|
||||
<div v-if="myRole === 'P2'">
|
||||
<button class="btn" @click="$emit('p2Action', 'accept')">P2: Aceptar</button>
|
||||
<button class="btn" @click="$emit('p2Action', 'reject')">P2: Rechazar</button>
|
||||
@@ -35,6 +35,6 @@ function onNoOffer() {
|
||||
.g { background:#fff; padding:12px; border-radius:8px; }
|
||||
.controls { display:flex; gap:8px; margin:8px 0; }
|
||||
.btn { padding:8px 12px; border:none; border-radius:6px; background:#e3f2fd; color:#1565c0; cursor:pointer; }
|
||||
.note { color:#1565c0; font-weight:600; }
|
||||
.offer-view { font-size: 14px; color:#333; }
|
||||
.hint { color:#666; }
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
<div class="g">
|
||||
<h3>G3 – Token de repudio (vergüenza)</h3>
|
||||
<OfferControls v-if="myRole==='P1' && !state.offer?.active" @propose="onPropose" @no-offer="onNoOffer"/>
|
||||
<div v-if="state.offer?.active" class="controls">
|
||||
<div v-if="state.offer?.active && !state.p2Action" class="controls">
|
||||
<div class="offer-view">Oferta: 🦃 {{ state.offer.offerPavo }} / 🌽 {{ state.offer.offerElote }} | Pedido: 🦃 {{ state.offer.requestPavo }} / 🌽 {{ state.offer.requestElote }}</div>
|
||||
<div v-if="myRole === 'P2'">
|
||||
<button class="btn" @click="$emit('p2Action', 'accept')">P2: Aceptar</button>
|
||||
<button class="btn" @click="$emit('p2Action', 'reject')">P2: Rechazar</button>
|
||||
@@ -34,5 +35,6 @@ function onNoOffer() {
|
||||
.controls { display:flex; gap:8px; margin:8px 0; }
|
||||
.btn { padding:8px 12px; border:none; border-radius:6px; background:#e3f2fd; color:#1565c0; cursor:pointer; }
|
||||
.btn.warn { background:#ffecb3; color:#8d6e63; }
|
||||
.offer-view { font-size: 14px; color:#333; }
|
||||
.hint { color:#666; }
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
<div class="g">
|
||||
<h3>G4 – Derechos mínimos de propiedad (juez)</h3>
|
||||
<OfferControls v-if="myRole==='P1' && !state.offer?.active" @propose="onPropose" @no-offer="onNoOffer"/>
|
||||
<div v-if="state.offer?.active" class="controls">
|
||||
<div v-if="state.offer?.active && !state.p2Action" class="controls">
|
||||
<div class="offer-view">Oferta: 🦃 {{ state.offer.offerPavo }} / 🌽 {{ state.offer.offerElote }} | Pedido: 🦃 {{ state.offer.requestPavo }} / 🌽 {{ state.offer.requestElote }}</div>
|
||||
<div v-if="myRole === 'P2'">
|
||||
<button class="btn" @click="$emit('p2Action', 'accept')">P2: Aceptar</button>
|
||||
<button class="btn" @click="$emit('p2Action', 'reject')">P2: Rechazar</button>
|
||||
@@ -34,5 +35,6 @@ function onNoOffer() {
|
||||
.controls { display:flex; gap:8px; margin:8px 0; }
|
||||
.btn { padding:8px 12px; border:none; border-radius:6px; background:#e3f2fd; color:#1565c0; cursor:pointer; }
|
||||
.btn.warn { background:#ffe0e0; color:#b71c1c; }
|
||||
.offer-view { font-size: 14px; color:#333; }
|
||||
.hint { color:#666; }
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
<button class="btn" @click="send">Enviar</button>
|
||||
</div>
|
||||
<OfferControls v-if="myRole==='P1' && !state.offer?.active" @propose="onPropose" @no-offer="onNoOffer"/>
|
||||
<div v-if="state.offer?.active" class="controls">
|
||||
<div v-if="state.offer?.active && !state.p2Action" class="controls">
|
||||
<div class="offer-view">Oferta: 🦃 {{ state.offer.offerPavo }} / 🌽 {{ state.offer.offerElote }} | Pedido: 🦃 {{ state.offer.requestPavo }} / 🌽 {{ state.offer.requestElote }}</div>
|
||||
<div v-if="myRole === 'P2'">
|
||||
<button class="btn" @click="$emit('p2Action', 'accept')">P2: Aceptar</button>
|
||||
<button class="btn" @click="$emit('p2Action', 'reject')">P2: Rechazar</button>
|
||||
@@ -46,5 +47,6 @@ function onNoOffer() {
|
||||
.chat { display:flex; gap:8px; margin:8px 0; }
|
||||
.chat input { flex:1; padding:8px; border-radius:6px; border:1px solid #ddd; }
|
||||
.btn { padding:8px 12px; border:none; border-radius:6px; background:#e3f2fd; color:#1565c0; cursor:pointer; }
|
||||
.offer-view { font-size: 14px; color:#333; }
|
||||
.hint { color:#666; }
|
||||
</style>
|
||||
|
||||
@@ -85,6 +85,10 @@ export class GameRoom extends Room<GameState> {
|
||||
const player = this.state.players.get(client.sessionId);
|
||||
if (!player) return;
|
||||
if (player.role !== "P2") return;
|
||||
|
||||
// Prevent multiple actions on the same offer
|
||||
if (this.state.p2Action) return;
|
||||
|
||||
this.state.p2Action = action; // accept | reject | snatch
|
||||
this.resolveP2Action();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user