Skip to content

Fix completion-screen override handling (blank button + uninterpolated {tokens}) - #157

Open
gcutrini wants to merge 2 commits into
mainfrom
fix/purchase-complete-copy
Open

Fix completion-screen override handling (blank button + uninterpolated {tokens})#157
gcutrini wants to merge 2 commits into
mainfrom
fix/purchase-complete-copy

Conversation

@gcutrini

@gcutrini gcutrini commented Aug 24, 2026

Copy link
Copy Markdown
Member

ref: https://app.clickup.com/t/86bbm1pzq

Problem

On the purchase-complete screen, marketing overrides were mishandled two ways:

  1. Blank button — a button/title override passed as a present-but-undefined prop
    passed the !isEmptyString(...) guard (isEmptyString only treated strings as
    empty), so the order-complete button rendered with no text.
  2. Uninterpolated tokens — an override paragraph was inserted verbatim, so
    {attendee}/{adv}/{button} tokens in custom copy printed literally, while the
    built-in i18n strings interpolated them.

Fix

  • isEmptyString now treats null/undefined as empty, so every override guard
    (both buttons + title) falls back to its default. Redundant typeof checks removed.
  • New interpolate() helper; override paragraphs run through it with the same
    {attendee}/{adv}/{button} values the defaults use.

Tests

  • Unit tests for isEmptyString (null/undefined/whitespace) and interpolate.
  • Regression tests: undefined button prop falls back to the label; {button} in an
    override paragraph resolves.

Two problems on the completion screen when marketing overrides are set:

- A button/title override passed as a present-but-undefined prop slipped
  through the `!isEmptyString(...)` guard, because isEmptyString only
  treated strings as empty. The order-complete button then rendered
  blank. isEmptyString now treats null/undefined as empty, so the button
  and title overrides fall back to their translated defaults; the
  redundant `typeof !== 'undefined'` checks are removed.

- An override paragraph was inserted verbatim, so {attendee}/{adv}/{button}
  tokens in custom copy printed literally. Add an interpolate() helper and
  run the override paragraphs through it with the same values the built-in
  strings use.

Adds unit tests for isEmptyString and interpolate, plus regression tests
for the blank button and the paragraph interpolation.
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 395b73df-c4fa-4378-a5de-44e2d361b550


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/utils/utils.js
// Replaces {token} placeholders in a template string with values from `vars`.
// Used so marketing-override copy supports the same {attendee}/{adv}/{button}
// tokens the built-in i18n strings do. Unknown tokens are left untouched.
export const interpolate = (template, vars = {}) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe you can avoid looping over the template over and over again with something like this:

const TOKEN = /\{(\w+)\}/g;
export const interpolate = (template, vars = {}) => {
    if (typeof template !== 'string') return template;
    return template.replace(TOKEN, (match, key) =>
        key in vars ? String(vars[key]) : match
    );
};```

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done in 8acd6e6, thanks. Single regex pass now.

It also fixes a bug: with the old loop, a value containing a {token} got expanded by the next pass. Added a test for it.

@santipalenque

Copy link
Copy Markdown
Contributor

@gcutrini @smarcet where should I log the review time for these PRs ?

@smarcet

smarcet commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

@gcutrini @smarcet where should I log the review time for these PRs ?

in the ticket provided by the PR
@gcutrini a PR should be submitted with a ref: header otherwise it will be not approved

Replace the per-variable split/join loop with one regex pass. A value
that contains a {token} is now inserted as written, not expanded again.
@gcutrini
gcutrini requested a review from santipalenque August 25, 2026 15:43
@gcutrini

Copy link
Copy Markdown
Member Author

@smarcet all my open PRs have the ref: header now, each one pointing to its ClickUp ticket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants