room center: GATE VIEW supersedes SCAN SIGS / CAST SKY / DRAW SEA / sig overlay when token cost lapses — ROLE pick survives grace — TDD
Phase 3 of the room GATE VIEW + seat-renewal sprint. When the viewer's own FILLED gate-slot cost has lapsed (filled_at past the cost-current window), the center hex shows a GATE VIEW button (→ room gate-view) instead of the phase affordances, so they must renew before advancing. - _role_select_context: adds viewer_cost_current / viewer_in_grace from the viewer's FILLED slot (no slot → current, defensive) - room.html: the ROLE card-stack renders OUTSIDE the cost gate (the gamer's own role pick survives the renewal grace — deposit privilege); GATE VIEW supersedes the rest of .table-center; #id_pick_sigs_wrap (SCAN SIGS, advancing the whole table) is gated on viewer_cost_current; the SIG/SKY/SEA overlays are gated too (they embed their trigger-btn ids in JS, so they must not render alongside GATE VIEW) - per user-spec: only the ROLE pick stays in grace; SCAN SIGS + every later phase get GATE VIEW Tests: RoomCenterSupersessionTest (9) — GATE VIEW supersedes sig overlay / CAST SKY / DRAW SEA / SCAN SIGS when lapsed, normal buttons when current; RoomRoleStackGraceTest (1) — card-stack (eligible) kept alongside GATE VIEW when lapsed. 838 epic+gameboard ITs green. Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -345,6 +345,19 @@ def _role_select_context(room, user):
|
||||
"gate_positions": _gate_positions(room),
|
||||
"slots": room.gate_slots.order_by("slot_number"),
|
||||
}
|
||||
# Viewer's seat token-cost state — drives the center-hex GATE VIEW
|
||||
# supersession (room.html). When the viewer's FILLED slot's cost has
|
||||
# lapsed (filled_at past the cost-current window), GATE VIEW replaces
|
||||
# SCAN SIGS / CAST SKY / DRAW SEA / the sig overlay; the gamer's own
|
||||
# ROLE card-stack pick survives the renewal grace. No filled slot →
|
||||
# treated as current (defensive — non-seated viewers see the normal UI).
|
||||
viewer_slot = (
|
||||
room.gate_slots.filter(gamer=user, status=GateSlot.FILLED).first()
|
||||
if user.is_authenticated else None
|
||||
)
|
||||
ctx["viewer_cost_current"] = viewer_slot.cost_current if viewer_slot else True
|
||||
ctx["viewer_in_grace"] = viewer_slot.in_renewal_grace if viewer_slot else False
|
||||
|
||||
# Tray cell 2: sig card (set once polarity group confirms)
|
||||
_canonical_seat = _canonical_user_seat(room, user) if user.is_authenticated else None
|
||||
ctx["my_tray_sig"] = _canonical_seat.significator if _canonical_seat else None
|
||||
|
||||
Reference in New Issue
Block a user