Commit Graph

16 Commits

Author SHA1 Message Date
Disco DeDisco
81b3c112b4 feat: wallet Shop applet — tile grid + BUY-ITEM microbutton + Stripe.js wiring — Chunk 4 of [[project-wallet-shop-expansion]]. The shop applet (slug wallet-shop, seeded in Chunk 2) now renders the catalog as a horizontal grid of .shop-tile icons: tithe-1 ($1, fa-piggy-bank), tithe-5 ($4, fa-piggy-bank w. ×5 badge), band-1 ($20, fa-ring). Each tile hosts a hover-portaled tooltip carrying name + description + price + a .tt-microbutton-portal w. a .btn-primary BUY ITEM button — clicking opens #id_guard_portal w. "Buy {name} for ${price}?" prompt; confirming triggers Stripe.js confirmCardPayment then POSTs to /shop/confirm + reloads. Items where the user's owned-count has hit max_owned (eg. BAND, owned=1, cap=1) render w. .btn-disabled + × glyph + "Already owned" microtooltip text — visible-but-unbuyable per the locked decision. View context — wallet view + toggle_wallet_applets view both pass shop_items (decorated w. per-user .available via the new _shop_items_for(user) helper) + default_payment_method_id + stripe_publishable_key. SCSS — .wallet-shop (flex column wrapping .shop-grid flex row), .shop-tile (inline-flex tooltip target), .shop-badge (2rem circle, --quaUser glyph on --quiUser bg, top-right corner per spec), .tt-microbutton-portal (column-flex, BUY btn + 'Already owned' caption styling). JS in wallet-shop.js exposes a singleton WalletShop module (matching the project's Brief / SeaDeal / StageCard module pattern) w. a tested initWalletShop() method — uses event delegation on the shop root (so portal-relocated buy btns still hit the handler) + a DOM-keyed data-shop-wired flag (not a module-level boolean) so per-test fixture rebuilds re-wire cleanly. Wired into wallet.html after wallet.js. **TDD** — 5 Jasmine specs in WalletShopSpec.js: T1 click-on-enabled-BUY opens guard w. correct prompt; T2 click-on-disabled-BUY no-op; T3 onConfirm POSTs shop_item_slug to /shop/buy; T4 init idempotent (calling twice doesn't double-wire); T5 missing-root no-throw. **2 Jasmine traps caught**: (a) spyOn(window, 'fetch') collides if another spec already spied on fetch — switched to save+restore via per-test _origFetch capture; (b) T3 async pollution — sync assertion passed, afterEach restored window.Stripe=undefined, then _doBuy's async continuation hit Stripe(pubKey) and threw "Unhandled promise rejection". Fixed by T3-local fetch mock returning a never-resolving promise so the chain pauses at the first await. **3 new FTs** in test_dash_wallet.py: tiles + icons + ×5 badge + tooltip prose; BUY click opens guard portal + NVM dismisses; BAND-already-owned shows disabled BUY w. 'Already owned' microtext (reads via textContent since .tt is display: none). FT trap caught: TransactionTestCase wipes both migration-seeded Applets + ShopItems → setUp must re-seed both manually (mirrors test_shop_views.py's _seed_starting_items pattern). 1208 IT/UT + 9 wallet FTs + 5 Jasmine specs green
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 01:15:05 -04:00
Disco DeDisco
e2040fda8f applet rows: hover + click-lock highlight on every .applet-list-entry.row-3col (My Posts / My Buds / My Notes / My Scrolls / My Games) — bg shifts to --secUser, title to --quiUser (overriding the inherited --terUser link color + stripping the text-shadow the global .applet-list-entry a:hover rule had been baking in), body + ts cells come up from their dimmed 0.6 / 0.5 opacity to full --priUser so the dim middle/right cols pop against the --secUser fill; new apps/applets/static/apps/applets/row-lock.js IIFE module owns the touch-persistence state machine (single _lockedRow ref, .row-locked class toggle): clicking a row not currently locked → locks (clearing any prior lock); clicking the locked row again → unlocks; clicking another row → moves the lock to the new row; clicking anywhere not inside a .row-3col → clears the lock — mirrors the note-page notes-locked click-lock state machine but lighter (no DON/DOFF, no greeting swap, no fetch), one document-level click listener bound once via _bound re-entry guard so beforeEach _init() calls in specs don't pile up handlers; loaded globally via base.html next to applets.js since the rows render on both /billboard/ + /gameboard/; padding-inline 0.5rem + border-radius 0.25rem on the row container shrinks the highlight to a chip shape so hovered rows don't bleed all the way to the applet box edge; 6 Jasmine specs in RowLockSpec.js cover the four state-machine transitions + the "child element of row still locks the parent row" affordance (since the user can tap the body cell text, not just the title link) + the "only one row carries .row-locked at a time" invariant; SpecRunner.html updated (both static_src + the static/ runtime mirror the FT reads from per the project's static-src→static copy discipline) — TDD
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:27:39 -04:00
Disco DeDisco
cc2a3f3526 rename natus → sky across the codebase — natal chart abstraction is now sky throughout, since chart inputs aren't birthday-gated
Some checks failed
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed
Mechanical rename: 5 files (sky-wheel.js, _sky.scss, _sky_overlay.html, SkyWheelSpec.js x2), 24 in-place edits across templates/views/urls/SCSS/JS/tests/CLAUDE.md. URL names epic:natus_save → epic:sky_save (epic namespaced, no clash w. dashboard:sky_save), JS module NatusWheel → SkyWheel, DOM ids id_natus_* → id_sky_*, BEM classes natus-* → sky-*, dashboard sky_natus_data/sky_natus_preview collapsed to sky_data/sky_preview_data. No DB migration needed (User.sky_chart_data + GameEvent.SKY_SAVED already used sky-prefix). 778 ITs + Jasmine green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 20:36:15 -04:00
Disco DeDisco
08243d109d tray cards: shadow, hover-tilt w. focus persistence, role-card tooltip — TDD
- _tray.scss: drop-shadow on cell child elements (img → filter:drop-shadow so the silhouette is the shadow caster, div → box-shadow); 7° hover-tilt on .tray-role-card > img (-7°) and .tray-sig-card > .sig-stage-card (+7° via the standalone `rotate` property so the existing -5° baseline transform composes); :focus persists the tilt after click; cursor: pointer
- tray.js: set tabIndex=0 on placeCard's role cell + on template-rendered .tray-role-card / .tray-sig-card cells at init() so :focus latches the hover state; clear tabindex in reset() for Jasmine afterEach
- TraySpec: 4 new specs covering placeCard tabindex, reset cleanup, init-time tabindex on template-rendered sig & role cards, no-tabindex on bare cells
- New tray-tooltip.js (#id_tooltip_portal) — Phase 1 of the apps.tooltips integration: hovering .tray-role-card > img copies its sibling .tt's innerHTML into the page-root portal, anchors above/below the trigger, & clamps to the viewport horizontally; mousemove outside the union of [trigger, portal] rects clears the portal (Game-Kit pattern, no btns)
- room.html: #id_tooltip_portal mounted at room-page root (outside tray's overflow:hidden); .tt block rendered inline inside .tray-role-card via {% tooltip %} templatetag w. title=role display name & description="[Placeholder description]"
- epic/views.py: my_tray_role_tooltip context dict ({title, description}) keyed off the seated role
- TrayTooltipSpec: 8 specs covering portal population, .active class, sibling-.tt fallback, viewport-edge clamp left/right, and union-rect mouseleave
- 2 FTs in test_component_tray_tooltip.py: hover role img → portal title=Player + description=Placeholder; mouseleave → portal clears

Phase 2 (sig-card tooltip mirroring #id_fan_fyi_panel via a DRY refactor) deferred per plan.

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:40:10 -04:00
Disco DeDisco
2f039559e6 Game Kit fan stage + FLIP/SPIN; sig/sea/fan refactor — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful
- fan modal: stage block w. idle-reveal/careen-out; carousel shifts left so focused card sits left-of-center; SPIN rotates whole card via Element.animate(); FLIP toggles polarity (Levity ↔ Gravity) via perspective rotateY w. mid-flip repaint; SPIN state retained across FLIP; FLIP btn hover-revealed only when focused card or btn is hovered (:has)
- mobile breakpoints: --fan-card-w / --fan-card-h / --fan-stage-shift / --fan-carousel-step lifted to CSS vars on .tarot-fan-wrap; portrait ≤ 480px @ 150×230, landscape ≤ 500h @ 150×235; corners + face text/padding scale w. card width
- shared StageCard JS module (apps/epic/stage-card.js): fromDataset, populateCard, populateKeywords, buildInfoData, renderFyi — sig/sea/fan all delegate; ~150 lines de-duplicated
- shared @mixin stat-block-shared (SCSS) lifts duplicated stat-face / stat-keywords / sig-info rules; @mixin stage-card-polarity unifies sea-stage--levity/--gravity + fan[data-polarity] coloring
- model rename: TarotCard.reversal → reversal_qualifier (migration 0014); render-time fallback to current polarity's qualifier when blank
- class unification: .sig-info-open / .sea-info-open / .fyi-open → .fyi-open (on stat block); .sig-flip-btn / .sea-spin-btn / .fan-spin-btn → .spin-btn; same for .fyi-btn / .fyi-prev / .fyi-next
- custom combobox (apps/epic/combobox.js) replaces native <select> for PICK SEA spread picker — keyboard nav, click-outside-close, aria roles; Firefox/Chrome OS-rendered <option> ignored CSS
- Jasmine: FanStageSpec.js w. idle-reveal / population / SPIN / FYI / FLIP specs; sig + sea fixtures + IT view assertions updated for renamed classes
- 748 ITs + Jasmine green

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 21:01:52 -04:00
Disco DeDisco
08aa4dc819 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>
2026-04-29 01:12:06 -04:00
Disco DeDisco
e78bbb873b Billnotes note-page interaction: hover glow, click-lock, DON/DOFF; note titles + card-ref styling — TDD
- note-page.js: click-lock (_lockedItem + notes-locked body class); DON auto-DOFFs prev donned; _setGreeting updates navbar; _donnedItem exposed for test API
- NotePageSpec.js: 18 Jasmine specs covering lock/unlock, DON/DOFF state, auto-DOFF, greeting update, initial load; flushPromises helper for chained fetch .then()
- _note.scss: DON/DOFF opacity:0 by default; hover + locked + donned states show them; body:not(.notes-locked) hover suppression
- views.py: Super-Schizo/Super-Nomad card titles; recognition_title field (display_title) separate from card title; mark_safe descriptions w. card-ref spans
- my_notes.html: |safe on description; recognition_title for Recognitions block
- _navbar.html: id_greeting_prefix/id_greeting_name spans for JS greeting update
- _base.scss: global .card-ref rule (--terUser, font-weight 600, !important)

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 01:54:57 -04:00
Disco DeDisco
473e6bc45a rename: Note→Post/Line (dashboard); Recognition→Note (drama); new-post/my-posts to billboard
- dashboard: Note→Post, Item→Line across models, forms, views, API, urls & tests
- new-post (9×3) & my-posts (3×3) applets migrate from dashboard→billboard context; billboard view passes form & recent_posts
- drama: Recognition→Note, related_name notes; billboard URL /recognition/→/my-notes/, set-palette at /note/<slug>/set-palette
- recognition.js→note.js (module Note, data.note key); recognition-page.js→note-page.js; .recog-*→.note-*
- _recognition.scss→_note.scss; BillNotes page header; applet slug billboard-recognition→billboard-notes (My Notes)
- NoteSpec.js replaces RecognitionSpec.js; test_recognition.py→test_applet_my_notes.py
- 4 migrations applied: dashboard 0004, applets 0011+0012, drama 0005; 683 ITs green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 22:32:34 -04:00
Disco DeDisco
565f727aa6 recognition: recognition.js showBanner/handleSaveResponse; wired into sky SAVE handler on applet & sky page — TDD
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 03:05:35 -04:00
Disco DeDisco
2910012b67 PICK SKY: natal wheel planet tooltips + FT modernisation
- natus-wheel.js: per-planet <g> group with data-planet/sign/degree/retrograde
  attrs; mouseover/mouseout on group (pointer-events:none on child text/℞ so
  the whole apparatus triggers hover); tooltip uses .tt-title/.tt-description;
  in-sign degree via _inSignDeg() (ecliptic % 30); D3 switched from CDN to
  local d3.min.js
- _natus.scss: .nw-planet--hover glow; #id_natus_tooltip position:fixed z-200
- _natus_overlay.html: tooltip div uses .tt; local d3.min.js script tag
- T3/T4/T5 converted from Selenium execute_script to Jasmine unit tests
  (NatusWheelSpec.js) — NatusWheel was never defined in headless GeckoDriver;
  SpecRunner.html updated to load D3 + natus-wheel.js
- test_pick_sky.py: NatusWheelTooltipTest removed (replaced by Jasmine)
- test_component_cards_tarot / test_trinket_carte_blanche: equip assertions
  updated from legacy .equip-deck-btn/.equip-trinket-btn mini-tooltip pattern
  to current DON|DOFF (.btn-equip in main portal); mini-portal text assertions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 01:57:02 -04:00
Disco DeDisco
c7370bda03 sig-select sprint: SigReservation model + sig_reserve view (OK/NVM hold); full sig-select.js rewrite with stage preview, WS hover cursors, reservation lock (must NVM before OK-ing another card — enforced server-side 409 + JS guard); sizeSigModal() + sizeSigCard() in room.js (JS-based card sizing avoids libsass cqw/cqh limitation); stat block hidden until OK pressed; mobile touch: dismiss stage on outside-grid tap when unfocused; 17 IT + Jasmine specs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 22:01:23 -04:00
Disco DeDisco
fb782cf5ef maybe don't delete collectstatic static/tests/ dir 2026-03-29 23:39:03 -04:00
Disco DeDisco
57f47cc77e another attempt to unclog pipeline; this time a slight sleep timeout used to accomodate headless browser resize flush
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-03-29 21:11:24 -04:00
Disco DeDisco
b35c9b483e seat tray: tray.js, SCSS, FTs, Jasmine specs
- new apps.epic.static tray.js: IIFE with drag-open/click-close/wobble
  behaviour; document-level pointermove+mouseup listeners; reset() for
  Jasmine afterEach; try/catch around setPointerCapture for synthetic events
- _room.scss: #id_tray_wrap fixed-right flex container; #id_tray_handle +
  #id_tray_grip (box-shadow frame, transparent inner window, border-radius
  clip); #id_tray_btn grab cursor; #id_tray bevel box-shadows, margin-left
  gap, height removed (align-items:stretch handles it); tray-wobble keyframes
- _applets.scss + _game-kit.scss: z-index raised (312-318) for primacy over
  tray (310)
- room.html: #id_tray_wrap + children markup; tray.js script tag
- FTs test_room_tray: 5 tests (T1-T5); _simulate_drag via execute_script
  pointer events (replaces unreliable ActionChains drag); wobble asserts on
  #id_tray_wrap not btn
- static_src/tests/TraySpec.js + SpecRunner.html: Jasmine unit tests for
  all tray.js branches

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 18:52:46 -04:00
Disco DeDisco
5d0a1401d8 created new dir for STATICFILES_DIRS in core.settings; all Jasmine test files transferred to new dir src/static_src/; new FT test_jasmine executes Jasmine test runner as part of CI pipeline & base FT has dobules MAX_WAIT to 10s; some cleanup of unused imports in text_simple_list_creation
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-02-11 14:42:38 -05:00
Disco DeDisco
a98a0fcd53 added Jasmine test suite from inside src/static dir to git repo 2026-02-11 13:43:59 -05:00