Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions docs/my-account-v2-prototype-brief.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ Before writing any code: clone the repo via `n`, install deps (`npm install` and

## 3. Scope of screens

Three priority surfaces, each with several variant states. Everything else (account settings, delete account, signed-out, email-unverified) is **reused from v1 as-is** for the prototype.
Four priority surfaces, each with several variant states. Everything else (account settings, delete account, signed-out, email-unverified) is **reused from v1 as-is** for the prototype.

**Newsletters** (Figma section `2636:46703`)

Expand Down Expand Up @@ -182,6 +182,10 @@ v1 already extends the WooCommerce Subscriptions endpoint, but the design is bei
- Detail variants: `active`, `active (no fees)`, `cancelled`, `expiring`, `renewed`.
- Modals: `Cancel subscription – Init/Success`, `Renew subscription` and its `Success`, `Change subscription – Init / Monthly selected / Plan selected / Transaction modal`.

**Payment methods** (no Figma — reproduce v1 as-is)

v1 already renders `/my-account/payment-methods/` as a `<table class="shop_table account-payment-methods-table">` of saved cards with action buttons (Make default / Delete) plus an "Add payment method" CTA. The v2 prototype reproduces the exact v1 DOM under the `?v2-demo` flag, fed by fake data instead of real `wc_get_customer_saved_methods_list()` — no new design, no new components. This means v2-demo readers can see and click through the payment-methods experience without needing real WC payment tokens on the demo site. Phase 6 ships this; details in §10 → Phase 6.

Reused from v1 unchanged: account-page page template, sidebar/menu, account settings, delete-account flow, signed-out state.

## 4. The `?v2-demo` mechanism
Expand Down Expand Up @@ -615,11 +619,15 @@ All 5 detail variants. Figma section `2636:46116`. v1 already has a subscription

All six modal flows (cancel donation, modify donation, restart donation, cancel subscription, renew subscription, change subscription) wired to client-side handlers + toast confirmations. All use `Newspack / Modal` → `.newspack-ui__modal*` (see §6).

### Phase 6 — Polish + scenario fixtures (~0.5 day)
### Phase 6 — Payment methods (~1–1.5 days)

Reproduce v1's `/my-account/payment-methods/` surface byte-for-byte under the v2-demo flag, fed entirely by fake data (no real WooCommerce payment-token storage). The v1 page is a saved-cards table backed by `wc_get_account_payment_methods_columns()` + `wc_get_account_payment_methods_types()` plus an "Add payment method" CTA; the v2 prototype renders the same DOM (`<table class="shop_table account-payment-methods-table">` headers, per-row method/expiry/actions cells, default-card badge) so v1's existing styling carries through verbatim. Fake data adds a `payment_methods` slice on `My_Account_UI_V2_Demo::get_fake_data()` (an array of saved cards with brand / last4 / expiry / is_default / actions). Action buttons (Make default / Delete / Add new) wire to client-side stubs that surface snackbars, mirroring the Phase 5 modal-trigger pattern. Sidebar item is added at the same priority as the Phase 1–4 endpoints. No new modals.

### Phase 7 — Polish + scenario fixtures (~0.5 day)

`?v2-demo=<scenario>` overrides for cancelled / expired / empty / no-fees states (see §7). Final screenshot pass against Figma.

**Total estimate:** ~7 dev-days for one engineer, end-to-end clickable on any Newspack site.
**Total estimate:** ~8–8.5 dev-days for one engineer, end-to-end clickable on any Newspack site.

## 11. Working in the open — dev log practice

Expand Down Expand Up @@ -655,7 +663,7 @@ Add links to PRs, commits, and Figma frames. Keep it scannable.
- An admin can append `?v2-demo` (or `?v2-demo=<scenario>`) to any `/my-account/...` URL on any Newspack site and see the prototype rendered.
- A non-admin appending the same URL sees v1 unchanged.
- All visible markup uses `.newspack-ui*` classes. The v2-demo `style.scss` contains the `.newspack-my-account--v2-demo` scoping wrapper and effectively nothing else — open it in PR review and check.
- All four primary screens (dashboard, newsletters, donations, subscriptions) plus all six modals are reachable.
- All five primary screens (dashboard, newsletters, donations, subscriptions, payment methods) plus all six modals are reachable.
- Scenario flag toggles produce visibly different fixtures.
- `npm run lint` and `npm run lint:php` pass.
- The devlog has at least one entry per shipped phase.
Expand Down
78 changes: 75 additions & 3 deletions docs/my-account-v2-prototype-devlog.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,50 @@ class="newspack-ui__button newspack-ui__button--secondary"
</section>
<?php endif; ?>
</div>

<?php
/*
* Phase 5 modal partials — rendered outside the detail-page wrap so the
* dispatcher's click listener (registered on the wrap) doesn't see modal-
* internal clicks. Modify + Cancel render for the active recurring
* variant; Restart for the cancelled recurring variant. Donation reuses
* the shared `tiers.billing` fixture for the Restart transaction step's
* billing readout, since donations don't carry their own billing fixture
* in the fake data and the demo address is the same one the Renew /
* Change subscription modals already render.
*/
$reader = isset( $data['reader'] ) ? $data['reader'] : [];
$reader_email = isset( $reader['email'] ) ? (string) $reader['email'] : '';
$subscriptions_data = isset( $data['subscriptions'] ) ? $data['subscriptions'] : [];
$shared_billing = isset( $subscriptions_data['tiers']['billing'] ) ? $subscriptions_data['tiers']['billing'] : [];

if ( $is_recurring && $is_active ) {
load_template(
__DIR__ . '/partials/modify-donation-modal.php',
false,
[
'donation' => $donation,
'currency_symbol' => $currency_symbol,
]
);
load_template(
__DIR__ . '/partials/cancel-donation-modal.php',
false,
[
'donation' => $donation,
'reader_email' => $reader_email,
]
);
}
if ( $is_recurring && $is_cancelled ) {
load_template(
__DIR__ . '/partials/restart-donation-modal.php',
false,
[
'donation' => $donation,
'billing' => $shared_billing,
'currency_symbol' => $currency_symbol,
]
);
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php
/**
* My Account v2 prototype — Cancel donation modal partial.
*
* Two visual steps:
* - init (Figma 2636:46591) — "Are you sure?" body + destructive
* confirm + ghost "Keep donation".
* - success (Figma 2636:46550) — green-check success box + email-sent
* line + "Done" close button.
*
* Mirrors the cancel-subscription confirmation pattern; only copy + the
* resource keying differ.
*
* @package Newspack
* @var array $args Template args; expected keys:
* - `donation` => the donation row (id).
* - `reader_email` => email surfaced in the success copy.
*/

defined( 'ABSPATH' ) || exit;

$donation = isset( $args['donation'] ) ? $args['donation'] : [];
$reader_email = isset( $args['reader_email'] ) ? (string) $args['reader_email'] : '';
$donation_id = isset( $donation['id'] ) ? (string) $donation['id'] : '';
?>
<div
id="newspack-my-account__cancel-donation-<?php echo esc_attr( $donation_id ); ?>"
class="newspack-ui newspack-ui__modal-container newspack-my-account__v2-demo-cancel-donation"
data-state="closed"
data-newspack-my-account-v2-demo="cancel-donation-modal"
data-donation-id="<?php echo esc_attr( $donation_id ); ?>"
>
<div class="newspack-ui__modal-container__overlay"></div>
<div class="newspack-ui__modal newspack-ui__modal--small">
<header class="newspack-ui__modal__header">
<h2><?php esc_html_e( 'Cancel donation', 'newspack-plugin' ); ?></h2>
<button class="newspack-ui__button newspack-ui__button--icon newspack-ui__button--ghost newspack-ui__modal__close" type="button">
<span class="screen-reader-text"><?php esc_html_e( 'Close', 'newspack-plugin' ); ?></span>
<?php \Newspack\Newspack_UI_Icons::print_svg( 'close' ); ?>
</button>
</header>

<div class="newspack-ui__modal__content" data-step="init">
<h3><?php esc_html_e( 'Are you sure?', 'newspack-plugin' ); ?></h3>
<p><?php esc_html_e( 'We appreciate your generous support, even if you can no longer donate at this time.', 'newspack-plugin' ); ?></p>

<button
type="button"
class="newspack-ui__button newspack-ui__button--primary newspack-ui__button--destructive newspack-ui__button--wide"
data-action="confirm"
>
<?php esc_html_e( 'Cancel donation', 'newspack-plugin' ); ?>
</button>
<button type="button" class="newspack-ui__button newspack-ui__button--ghost newspack-ui__button--wide newspack-ui__modal__close">
<?php esc_html_e( 'Keep donation', 'newspack-plugin' ); ?>
</button>
</div>

<div class="newspack-ui__modal__content" data-step="success" hidden>
<div class="newspack-ui__box newspack-ui__box--success newspack-ui__box--text-center">
<span class="newspack-ui__icon newspack-ui__icon--success">
<?php \Newspack\Newspack_UI_Icons::print_svg( 'check' ); ?>
</span>
<p>
<strong><?php esc_html_e( 'Your donation has been successfully cancelled.', 'newspack-plugin' ); ?></strong>
</p>
<?php if ( '' !== $reader_email ) : ?>
<p>
<?php
echo wp_kses(
sprintf(
/* translators: %s: reader email address in <strong>. */
__( 'We have just sent a confirmation email to %s.', 'newspack-plugin' ),
'<strong>' . esc_html( $reader_email ) . '</strong>'
),
[ 'strong' => [] ]
);
?>
</p>
<?php endif; ?>
</div>

<button type="button" class="newspack-ui__button newspack-ui__button--primary newspack-ui__button--wide newspack-ui__modal__close">
<?php esc_html_e( 'Done', 'newspack-plugin' ); ?>
</button>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php
/**
* My Account v2 prototype — Cancel subscription modal partial.
*
* Two visual steps in one modal container:
* - init (Figma 2636:46259) — "Are you sure?" body + destructive
* confirm + ghost "Keep subscription".
* - success (Figma 2636:46262) — green-check success box + email-sent
* line + "Done" close button.
*
* Markup mirrors the v1/newspack-ui modal conventions (per brief §2.1.1):
* `.newspack-ui__modal-container` → overlay → `.newspack-ui__modal--small`
* → `__header` (h2 + close button) → `.newspack-ui__modal__content`. Action
* buttons render directly inside `__content` (NOT `__footer`, which has the
* grey neutral-5 background that clashes with the design — same call as
* Phase 4's change-subscription modal). Success state uses
* `.newspack-ui__box--success.--text-center` + `__icon--success` + check
* SVG, matching the canonical pattern in `class-newspack-ui.php`.
*
* @package Newspack
* @var array $args Template args; expected keys:
* - `subscription` => the subscription row this modal is for
* (id, status, expires_on, next_payment).
* - `reader_email` => email address surfaced in the success
* copy (matches the page-level fake data).
*/

defined( 'ABSPATH' ) || exit;

$subscription = isset( $args['subscription'] ) ? $args['subscription'] : [];
$reader_email = isset( $args['reader_email'] ) ? (string) $args['reader_email'] : '';
$subscription_id = isset( $subscription['id'] ) ? (string) $subscription['id'] : '';

// "active until X" date: prefer next_payment for actively-renewing subs; fall
// back to expires_on for the expiring variant. Either way the source is the
// fake-data fixture, formatted with WP's locale-aware date helper.
$end_iso = '';
if ( ! empty( $subscription['next_payment'] ) ) {
$end_iso = (string) $subscription['next_payment'];
} elseif ( ! empty( $subscription['expires_on'] ) ) {
$end_iso = (string) $subscription['expires_on'];
}
$end_date_label = '';
if ( '' !== $end_iso ) {
$end_ts = strtotime( $end_iso );
$end_date_label = $end_ts ? date_i18n( 'F j, Y', $end_ts ) : $end_iso;
}
?>
<div
id="newspack-my-account__cancel-subscription-<?php echo esc_attr( $subscription_id ); ?>"
class="newspack-ui newspack-ui__modal-container newspack-my-account__v2-demo-cancel-subscription"
data-state="closed"
data-newspack-my-account-v2-demo="cancel-subscription-modal"
data-subscription-id="<?php echo esc_attr( $subscription_id ); ?>"
>
<div class="newspack-ui__modal-container__overlay"></div>
<div class="newspack-ui__modal newspack-ui__modal--small">
<header class="newspack-ui__modal__header">
<h2><?php esc_html_e( 'Cancel subscription', 'newspack-plugin' ); ?></h2>
<button class="newspack-ui__button newspack-ui__button--icon newspack-ui__button--ghost newspack-ui__modal__close" type="button">
<span class="screen-reader-text"><?php esc_html_e( 'Close', 'newspack-plugin' ); ?></span>
<?php \Newspack\Newspack_UI_Icons::print_svg( 'close' ); ?>
</button>
</header>

<div class="newspack-ui__modal__content" data-step="init">
<h3><?php esc_html_e( 'Are you sure?', 'newspack-plugin' ); ?></h3>
<?php if ( '' !== $end_date_label ) : ?>
<p>
<?php
echo wp_kses(
sprintf(
/* translators: %s: end-of-access date in <strong>. */
__( 'If you cancel now, your subscription will remain active until %s.', 'newspack-plugin' ),
'<strong>' . esc_html( $end_date_label ) . '</strong>'
),
[ 'strong' => [] ]
);
?>
</p>
<?php endif; ?>
<p><?php esc_html_e( 'After this, your subscription access will end unless you choose to renew.', 'newspack-plugin' ); ?></p>

<button
type="button"
class="newspack-ui__button newspack-ui__button--primary newspack-ui__button--destructive newspack-ui__button--wide"
data-action="confirm"
>
<?php esc_html_e( 'Cancel subscription', 'newspack-plugin' ); ?>
</button>
<button type="button" class="newspack-ui__button newspack-ui__button--ghost newspack-ui__button--wide newspack-ui__modal__close">
<?php esc_html_e( 'Keep subscription', 'newspack-plugin' ); ?>
</button>
</div>

<div class="newspack-ui__modal__content" data-step="success" hidden>
<div class="newspack-ui__box newspack-ui__box--success newspack-ui__box--text-center">
<span class="newspack-ui__icon newspack-ui__icon--success">
<?php \Newspack\Newspack_UI_Icons::print_svg( 'check' ); ?>
</span>
<p>
<strong><?php esc_html_e( 'Your subscription has been successfully cancelled.', 'newspack-plugin' ); ?></strong>
</p>
<?php if ( '' !== $reader_email ) : ?>
<p>
<?php
echo wp_kses(
sprintf(
/* translators: %s: reader email address in <strong>. */
__( 'We have just sent a confirmation email to %s.', 'newspack-plugin' ),
'<strong>' . esc_html( $reader_email ) . '</strong>'
),
[ 'strong' => [] ]
);
?>
</p>
<?php endif; ?>
</div>

<button type="button" class="newspack-ui__button newspack-ui__button--primary newspack-ui__button--wide newspack-ui__modal__close">
<?php esc_html_e( 'Done', 'newspack-plugin' ); ?>
</button>
</div>
</div>
</div>
Loading
Loading