Skip to content

feat(my-account): v2 prototype#4679

Draft
thomasguillot wants to merge 32 commits into
trunkfrom
prototype/my-account-demo
Draft

feat(my-account): v2 prototype#4679
thomasguillot wants to merge 32 commits into
trunkfrom
prototype/my-account-demo

Conversation

@thomasguillot
Copy link
Copy Markdown
Contributor

@thomasguillot thomasguillot commented Apr 28, 2026

All Submissions:

Changes proposed in this Pull Request:

Lands the My Account v2 design-review prototype — an admin-gated, fake-data, clickable build of the redesigned /my-account/ experience, plus a small WP-admin companion. It exists so stakeholders can actually use the redesign during review on any Newspack site, without touching what real readers see.

Figma: My Account — i5 (Final)


How it works (mental model in 60 seconds)

  • One query parameter turns it on. Append ?my-account-v2-demo=1 to any /my-account/... URL (or to the homepage). The prototype renders.
  • Only admins see it. Every callback gates on is_account_page() + logged-in + manage_options + ?my-account-v2-demo. Non-admins get v1 unchanged. No-flag admins also get v1 unchanged.
  • Everything is fake data. A single My_Account_V2_Demo::get_fake_data() method feeds every template and JS module. Real readers, orders, subscriptions, and payment methods are never touched. You can demo this on a brand-new site with zero donations or subs configured.
  • Every action is a snackbar. Modify / Cancel / Renew / Restart / Subscribe / Unsubscribe / Save / Delete / Add — they all do client-side DOM updates + a toast. No AJAX, no POST, no real Stripe. Newsletter row state persists across reloads via localStorage; everything else resets.
  • Internal links carry the flag. Clicking around inside the demo stays in the demo. The flag is appended to every internal endpoint URL via a filter, so navigation doesn't drop you back into v1.
  • There's also a WP-admin companion. A new Reader Account Customization tab in the Audience wizard (/wp-admin/admin.php?page=newspack-audience#/reader-account-customization) shows publishers what the v2 customisation controls would look like. Pure-demo: local React state, Save is a no-op. Doesn't need the ?my-account-v2-demo flag — admin caps gate the whole wizard already.

Quick start — demo it in 30 seconds

  1. Pull prototype/my-account-demo into a Newspack site with WooCommerce (and ideally WC Subscriptions).
  2. n npm run build (or n npm start for watch).
  3. As an admin, open: /my-account/?my-account-v2-demo=1.
  4. Click around. Every internal link keeps you in the demo.
  5. For the admin companion: /wp-admin/admin.php?page=newspack-audience#/reader-account-customization.

If endpoint URLs 404 in dev/staging (opcache + ENDPOINTS_VERSION race): n wp eval 'opcache_reset();' && n wp option delete newspack_my_account_v2_demo_endpoints_version && n wp rewrite flush. Production deploys clear opcache, so this only bites in dev.


Demo walkthrough

A suggested running order for a stakeholder review. Each surface notes what's clickable and what just fires a snackbar.

1. Sidebar + entry — /my-account/?my-account-v2-demo=1

The shell. Sidebar shows Account details / Newsletters / Donations / Subscriptions / Payment information (in that order). Dashboard body is v1 unchanged — all the v2 work lives behind the sidebar items.

2. Newsletters — /my-account/newsletters/?my-account-v2-demo=1

Sectioned list (Featured / Technology / Subscriber-only) of newsletter rows, each with a thumbnail, frequency badge, optional SUBSCRIBER-ONLY outline badge, and a Sign up / Unsubscribe button.

  • Click any row's button — fake-network spinner runs for ~1.5s, the row flips state, snackbar fires. Try toggling several rows.
  • Click "Unsubscribe from all" at the bottom — every visible Unsubscribe button spins in unison, then all rows flip to Sign up, button disables.
  • Reload the page — your row state survives (this surface uses localStorage so the demo feels like real persistence; productionisation removes that layer).
  • Try ?my-account-v2-demo=no-categories for the flat-list variant.

3. Donations — /my-account/donations/?my-account-v2-demo=1

List with two sections:

  • Recurring donation — a Plan Card with a Manage donation button.
  • Previous donations — a clickable table.

