burger sea sub-btn: wire .active = show_picker and not hand_complete (phase 1/3) — TDD

First slice of the "Sea sub-btn opens the spread modal" feature push.

## Server (apps/gameboard/views.py)

`my_sea` view now passes `sea_btn_active = show_picker and not hand_complete` in context. Picker phase w. cards still to draw → True; landing / sign-gate / hand-complete states → False. The condition mirrors the AUTO-DRAW-vs-GATE-VIEW state machine — sea_btn lights up exactly when AUTO DRAW is the live action btn, returns to inactive at the same moment AUTO DRAW becomes GATE VIEW + the deck FLIP gains .btn-disabled.

## Template (_partials/_burger.html)

`#id_sea_btn` conditionally renders the `.active` class:
```
<button id="id_sea_btn" type="button" class="burger-fan-btn{% if sea_btn_active %} active{% endif %}" ...>
```

Per the burger sub-btn CSS that landed in 894d65f, .active means opacity 1 + skip the --priRd inactive-click flash. The other 4 sub-btns (sky/earth/voice/text/...) remain inactive scaffolding for later sprints to wire one-by-one.

## Tests (apps/gameboard/tests/integrated/test_views.py)

3 new ITs on MySeaViewTest:
- `test_sea_btn_is_inactive_on_landing_phase` — fresh user / landing → no .active class.
- `test_sea_btn_is_active_on_picker_phase_with_partial_hand` — sig + 1-card MySeaDraw → .active class present.
- `test_sea_btn_returns_to_inactive_when_hand_complete` — 3-card spread w. all 3 positions drawn → hand_complete True → sea_btn back to inactive (regression guard for the GATE VIEW transition).

## Verification

All 12 MySeaViewTest green (+3 new). No JS / CSS touches — pure server + template change. Phase 2 (modal extraction + .sea-stacks relocate) + Phase 3 (--priYl glow handoff) land in follow-up commits.

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:
Disco DeDisco
2026-05-26 23:24:27 -04:00
parent 5cade51d03
commit 3ae85b962b
3 changed files with 63 additions and 1 deletions

View File

@@ -1042,6 +1042,63 @@ class MySeaViewTest(TestCase):
response = self.client.get(reverse("my_sea")) response = self.client.get(reverse("my_sea"))
self.assertIn("location.href='/gameboard/'", response.content.decode()) self.assertIn("location.href='/gameboard/'", response.content.decode())
def test_sea_btn_is_inactive_on_landing_phase(self):
"""Sea sub-btn flips ACTIVE only when the user is in the picker
phase w. cards still to draw. Landing phase = inactive (default)."""
response = self.client.get(reverse("my_sea"))
self.assertContains(
response,
'<button id="id_sea_btn" type="button" class="burger-fan-btn" aria-label="Sea">',
)
def test_sea_btn_is_active_on_picker_phase_with_partial_hand(self):
from apps.epic.models import personal_sig_cards, TarotCard
from apps.gameboard.models import MySeaDraw
sig = personal_sig_cards(self.user)[0]
self.user.significator = sig
self.user.save(update_fields=["significator"])
card = TarotCard.objects.exclude(pk=sig.pk).first()
MySeaDraw.objects.create(
user=self.user, spread="situation-action-outcome",
significator_id=sig.id,
hand=[{"position": "lay", "card_id": card.id,
"reversed": False, "polarity": "gravity"}],
)
response = self.client.get(reverse("my_sea"))
self.assertContains(
response,
'id="id_sea_btn" type="button" class="burger-fan-btn active"',
)
def test_sea_btn_returns_to_inactive_when_hand_complete(self):
"""3-card spread w. all 3 positions drawn → hand_complete True →
sea_btn returns to inactive (the AUTO DRAW btn becomes GATE VIEW
+ the deck FLIP gets .btn-disabled at this moment)."""
from apps.epic.models import personal_sig_cards, TarotCard
from apps.gameboard.models import MySeaDraw
sig = personal_sig_cards(self.user)[0]
self.user.significator = sig
self.user.save(update_fields=["significator"])
cards = list(TarotCard.objects.exclude(pk=sig.pk)[:3])
MySeaDraw.objects.create(
user=self.user, spread="situation-action-outcome",
significator_id=sig.id,
hand=[
{"position": "lay", "card_id": cards[0].id,
"reversed": False, "polarity": "gravity"},
{"position": "cross", "card_id": cards[1].id,
"reversed": False, "polarity": "gravity"},
{"position": "crown", "card_id": cards[2].id,
"reversed": False, "polarity": "gravity"},
],
)
response = self.client.get(reverse("my_sea"))
# active class absent
self.assertContains(
response,
'<button id="id_sea_btn" type="button" class="burger-fan-btn" aria-label="Sea">',
)
def test_gear_nvm_navs_to_my_sea_landing_on_picker_phase(self): def test_gear_nvm_navs_to_my_sea_landing_on_picker_phase(self):
"""Picker-phase NVM = "back out of the spread to the table hex" """Picker-phase NVM = "back out of the spread to the table hex"
/gameboard/my-sea/ (the landing). User-spec'd 2026-05-26 so the /gameboard/my-sea/ (the landing). User-spec'd 2026-05-26 so the

View File

@@ -348,6 +348,11 @@ def my_sea(request):
"next_free_draw_at": next_free_draw_at, "next_free_draw_at": next_free_draw_at,
"hand_complete": hand_complete, "hand_complete": hand_complete,
"show_picker": show_picker, "show_picker": show_picker,
# Sub-btn .active flag for the burger fan — Sea sub-btn lights up
# when the user is in the picker phase w. cards still to draw.
# As soon as hand_complete flips True (AUTO DRAW → GATE VIEW + the
# deck FLIP gets .btn-disabled) the Sea sub-btn returns to inactive.
"sea_btn_active": show_picker and not hand_complete,
"show_paid_draw": show_paid_draw, "show_paid_draw": show_paid_draw,
"show_gate_view": show_gate_view, "show_gate_view": show_gate_view,
"deposit_reserved": deposit_reserved, "deposit_reserved": deposit_reserved,

View File

@@ -24,7 +24,7 @@
<i class="fa-solid fa-earth-americas burger-fan-icon--on"></i> <i class="fa-solid fa-earth-americas burger-fan-icon--on"></i>
<i class="fa-solid fa-ban burger-fan-icon--off"></i> <i class="fa-solid fa-ban burger-fan-icon--off"></i>
</button> </button>
<button id="id_sea_btn" type="button" class="burger-fan-btn" aria-label="Sea"> <button id="id_sea_btn" type="button" class="burger-fan-btn{% if sea_btn_active %} active{% endif %}" aria-label="Sea">
<i class="fa-solid fa-bridge-water burger-fan-icon--on"></i> <i class="fa-solid fa-bridge-water burger-fan-icon--on"></i>
<i class="fa-solid fa-ban burger-fan-icon--off"></i> <i class="fa-solid fa-ban burger-fan-icon--off"></i>
</button> </button>