PICK SEA Sprint C: sea stage card viewer — FLIP in, SPIN/FYI, deposit/re-expand — TDD
- sea.js: SeaDeal module — openStage() shows big card viewer w. flip-in animation; SPIN toggles stage-card--reversed; FYI shows energies/operations (Energy/Operation titles, PRV/NXT nav); backdrop click deposits card to slot; click deposited slot re-opens stage; resetHand() clears hand on DEL - sea_deck view: adds name_group/name_title/reversal/keywords_upright/keywords_reversed/ energies/operations to each card dict (full sig-select stage data set) - _sea_overlay.html: data-sea-user-polarity attr; sea stage HTML (sig-stage-card shell + fan-card-face-upright/reversal structure + sea-stat-block w. SPIN/FYI/PRV/NXT); FLIP click calls SeaDeal.openStage(); _fillPos removed (sea.js handles slot fill); _reset calls SeaDeal.resetHand() - room.html: sea.js included alongside sig-select.js - _card-deck.scss: sea-stage layout (fixed overlay, backdrop, content row); sea-stage-card w. @keyframes sea-flip-in (3D rotateY perspective); sea-stat-block scoped styles incl. SPIN/FYI btns, stat faces, sig-info FYI panel - SeaDealSpec.js: 20 Jasmine specs — openStage, SPIN, FYI, backdrop dismiss, slot re-expand 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:
@@ -5,7 +5,8 @@
|
||||
|
||||
<div class="sea-backdrop"></div>
|
||||
<div class="sea-overlay" id="id_sea_overlay"
|
||||
data-sea-deck-url="{% url 'epic:sea_deck' room.id %}">
|
||||
data-sea-deck-url="{% url 'epic:sea_deck' room.id %}"
|
||||
data-sea-user-polarity="{{ user_polarity }}">
|
||||
|
||||
<div class="sea-modal-wrap">
|
||||
<div class="sea-modal">
|
||||
@@ -78,13 +79,13 @@
|
||||
<span class="sea-stacks-label">DECKS</span>
|
||||
<div class="sea-deck-stack sea-deck-stack--gravity">
|
||||
<div class="sea-stack-face">
|
||||
<button class="btn btn-confirm sea-stack-ok" type="button">OK</button>
|
||||
<button class="btn btn-reveal sea-stack-ok" type="button">FLIP</button>
|
||||
</div>
|
||||
<span class="sea-stack-name">Gravity</span>
|
||||
</div>
|
||||
<div class="sea-deck-stack sea-deck-stack--levity">
|
||||
<div class="sea-stack-face">
|
||||
<button class="btn btn-confirm sea-stack-ok" type="button">OK</button>
|
||||
<button class="btn btn-reveal sea-stack-ok" type="button">FLIP</button>
|
||||
</div>
|
||||
<span class="sea-stack-name">Levity</span>
|
||||
</div>
|
||||
@@ -109,6 +110,59 @@
|
||||
<button type="button" id="id_sea_cancel" class="btn btn-cancel btn-sm">NVM</button>
|
||||
|
||||
</div>{# /.sea-modal-wrap #}
|
||||
|
||||
{# ── Sea stage — big card viewer ─────────────────────────────────────────── #}
|
||||
<div class="sea-stage" id="id_sea_stage" style="display:none">
|
||||
<div class="sea-stage-backdrop"></div>
|
||||
<div class="sea-stage-content">
|
||||
<div class="sig-stage-card sea-stage-card" style="--sig-card-w:140px">
|
||||
<div class="fan-card-corner fan-card-corner--tl">
|
||||
<span class="fan-corner-rank"></span>
|
||||
<i class="fa-solid stage-suit-icon" style="display:none"></i>
|
||||
</div>
|
||||
<div class="fan-card-face">
|
||||
<div class="fan-card-face-upright">
|
||||
<p class="fan-card-name-group"></p>
|
||||
<p class="sig-qualifier-above"></p>
|
||||
<h3 class="fan-card-name"></h3>
|
||||
<p class="sig-qualifier-below"></p>
|
||||
</div>
|
||||
<p class="fan-card-arcana"></p>
|
||||
<div class="fan-card-face-reversal">
|
||||
<p class="fan-card-reversal-name"></p>
|
||||
<p class="fan-card-reversal-qualifier"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fan-card-corner fan-card-corner--br">
|
||||
<span class="fan-corner-rank"></span>
|
||||
<i class="fa-solid stage-suit-icon" style="display:none"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sig-stat-block sea-stat-block">
|
||||
<button class="btn btn-reverse sea-spin-btn" type="button">SPIN</button>
|
||||
<button class="btn btn-info sea-fyi-btn" type="button">FYI</button>
|
||||
<div class="stat-face stat-face--upright">
|
||||
<p class="stat-face-label">Emanation</p>
|
||||
<ul class="stat-keywords" id="id_sea_stat_upright"></ul>
|
||||
</div>
|
||||
<div class="stat-face stat-face--reversed">
|
||||
<p class="stat-face-label">Reversal</p>
|
||||
<ul class="stat-keywords" id="id_sea_stat_reversed"></ul>
|
||||
</div>
|
||||
<div class="sig-info" id="id_sea_fyi_panel" style="display:none">
|
||||
<div class="sig-info-header">
|
||||
<h4 class="sig-info-title"></h4>
|
||||
<p class="sig-info-type"></p>
|
||||
</div>
|
||||
<p class="sig-info-effect"></p>
|
||||
<span class="sig-info-index"></span>
|
||||
</div>
|
||||
<button class="btn btn-nav-left sea-fyi-prev" type="button">PRV</button>
|
||||
<button class="btn btn-nav-right sea-fyi-next" type="button">NXT</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>{# /.sea-overlay #}
|
||||
|
||||
<script>
|
||||
@@ -129,7 +183,6 @@
|
||||
const pickSeaBtn = document.getElementById('id_pick_sea_btn');
|
||||
if (pickSeaBtn) pickSeaBtn.addEventListener('click', openSea);
|
||||
cancelBtn.addEventListener('click', closeSea);
|
||||
overlay.addEventListener('click', (e) => { if (e.target === overlay) closeSea(); });
|
||||
|
||||
// ── Deck draw ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -174,22 +227,6 @@
|
||||
if (ok) ok.style.display = '';
|
||||
}
|
||||
|
||||
function _fillPos(sel, card, isLevity) {
|
||||
const cell = overlay.querySelector(sel);
|
||||
if (!cell) return;
|
||||
const slot = cell.querySelector('.sea-card-slot');
|
||||
if (!slot) return;
|
||||
slot.classList.remove('sea-card-slot--empty');
|
||||
slot.classList.add('sea-card-slot--filled');
|
||||
slot.classList.add(isLevity ? 'sea-card-slot--levity' : 'sea-card-slot--gravity');
|
||||
slot.dataset.cardId = String(card.id);
|
||||
slot.innerHTML =
|
||||
`<span class="fan-corner-rank">${card.corner_rank}</span>` +
|
||||
(card.suit_icon ? `<i class="fa-solid ${card.suit_icon}"></i>` : '');
|
||||
_filled++;
|
||||
if (lockBtn) lockBtn.disabled = (_filled < 6);
|
||||
}
|
||||
|
||||
function _reset() {
|
||||
_filled = 0;
|
||||
_hideOk();
|
||||
@@ -198,8 +235,10 @@
|
||||
s.classList.add('sea-card-slot--empty');
|
||||
s.innerHTML = '';
|
||||
delete s.dataset.cardId;
|
||||
delete s.dataset.posKey;
|
||||
});
|
||||
if (lockBtn) lockBtn.disabled = true;
|
||||
if (window.SeaDeal) SeaDeal.resetHand();
|
||||
_fetchDeck();
|
||||
}
|
||||
|
||||
@@ -224,7 +263,11 @@
|
||||
const pile = isLevity ? levityPile : gravityPile;
|
||||
const card = pile.length ? pile.shift() : null;
|
||||
const pos = _nextPosSelector();
|
||||
if (card && pos) _fillPos(pos, card, isLevity);
|
||||
if (card && pos) {
|
||||
_filled++;
|
||||
if (lockBtn) lockBtn.disabled = (_filled < 6);
|
||||
if (window.SeaDeal) SeaDeal.openStage(card, pos, isLevity);
|
||||
}
|
||||
_hideOk();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -113,5 +113,6 @@
|
||||
<script src="{% static 'apps/epic/gatekeeper.js' %}"></script>
|
||||
<script src="{% static 'apps/epic/role-select.js' %}"></script>
|
||||
<script src="{% static 'apps/epic/sig-select.js' %}"></script>
|
||||
<script src="{% static 'apps/epic/sea.js' %}"></script>
|
||||
<script src="{% static 'apps/epic/tray.js' %}"></script>
|
||||
{% endblock scripts %}
|
||||
|
||||
Reference in New Issue
Block a user