Click the active card's Manage donation → detail page (/donations/don-001/). Detail page has:

  • Edit donation → opens the Modify donation modal (frequency tabs, amount input, totals breakdown that recomputes as you type, cover-fees toggle).
  • More dropdown → Update payment method (snackbar stub) + Cancel donation (two-step modal: confirm → success).

A cancelled donation (click any cancelled row in the Previous table) shows a CANCELLED badge + a single Restart donation button → transaction modal, snackbar on submit.

The list-page bottom has a billing history Button Card. Try ?my-account-v2-demo=billing-history to see the inline-table variant instead.

4. Subscriptions — /my-account/subscriptions/?my-account-v2-demo=1

Same shape as Donations: active section + previous section. Each card click → detail page.

The detail page is the variant-richest in the prototype. Walk these URLs in order to see all six branches:

URL Variant
/subscriptions/sub-001/?my-account-v2-demo=1 Active (Change subscription + More dropdown)
/subscriptions/sub-cancelled/?my-account-v2-demo=1 Cancelled (CANCELLED badge + Renew button)
/subscriptions/sub-expired/?my-account-v2-demo=1 Expired (EXPIRED badge + Renew button)
/subscriptions/sub-expiring/?my-account-v2-demo=1 Expiring (inline error notice + Renew, also reachable via inline "renew now" anchor)
/subscriptions/sub-renewed/?my-account-v2-demo=1 Renewed (visually identical to active)
/subscriptions/sub-active-no-fees/?my-account-v2-demo=1 Active + fees covered (Amount breakdown collapses to a single Total row)

The Change subscription modal is the most ambitious in the prototype: segmented control of frequency tabs → tier cards → transaction step with a billing readout + Stripe-style payment form. Every "Pay now" snackbars and closes.

5. Payment information — /my-account/payment-methods/?my-account-v2-demo=1

