Skip to content

feat(my-account): build v2 prototype modals (Phase 5)#4681

Merged
thomasguillot merged 4 commits into
prototype/my-account-demofrom
prototype/my-account-demo-phase-5
Apr 28, 2026
Merged

feat(my-account): build v2 prototype modals (Phase 5)#4681
thomasguillot merged 4 commits into
prototype/my-account-demofrom
prototype/my-account-demo-phase-5

Conversation

@thomasguillot
Copy link
Copy Markdown
Contributor

All Submissions:

Changes proposed in this Pull Request:

Phase 5 of the My Account v2 prototype (umbrella tracker: #4679; targets prototype/my-account-demo, not trunk). Promotes the five remaining stub-snackbar triggers on the ?v2-demo=1 donation and subscription detail pages to real modals. Each modal lives at the bottom of its detail (or list) template behind a status guard, keyed by resource id, and matches the corresponding Figma frame:

  • Cancel subscription — confirmation pattern: "Are you sure?" body + active-until date, transitioning to a green-check success step with email-confirmation copy. (Figma 2636:462592636:46262.)
  • Renew subscription — single-screen transaction (summary box + Pay-now CTA + billing readout + Stripe-style payment form), then a success step. (2636:462762636:46269.)
  • Cancel donation — same confirmation shape as cancel-subscription with donation copy. (2636:465912636:46550.)
  • Restart donation — transaction pattern (no Figma success state — terminates on snackbar). (2636:46530.)
  • Modify donation — frequency segmented control + currency input + cover-fees checkbox + recurring-totals breakdown that recomputes live as the amount or fee toggle changes. (2636:46578.)

The detail-page click handler in donations.js / subscriptions.js is rewritten as a small action-router (tryOpenModal(action, id, root)): it looks up newspack-my-account__<slug>-<id> and toggles data-state="open" if the modal exists, otherwise the click falls through to a snackbar fallback for update-payment-method (the only Phase 5 stub left — the brief lumps it with the v1 checkout flow). The same handler covers the inline "renew now" anchor inside the expiring-subscription notice on both list and detail pages.

The shared snackbar helper that newsletters / donations / subscriptions all carried as identical copies has been extracted into src/my-account/v2-demo/util/snackbar.js per the cross-phase rule-of-three commitment. The refactor lands as its own no-op commit ahead of the modal code so the diff stays reviewable.

This PR also updates the roadmap to insert a new Phase 6 — Payment methods (reproduce v1's /my-account/payment-methods/ byte-for-byte under the demo flag, fed by fake data — no new design); the previous Phase 6 (polish + scenario fixtures) becomes Phase 7. Brief §3 / §10 / §12 + devlog updated; historical Phase 6 references in earlier devlog entries are left in place because the new cross-phase decision row dates the renumbering, preserving the timeline.

update-payment-method is intentionally not a Phase 5 modal; building one would either duplicate the renew/restart payment forms or pretend to mutate state. Phase 6 / productisation will resolve.

How to test the changes in this Pull Request:

  1. On a Newspack site with the prototype branch checked out, sign in as an administrator and append ?v2-demo=1 to any /my-account/... URL.
  2. Visit /my-account/subscriptions/sub-001/?v2-demo=1. Open the More dropdown next to the page header. Click Cancel subscription: a small modal opens with "Are you sure?", an active-until date in bold ("March 16, 2027"), a destructive Cancel CTA, and a ghost "Keep subscription". Click Cancel: the modal flips to a success step (green check + "Your subscription has been successfully cancelled." + the reader's email in bold + a Done button). Close via Done, the X button, or the overlay. Re-open: it should show the init step again (state resets on close).
  3. Same page, click Change subscription in the header. Confirm Phase 4's tier-picker modal still opens correctly (Phase 5 didn't touch it but the click router did).
  4. Visit /my-account/subscriptions/sub-cancelled/?v2-demo=1. Click Renew subscription: the modal shows a summary box ("Patron: $101.70 / year"), a Pay-now CTA, a billing-details readout (John Lewis address), and a Stripe-style payment form (radio + card/expiry/CVC inputs + cover-fees checkbox). Click Pay now: flips to a "Thank you" success step.
  5. Visit /my-account/subscriptions/sub-expiring/?v2-demo=1. Confirm the inline error notice's "renew now" anchor opens the same Renew modal as step 4 (instead of the previous stub snackbar). The header Renew subscription button does the same thing.
  6. Visit /my-account/donations/don-001/?v2-demo=1. Click Edit donation: a modal opens with a Frequency segmented control (Monthly / Annually preselect matches the donation's current frequency), an editable amount input, a "Cover transaction fees?" checkbox, and a Recurring totals box (Subtotal / VAT / Transaction fee / Recurring total + next-donation date). Edit the amount: subtotal/VAT/total all update live. Toggle the cover-fees checkbox: the transaction fee row flips between and $X.XX. Switch to Annually: the unit suffix in the amount label and total flips to "/ year". Click Confirm donation: the modal closes and a "Donation modified." snackbar appears.
  7. Same page, open the More dropdown and click Cancel donation: confirmation pattern (init → success), same shape as step 2.
  8. Same page, More → Update payment method: snackbar (intentionally — this stays a stub in Phase 5).
  9. Visit /my-account/donations/don-cancelled/?v2-demo=1. Click Restart donation: modal opens with "Donate Annually: $153.00" summary, a Restart donation CTA, billing readout, and the Stripe-style form. Click Restart: snackbar ("Donation restarted.") and the modal closes (no success step in Figma for restart).
  10. As a non-admin user (or signed out), confirm the same URLs render v1 unchanged with no modal markup leaking — the demo is gated on manage_options.
  11. Run npm run lint:php, npm run lint:js -- src/my-account/v2-demo/, and npm run lint:scss -- 'src/my-account/v2-demo/**/*.scss' — all should pass.
  12. Run npm run build — should complete with no new errors.
  13. Open docs/my-account-v2-prototype-brief.md and confirm §3 lists four primary surfaces (newsletters / donations / subscriptions / payment methods), §10 has Phase 6 (payment methods) before Phase 7 (polish), and §12 says "five primary screens".

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

…r.js

Pre-Phase 5 cleanup. Newsletters / donations / subscriptions all carried
identical copies of `ensureSnackbarContainer` + `snackbar`; Phase 5
modals make a third caller. Per the cross-phase devlog rule-of-three
commitment, factor into `src/my-account/v2-demo/util/snackbar.js` and
import from there. No behaviour change.
Five remaining modal flows from the brief, each as its own partial under
`templates/v2-demo/partials/`:

- cancel-subscription-modal.php — confirmation pattern (init + success).
- renew-subscription-modal.php — transaction pattern + success state.
- cancel-donation-modal.php — same shape as cancel-subscription.
- restart-donation-modal.php — transaction pattern (no success state).
- modify-donation-modal.php — frequency + amount editor with live totals.

Detail templates load partials behind the same status guards their headers
already branch on. The list-page renders the renew modal alongside any
expiring sub in the active bucket so the inline 'renew now' anchor opens
the modal once Phase 6 fixtures swap one in.

donations.js / subscriptions.js trade the per-action snackbar switch for a
slug-map dispatcher (`tryOpenModal` / `tryOpenDonationModal`); each
opens `newspack-my-account__<slug>-<id>` and toggles `data-state` to
'open'. Confirmation modals reset to init via the `closeModal` event.
Modify-donation recomputes totals declaratively as the amount changes.

`update-payment-method` stays a stub snackbar — the brief lumps it with
the v1 checkout flow, not a Phase 5 modal.

Devlog Phase 5 entry + cross-phase decision log rows added.
…o Phase 7

Mid-Phase-5 scope addition: reproduce v1's `/my-account/payment-methods/`
page byte-for-byte under the v2-demo flag, fed by fake data — no new
design, no new components. Closes a credibility gap (the v1 surface
exists today and readers see it; the prototype had no story there).

Brief §3 grows from three to four primary surfaces (newsletters /
donations / subscriptions / payment methods). Brief §10 gains a new
Phase 6 entry; the previous Phase 6 (polish + scenario fixtures) becomes
Phase 7. §12 definition-of-done updated to "five primary screens."

Devlog adds the Phase 6 / Phase 7 stubs and a cross-phase decision row.
Historical entries' Phase 6 references (scenario fixtures, polish, etc.)
are left as-is; the decision row dates the renumbering so the timeline
stays auditable.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR advances the My Account v2 demo prototype (Phase 5) by replacing remaining “stub snackbar” actions on donation/subscription detail screens with real, status-guarded modal flows, and by extracting a shared snackbar utility used across v2-demo screens.

Changes:

  • Added Phase 5 modal partials for cancel/renew subscription and cancel/restart/modify donation flows, with JS wiring for step transitions and close/reset behavior.
  • Refactored per-screen snackbar helpers into a shared src/my-account/v2-demo/util/snackbar.js utility and updated callers.
  • Updated prototype documentation/roadmap to introduce Phase 6 (Payment methods) and renumber subsequent phases.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/my-account/v2-demo/util/snackbar.js New shared snackbar helper used by multiple v2-demo screens.
src/my-account/v2-demo/subscriptions.js Reworked click handling into an action router; added modal wiring for cancel/renew flows; switched to shared snackbar.
src/my-account/v2-demo/donations.js Added modal wiring for cancel/restart/modify donation; switched to shared snackbar.
src/my-account/v2-demo/newsletters.js Switched to shared snackbar helper.
includes/.../templates/v2-demo/subscriptions.php Renders renew-subscription modal(s) for expiring active list rows (forward-compat).
includes/.../templates/v2-demo/subscription-details.php Loads cancel/renew modal partials based on subscription status guards.
includes/.../templates/v2-demo/donation-details.php Loads modify/cancel/restart donation modal partials based on donation status guards.
includes/.../partials/renew-subscription-modal.php New two-step renew subscription modal (init → success) with billing/payment markup.
includes/.../partials/cancel-subscription-modal.php New two-step cancel subscription confirmation modal (init → success).
includes/.../partials/modify-donation-modal.php New modify donation modal with segmented control and JS-driven totals recompute.
includes/.../partials/cancel-donation-modal.php New two-step cancel donation confirmation modal (init → success).
includes/.../partials/restart-donation-modal.php New restart donation transaction modal terminating on snackbar.
docs/my-account-v2-prototype-devlog.md Added Phase 5 entry and roadmap renumbering notes.
docs/my-account-v2-prototype-brief.md Updated scope/roadmap to include Payment methods as Phase 6 and adjust estimates/DoD.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/my-account/v2-demo/subscriptions.js Outdated
Three issues flagged on PR #4681:

- subscriptions.js: `handleActionClick` was unconditionally calling
  `preventDefault()` on any anchor with a `data-action`, which would
  break the list-page "Manage subscription" link
  (`<a data-action="manage-subscription" href=".../subscriptions/<id>/">`)
  by suppressing real navigation when no modal handler matches. Move
  `preventDefault()` inside the handled paths so unhandled actions let
  the trigger behave naturally.

- modify-donation-modal.php: the amount input used
  `number_format_i18n()` for both `value` and `data-initial-amount`.
  In comma-decimal locales this produces "9,99", which JS `parseFloat`
  truncates to 9 — breaking the live totals math and confirm-button
  enable/disable. Switch to dot-decimal `number_format($amount, 2, '.', '')`
  for the machine-readable value (display-only strings keep i18n).

- renew-subscription-modal.php / restart-donation-modal.php: the
  `<div id="payment">` would duplicate IDs when multiple modals
  render on the same page (the brief's forward-compat for Phase 6
  fixtures puts more than one renew modal on the list view) and could
  collide with WC's own checkout markup elsewhere. Suffix with the
  resource id.
@thomasguillot thomasguillot marked this pull request as ready for review April 28, 2026 16:37
@thomasguillot thomasguillot requested a review from a team as a code owner April 28, 2026 16:37
@thomasguillot thomasguillot added the [Status] Needs Review The issue or pull request needs to be reviewed label Apr 28, 2026
@thomasguillot thomasguillot merged commit 210ca51 into prototype/my-account-demo Apr 28, 2026
13 checks passed
@thomasguillot thomasguillot deleted the prototype/my-account-demo-phase-5 branch April 28, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Status] Needs Review The issue or pull request needs to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants