ROLE SELECT: block role pick without deck; SigSelect qualifier spec fix — TDD
- role-select.js: _showNoDeckWarning(stack) intercepts at openFan() — fan never
opens when data-equipped-deck=""; warning positioned fixed over card-stack via
getBoundingClientRect(); .guard-actions wrapper for FYI/.btn-caution + NVM/.btn-cancel
- room.html: card-stack gains data-equipped-deck="{{ equipped_deck_id|default:'' }}"
- room view context: equipped_deck_id added
- _room.scss: .role-no-deck-warning — glass guard style matching #id_guard_portal
- _base.scss + _room.scss: guard portal + no-deck warning opacity 0.5 → 0.75
(matches .tt tooltip; light-palette handled via --tooltip-bg CSS var)
- RoleSelectSpec.js: 8 Jasmine specs — no-deck (fan blocked, warning, FYI/NVM,
no duplicate, no POST) + deck-present pass-through; afterEach cleans up warning
- SigSelectSpec.js: card fixture gains data-levity-qualifier + data-gravity-qualifier;
all "Leavened" expectations updated to "Elevated"
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,29 @@ var RoleSelect = (function () {
|
||||
if (backdrop) backdrop.remove();
|
||||
}
|
||||
|
||||
function _showNoDeckWarning(stack) {
|
||||
if (document.querySelector(".role-no-deck-warning")) return;
|
||||
var el = document.createElement("div");
|
||||
el.className = "role-no-deck-warning";
|
||||
el.innerHTML =
|
||||
"<p>Equip card deck before Role select</p>" +
|
||||
"<div class=\"guard-actions\">" +
|
||||
"<a class=\"btn btn-caution\" href=\"/gameboard/\">FYI</a>" +
|
||||
"<button class=\"btn btn-cancel\">NVM</button>" +
|
||||
"</div>";
|
||||
el.querySelector(".btn-cancel").addEventListener("click", function () {
|
||||
el.remove();
|
||||
});
|
||||
if (stack) {
|
||||
var rect = stack.getBoundingClientRect();
|
||||
el.style.position = "fixed";
|
||||
el.style.left = Math.round(rect.left + rect.width / 2) + "px";
|
||||
el.style.top = Math.round(rect.top + rect.height / 2) + "px";
|
||||
el.style.transform = "translate(-50%, -50%)";
|
||||
}
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
|
||||
function selectRole(roleCode) {
|
||||
_turnChangedBeforeFetch = false; // fresh selection, reset the race flag
|
||||
closeFan();
|
||||
@@ -138,6 +161,12 @@ var RoleSelect = (function () {
|
||||
function openFan() {
|
||||
if (document.querySelector(".role-select-backdrop")) return;
|
||||
|
||||
var stack = document.querySelector(".card-stack[data-starter-roles]");
|
||||
if (stack && stack.dataset.equippedDeck === "") {
|
||||
_showNoDeckWarning(stack);
|
||||
return;
|
||||
}
|
||||
|
||||
var taken = getStarterRoles();
|
||||
var available = ROLES.filter(function (r) { return taken.indexOf(r.code) === -1; });
|
||||
|
||||
|
||||
@@ -276,6 +276,7 @@ def _role_select_context(room, user):
|
||||
_my_role = assigned_seats[0].role if assigned_seats else None
|
||||
ctx = {
|
||||
"card_stack_state": card_stack_state,
|
||||
"equipped_deck_id": user.equipped_deck_id if user.is_authenticated else None,
|
||||
"starter_roles": starter_roles,
|
||||
"assigned_seats": assigned_seats,
|
||||
"my_tray_role": _my_role,
|
||||
|
||||
Reference in New Issue
Block a user