Card-based shell (rebuilt onto v1's payment-information.php shape mid-prototype after design review reversed the original WC-core-table call). Two sections:

  • Payment methods__box --border card per saved card. Default badge on the default row, Expired badge under ?my-account-v2-demo=expired-payment. Each card has a More dropdown with Edit + Delete modals, plus an Add payment method button that opens a singleton modal.
  • Addresses — billing + shipping cards. Each card's More opens Edit/Add address (modal title swaps based on whether the slot is populated) or Delete address.

Every modal Confirm fires a slug-keyed snackbar and closes. Try ?my-account-v2-demo=no-addresses to demo the empty-addresses fallback.

6. Account settings — /my-account/edit-account/?my-account-v2-demo=1

Profile + Password forms reusing v1's DOM. Save buttons fire snackbars without navigating. Forgot-password link snackbars.

The Delete account button is the centrepiece. It opens a two-step modal:

  • Step 1: "Are you sure?" + three "Manage my…" alternative-action rows (Donations / Subscriptions / Newsletters), each linking to the corresponding endpoint with the demo flag preserved.
  • Step 2: "Check your inbox" success state with email-send icon and the reader's address echoed back.

Close (X / ESC / backdrop / Cancel) resets to step 1.

7. Homepage drawer — /?my-account-v2-demo=1

The same flag on the site homepage opens a right-side drawer overlay with a backdrop. Greeting reads "Good {morning|afternoon|evening}, {first name}." based on the visitor's local time. The drawer mirrors the v2 sidebar menu, adds a placeholder secondary nav (FAQ / Contact us / Privacy Policy / Terms of Service), and a Sign out footer.

  • Click any menu item → lands on the corresponding /my-account/<slug>/?my-account-v2-demo=1.
  • Close via X, backdrop click, or ESC.
  • From any /my-account/ page, the sidebar's "Back to Homepage" link reopens the drawer (the flag survives the round-trip).

8. WP-admin: Reader Account Customization — /wp-admin/admin.php?page=newspack-audience#/reader-account-customization

The admin companion. New tab in the Audience wizard, between Configuration and Checkout & Payment. Three two-column sections — Branding (logo upload), Newsletters (page title + description), Account & Billing (Terminology toggle with Custom revealing stacked singular + plural inputs, plus cancel-recurring-donation message and billing/invoice footer).

  • Type / toggle / upload — every control responds. Selecting Terminology → Custom reveals two stacked text inputs.
  • Click Save Settings — no-op (pure-demo, local React state only).
  • Navigate away and back — state resets.

The brief's §2.1 / §2.1.1 reflexes (no custom CSS, reuse v1 class names) don't apply to this surface — admin React pages compose from @wordpress/components first, packages/components/src second, custom SCSS last. The single scoped SCSS rule that ships zeroes legacy BaseControl margins so the per-section <VStack spacing={8}> is the only source of vertical rhythm.


Scenario fixtures (alternate states)

Every URL accepts a scenario name in place of 1 to demo specific variants without writing real data:

Scenario What it shows
1 (or any unknown value) Happy path
cancelled-sub Active slot becomes a cancelled sub on the list
expiring Active slot becomes an expiring sub (inline error notice on list + detail)
renewed Active slot becomes a recently-renewed sub
no-fees Active sub renders without the Amount breakdown
billing-history Donations list embeds a billing-history table at the bottom
no-categories Newsletters flatten to a single ungrouped list
expired-payment Non-default saved card surfaces an inline Expired badge
empty Empties donations + subs + payment methods + addresses
no-donations / no-subscriptions / no-payment-methods / no-addresses Empties the named slice only

Allow-listed; anything outside the table falls through to the happy path. Full reference: Guide § Scenario index.


Gating regression check

Before signing off, log out (or switch to a non-admin user) and confirm the prototype is invisible to real readers:

  • /my-account/?my-account-v2-demo=1 → v1 renders unchanged. No newspack-my-account-v2-demo body class; no my-account-v2-demo.{js,css} enqueued.
  • /my-account/newsletters/?my-account-v2-demo=1 and /donations/?… → bounce to edit-account (the redirect-non-demo guard).
  • /my-account/subscriptions/?… → on a WCS-installed site, WCS' default still renders for non-admins (no demo hijack).
  • /?my-account-v2-demo=1 → homepage renders unchanged (no drawer).
  • /wp-admin/admin.php?page=newspack-audience#/reader-account-customization → non-admins can't reach the wizard at all (admin caps gate the whole thing).

Doc trio for deeper dives

  • 📄 Brief — the spec (goal, scope, component mapping, fake-data shape, phasing through Phase 10, definition of done).
  • 📝 Devlog — per-phase entries (What I built / What I learned / Decisions and why / Open questions) plus the cross-phase decision log spanning every PR below.
  • 🗺️ Guide — architectural map: reader's guide, agent map, productionisation playbook. Swept end-to-end to cover Phase 9, Phase 10, and the post-Phase-8 rebuilds (account settings, payment information rebuild, donation detail rebuild, subscriptions list polish, homepage overlay, Reader Account Customization admin).

Phasing — how this came together

Each phase / polish pass shipped as its own PR into prototype/my-account-demo; this umbrella PR lands the whole prototype into trunk as one merge. Scope grew from the original four primary surfaces to five plus a WP-admin companion, and from six modals to twelve, as design review surfaced gaps the original brief didn't cover.

Phase / pass Scope PR
1 Plumbing — ?my-account-v2-demo flag, body class, asset bundle scaffold Direct commits
2 Newsletters list, newsletters endpoint, auto-flush guard Direct commits
3 Donations list + 4-variant detail, donations endpoint with id-value resolution Direct commits
4 Subscriptions list + 5-variant detail, WCS endpoint takeover, Change subscription modal pulled forward from Phase 5 #4680
5 Five remaining modals, snackbar util extraction, action-router pattern #4681
6 Payment methods page (originally WC core's <table> DOM; later rebuilt — see post-Phase-8 row), payment-methods endpoint takeover #4682
7 Scenario machinery, 11 fixtures, polish sweep across Phases 3–6 open questions #4683
8 Documentation pass — docs/my-account-v2-prototype-guide.md #4684
Homepage overlay New surface: right-side drawer on the homepage, sidebar footer link injection, "Back to Homepage" round-trip Direct commits
9 Account settings page — form-edit-account.php swap, stateless form submits, Delete account two-step modal #4688
Newsletters polish Loading states, latent Phase 2 bug fix, denser typography, first scoped SCSS rule, localStorage persistence #4689 + direct commit
Payment information rebuild Phase 6 reversed — page rebuilt onto v1's card-based payment-information.php shell with payment methods + addresses sections + 5 new modals #4690
Donation detail rebuild donation-details.php retro-fitted to the v1-class-names-first reflex it predated; canonical WCS table classes; paidcompleted fake-data status alignment #4691
Subscriptions list polish + expired variant Typography migration, outer stack gap-9gap-11, __separator primitive replacing | glyph, sidebar relabel, expired variant wired (badge + Renew + modal) #4692
10 Reader Account Customization admin tab — first v2 surface in WP-admin (Audience wizard); pure-demo React state, three-section Branding / Newsletters / Account & Billing layout, Terminology Custom option with singular/plural inputs #4693
Doc sweep Brief + Guide brought up to date for Phase 9 + Phase 10 + the post-Phase-8 rebuilds This PR
Scope guardrails (still true at merge)
  • Admin-only. Every callback short-circuits when is_demo_active() returns false. The homepage overlay has a parallel is_homepage_demo_active() gate. The WP-admin companion lives behind the existing Audience wizard's admin caps.
  • Body-class scoped (on the my-account/ surface). All v2-demo markup hangs under .newspack-my-account-v2-demo; the homepage overlay uses its own .newspack-my-account-v2-demo-homepage scope. The dedicated style.scss is intentionally minimal — most of the surface area lives on newspack-ui primitives and v1 class names. The handful of scoped rules that exist are each documented inline with a "why" callout pointing back to the brief reflexes.
  • Stateless. Every Modify / Cancel / Renew / Restart / Subscribe / Unsubscribe / Delete / Make-default / Save / Edit is client-side: snackbar + DOM mutation. Newsletters row state persists via localStorage only (productionisation removes that layer entirely). The WP-admin companion is local React state only.
  • No production behaviour change. Non-demo readers see v1 unchanged; the prototype's new endpoints (newsletters, donations) ship redirect-non-demo guards so guessable URLs bounce non-admins to edit-account. Subscriptions on WCS-installed sites still render WCS' default for non-admin readers.
Productionisation — what's needed before this becomes the real My Account

Productionising the prototype into v1 is a separate workstream, not a follow-up to this PR. The Guide § Productionisation playbook is the to-do list when that work is scoped: replace fake-data slices with real WC/WCS/ESP queries, wire real Stripe on every modal form, scrub the remove_all_actions sledgehammers (subscriptions, payment-methods, newsletters) down to handler-name-keyed removals, drop the ?my-account-v2-demo gate + body-class scope + auto-flush plumbing + menu-item conditional + homepage drawer gate, productionise the WP-admin companion (real persistence, wire Custom terminology through to v2 templates), and pick up deferred design-system work.

Carryover items not blocking the prototype:

  • CANCELLED / EXPIRED badge saturation__badge--error is lighter than Figma; right fix is a __badge--error-strong addition to _badge.scss. Touches the shared design system → separate PR with design sign-off.
  • Detail-page kv-table densityorder_details + subscription_details cell padding renders ~56px row height vs Figma's ~32px row pitch. Shared by donation + subscription detail pages.
  • __separator primitive promotion — Subscriptions list polish introduced a prototype-local vertical-hairline. If a third caller appears in v1 it should graduate to _dividers.scss.
  • Optional ?my-account-v2-demo=multi-sub scenario — supported trivially; shipping is a stakeholder-review call.
  • No "Subscription details — expired" Figma frame — the wired EXPIRED variant mirrors cancelled; a dedicated frame would let us confirm whether copy / structure should diverge.
  • "Add new payment method" duplicate CTA in Figma's Edit/Add modals — treated as a Figma artifact for now.
  • Real edit-account / password reset parity — Phase 9 collapses v1's "Create a password" / "Reset password" branches into a single Current/New form; productionisation should decide whether to surface the magic-link flow.
  • Custom terminology pluralisation rules — Phase 10's two-input shape (singular + plural) handles simple cases but not languages with three plural categories. Productionisation decides whether to expose a third "many" form.

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? — N/A (admin-gated demo prototype, fake data only, stateless mutations).
  • Have you successfully ran tests with your changes locally?

Phase 1 plumbing for the My Account v2 prototype. Adds a new
`Newspack\My_Account_UI_V2_Demo` class that gates a stub on
`is_account_page()` + admin + `?v2-demo`, sets a scoped body class,
enqueues a dedicated webpack bundle (`my-account-v2-demo`), and
short-circuits to a no-op for everyone else. Loaded after the v1
class so v1's filters register first.

Bundles in `src/my-account/v2-demo/{index.js,style.scss}`. SCSS is
intentionally empty under the `.newspack-my-account--v2-demo` scope
— newspack-ui primitives drive the visuals in later phases.

Brief and dev log live under `docs/my-account-v2-prototype-*.md`.
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 introduces Phase 1 “plumbing” for an admin-only My Account v2 prototype demo gate, activated by the ?v2-demo query flag on WooCommerce /my-account/ URLs, without changing behavior for non-admins or requests without the flag.

Changes:

  • Adds a new webpack entry + stub JS/SCSS bundle for my-account-v2-demo.
  • Loads a new PHP gate class that (when active) adds a scoped body class, enqueues the v2-demo bundle, and renders a simple “hello” stub in the My Account content.
  • Adds initial prototype brief + devlog documentation.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
webpack.config.js Registers the new my-account-v2-demo build entry.
src/my-account/v2-demo/index.js Adds minimal v2-demo entrypoint (public-path + scoped stylesheet + verification log).
src/my-account/v2-demo/style.scss Adds an empty, fully-scoped styling wrapper for demo isolation.
includes/plugins/woocommerce/my-account/class-woocommerce-my-account.php Includes the v2-demo gate class after v1 in the v1 branch.
includes/plugins/woocommerce/my-account/class-my-account-ui-v2-demo.php Implements the admin-only ?v2-demo gate (query var/body class/assets/stub render).
docs/my-account-v2-prototype-devlog.md Adds a devlog template + Phase 1 entry.
docs/my-account-v2-prototype-brief.md Adds the detailed design/dev brief for the prototype phases.

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

Comment thread includes/plugins/woocommerce/my-account/class-woocommerce-my-account.php Outdated
Comment thread docs/my-account-v2-prototype-brief.md Outdated
Address Copilot review on #4679:

- Inline comment in class-woocommerce-my-account.php now reads as
  forward-tense ("later phases re-filter…") rather than implying
  Phase 1 already does the filter override work.
- Brief §4 now points at class-woocommerce-my-account.php for the
  include location, matching §10 Step 3.
Captures the sync conclusions that aren't otherwise in the brief
or the code: auto-flush guard strategy, single-PR delivery,
prototype-removal cleanup obligations, and the Phase 2 deferral
of the login-redirect query-string strip.
@thomasguillot thomasguillot changed the title feat(my-account): scaffold v2 prototype demo gate behind ?v2-demo flag feat(my-account): v2 prototype — gate + Newsletters list (Phases 1–2) Apr 28, 2026
@thomasguillot thomasguillot requested a review from Copilot April 28, 2026 10:55
Replaces the Phase 1 stub with the real Newsletters surface — grouped
sections, frequency badges, optional SUBSCRIBER-ONLY badges, and
client-side optimistic Sign up / Unsubscribe flow with snackbar
confirmations. Built entirely from newspack-ui primitives, gated on
?v2-demo and admin capability so non-admins see v1 unchanged.

- Register `newsletters` rewrite endpoint with the option-keyed
  auto-flush guard from the cross-phase decision log; bump
  ENDPOINTS_VERSION to 2.
- Hook `woocommerce_account_newsletters_endpoint` to render the v2
  template via load_template; skip wc_get_template since
  myaccount/newsletters.php isn't a real WC template path.
- v2-only "Newsletters" menu item via woocommerce_account_menu_items
  at priority 1100 (after v1's 1001).
- Preserve ?v2-demo on every internal nav link via
  woocommerce_get_endpoint_url filter, closing the Phase 1
  login-redirect query-string-strip open question.
- PHP fake data on the class as get_fake_data(), shipped to JS via
  wp_localize_script and to templates by passing into load_template.
- No scoped CSS — row layout composes from nested __stack
  (horizontal + vertical), --justify-between for left/right pinning,
  <img width height> attrs for thumbnail size, and <hr> between
  vertical-stack siblings for the hairline separator. style.scss
  stays wrapper-only.
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

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.


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

Comment thread docs/my-account-v2-prototype-brief.md Outdated
Comment thread src/my-account/v2-demo/newsletters.js Outdated
Comment thread includes/plugins/woocommerce/my-account/class-my-account-ui-v2-demo.php Outdated
Comment thread includes/plugins/woocommerce/my-account/class-my-account-ui-v2-demo.php Outdated
- Render snackbar markup directly with setTimeout cleanup instead of
  routing through newspackUI.notices.openNotice — the latter calls
  closeNotice on dismiss, which always sends an admin-ajax dismissal
  using a server-issued nonce we don't have, producing a 403 on every
  toast.
- Redirect non-demo visitors hitting /my-account/newsletters/ to
  /my-account/edit-account/ via template_redirect at priority 9 so
  they never land on an empty account body. Use get_query_var(),
  not is_wc_endpoint_url() (which only matches WC's hardcoded list).
- Enqueue the JS bundle using deps from dist/my-account-v2-demo.asset.php
  so @wordpress/i18n is loaded automatically. Matches the canonical
  pattern used elsewhere in this repo (e.g. trait-content-gate-layout).
- Drop role="list" / role="listitem" from the newsletters template —
  <hr> separators between rows would break ARIA list semantics, and
  we're not actually conveying list semantics with <div>/<button>
  children. Visual grouping is enough.
- Update the brief: bump picsum reference from 128×128 to 144×144 to
  match the retina rationale, and correct the §6 mapping-table row
  for SUBSCRIBER-ONLY (Figma uses --secondary, not --outline).
Adds the Donations list and detail surfaces to the My Account v2 prototype,
gated behind ?v2-demo. Registers a `donations` rewrite endpoint with a value
parameter (`/my-account/donations/<id>/`), bumps ENDPOINTS_VERSION to 3 to
re-trigger the auto-flush guard, and renders both list (recurring +
previous + billing-history button) and detail (recurring active /
cancelled, one-time, no-fees) variants from pure newspack-ui composition.
See docs/my-account-v2-prototype-devlog.md.
@thomasguillot thomasguillot changed the title feat(my-account): v2 prototype — gate + Newsletters list (Phases 1–2) feat(my-account): v2 prototype — gate + Newsletters + Donations (Phases 1–3) Apr 28, 2026
@thomasguillot thomasguillot requested a review from Copilot April 28, 2026 12:04
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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.


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

Comment thread includes/plugins/woocommerce/my-account/templates/v2-demo/donation-details.php Outdated
Comment thread src/my-account-v2-demo/donations.js
Comment thread src/my-account-v2-demo/donations.js
Comment thread includes/plugins/woocommerce/my-account/class-my-account-ui-v2-demo.php Outdated
Comment thread includes/plugins/woocommerce/my-account/class-my-account-ui-v2-demo.php Outdated
- donation-details: replace remaining inline `style="flex:1"` on date
  rows + payment-method with `__stack--justify-between` (matches the
  Amount section refactor — pure newspack-ui composition).
- donations list: add `tabindex="0"`, `role="link"`, and a descriptive
  `aria-label` to clickable `<tr>`s; wire keyboard activation
  (Enter/Space) in `donations.js` so rows are reachable without a mouse.
- donations.js: wire a stub snackbar for the "Billing history" Button
  Card so the click feels intentional ahead of Phase 6's
  `billing_history_inline` scenario fixture.
- demo-flag preservation: read the existing `$_GET[ self::DEMO_FLAG ]`
  value rather than forcing `'1'`, so navigation keeps the chosen
  scenario (e.g. `?v2-demo=cancelled-sub` per brief §7).
- register_endpoints: gate the flush behind `is_user_logged_in()` +
  `manage_options` so anonymous frontend traffic doesn't pay the
  ~50ms rule-regeneration cost. The first admin to hit any
  /my-account/ page after a deploy triggers it; rules apply for
  everyone after that.
@thomasguillot thomasguillot changed the title feat(my-account): v2 prototype — gate + Newsletters + Donations (Phases 1–3) feat(my-account): v2 prototype Apr 28, 2026
* feat(my-account): build v2 prototype payment methods (Phase 6)

Reproduces WC core's /my-account/payment-methods/ page byte-for-byte under
the ?v2-demo flag, fed by fake data instead of wc_get_customer_saved_methods_list.
Same template_redirect priority-8 takeover pattern Phase 4 uses for
subscriptions: drops both WC core's default renderer and v1's wc_get_template
swap to payment-information.php so the v2 template is the sole handler.

- Adds 'payment-methods' to the v2 sidebar between Subscriptions and the rest
- Bumps ENDPOINTS_VERSION 4 -> 5 to re-fire the auto-flush guard once
- Snackbar-only dispatcher (Make default / Delete / Add new) — no modals

* fix(my-account): address Copilot review on Phase 6
)

* feat(my-account): build v2 prototype scenarios + polish (Phase 7)

Wires the `?v2-demo=<scenario>` mechanism (11 scenarios), retires the
`extras` subscription bucket in favour of a fixture registry, and sweeps
the open-question polish backlog accumulated across Phases 3–6 (hash
fragments, "The News Paper" hardcodes). Adds an inline Expired badge to
the payment-methods table for the `expired-payment` scenario, mirroring
v1's parse-MM/YY-then-emit-badge pattern. Empty scenarios surface a
newspack-ui notice on the donations + subscriptions list pages.

Brief gets a new Phase 8 — Documentation pass (reader's guide,
architectural map, productionisation playbook) so the next person to
touch the prototype has a single guide-shaped doc to start from.

* fix(my-account): address Copilot review on Phase 7

- empty_payment_methods() now returns [] (was [ 'cc' => [] ]) so
  no-payment-methods / empty scenarios surface WC core's "No saved
  methods found." notice instead of an empty-tbody table.
- expired-payment falls back to index 0 when every card is default, so
  the scenario is deterministic regardless of the underlying card mix.
- Expired-badge detection uses date_parse_from_format( 'n/y', … ) with
  parse-error checks, mirroring v1's payment-information template.
  Malformed values (02/ab, 13/27, 00/27, empty) no longer false-positive.
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

Copilot reviewed 42 out of 43 changed files in this pull request and generated 4 comments.


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

Comment thread src/my-account-v2-demo-homepage/style.scss
Comment thread src/my-account/v1/_content.scss
miguelpeixe and others added 6 commits April 30, 2026 16:16
- Homepage overlay close: add visibility:hidden + toggle aria-hidden
  on close so the closed dialog is no longer focusable / discoverable
  by screen readers (was only opacity:0 + pointer-events:none).
- Payment-methods template: ksort the actions array directly instead
  of computing a sorted-but-unused $action_keys variable; matches v1.
- Edit-address modal: pair Town/City (form-row-first) with County
  (form-row-last), promote Post code to form-row-wide so the WC
  float grid stops breaking on first/first/last.
redirect_non_demo_v2_endpoints() previously bounced any non-demo
/my-account/newsletters/ request to /edit-account/, which would
break the real newsletters endpoint on sites that have
newspack-newsletters installed (its Subscription class owns
woocommerce_account_newsletters_endpoint at priority 10).

Mirror the existing WCS guard for /subscriptions/: only redirect
/newsletters/ when no real handler is present, gated by
class_exists( 'Newspack_Newsletters_Subscription' ). Donations
keeps unconditional redirect (no real handler exists outside
this prototype). Subscriptions WCS guard intact.
Bring the guide back in sync with the current implementation:
- edit-account.{php,js} → account-settings.{php,js} (file tree,
  walkthrough, hook table)
- render_homepage_drawer → render_homepage_overlay
- Homepage body class: newspack-my-account--my-account-v2-demo-homepage
  → newspack-my-account-v2-demo-homepage
- Body-class cleanup note: newspack-my-account--my-account-v2-demo
  → newspack-my-account-v2-demo
- Newsletters walkthrough: state now persists via localStorage
  (key newspack-my-account-v2-demo:newsletters), not reset-on-reload
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants