mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Added first version for offer redirects
refs https://github.com/TryGhost/Team/issues/1086 - fires stripe checkout for new Portal link for offers - `/#/portal/offers/OFFER_ID` as prototype
This commit is contained in:
parent
170e353b91
commit
63ca3a00f3
3 changed files with 33 additions and 8 deletions
|
@ -10,7 +10,7 @@ import * as Fixtures from './utils/fixtures';
|
||||||
import ActionHandler from './actions';
|
import ActionHandler from './actions';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import NotificationParser from './utils/notifications';
|
import NotificationParser from './utils/notifications';
|
||||||
import {createPopupNotification, getCurrencySymbol, getFirstpromoterId, getProductFromId, getQueryPrice, getSiteDomain, isComplimentaryMember, isInviteOnlySite, isSentryEventAllowed, removePortalLinkFromUrl} from './utils/helpers';
|
import {createPopupNotification, getAvailablePrices, getCurrencySymbol, getFirstpromoterId, getProductFromId, getQueryPrice, getSiteDomain, isComplimentaryMember, isInviteOnlySite, isSentryEventAllowed, removePortalLinkFromUrl} from './utils/helpers';
|
||||||
|
|
||||||
const handleDataAttributes = require('./data-attributes');
|
const handleDataAttributes = require('./data-attributes');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
@ -335,6 +335,7 @@ export default class App extends React.Component {
|
||||||
fetchLinkData() {
|
fetchLinkData() {
|
||||||
const productMonthlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
const productMonthlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
||||||
const productYearlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
const productYearlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
||||||
|
const offersRegex = /^offers\/(\w+?)\/?$/;
|
||||||
const [path] = window.location.hash.substr(1).split('?');
|
const [path] = window.location.hash.substr(1).split('?');
|
||||||
const linkRegex = /^\/portal\/?(?:\/(\w+(?:\/\w+)*))?\/?$/;
|
const linkRegex = /^\/portal\/?(?:\/(\w+(?:\/\w+)*))?\/?$/;
|
||||||
if (path && linkRegex.test(path)) {
|
if (path && linkRegex.test(path)) {
|
||||||
|
@ -344,7 +345,8 @@ export default class App extends React.Component {
|
||||||
const showPopup = (
|
const showPopup = (
|
||||||
['monthly', 'yearly'].includes(pageQuery) ||
|
['monthly', 'yearly'].includes(pageQuery) ||
|
||||||
productMonthlyPriceQueryRegex.test(pageQuery) ||
|
productMonthlyPriceQueryRegex.test(pageQuery) ||
|
||||||
productYearlyPriceQueryRegex.test(pageQuery)
|
productYearlyPriceQueryRegex.test(pageQuery) ||
|
||||||
|
offersRegex.test(pageQuery)
|
||||||
) ? false : true;
|
) ? false : true;
|
||||||
return {
|
return {
|
||||||
showPopup,
|
showPopup,
|
||||||
|
@ -515,12 +517,28 @@ export default class App extends React.Component {
|
||||||
this.setState(updatedState);
|
this.setState(updatedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleOfferQuery({site, offerId}) {
|
||||||
|
removePortalLinkFromUrl();
|
||||||
|
const prices = getAvailablePrices({site});
|
||||||
|
const priceId = prices?.[0]?.id;
|
||||||
|
if (this.state.member) {
|
||||||
|
this.dispatchAction('checkoutPlan', {plan: priceId, offerId});
|
||||||
|
} else {
|
||||||
|
this.dispatchAction('signup', {plan: priceId, offerId});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Handle direct signup link for a price */
|
/** Handle direct signup link for a price */
|
||||||
handleSignupQuery({site, pageQuery}) {
|
handleSignupQuery({site, pageQuery}) {
|
||||||
const productMonthlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
const productMonthlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
||||||
const productYearlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
const productYearlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
|
||||||
|
const offerQueryRegex = /^offers\/(\w+?)\/?$/;
|
||||||
let priceId = pageQuery;
|
let priceId = pageQuery;
|
||||||
if (productMonthlyPriceQueryRegex.test(pageQuery || '')) {
|
if (offerQueryRegex.test(pageQuery || '')) {
|
||||||
|
const [, offerId] = pageQuery.match(offerQueryRegex);
|
||||||
|
this.handleOfferQuery({site, offerId});
|
||||||
|
return;
|
||||||
|
} else if (productMonthlyPriceQueryRegex.test(pageQuery || '')) {
|
||||||
const [, productId] = pageQuery.match(productMonthlyPriceQueryRegex);
|
const [, productId] = pageQuery.match(productMonthlyPriceQueryRegex);
|
||||||
const product = getProductFromId({site, productId});
|
const product = getProductFromId({site, productId});
|
||||||
priceId = product?.monthlyPrice?.id;
|
priceId = product?.monthlyPrice?.id;
|
||||||
|
@ -544,7 +562,12 @@ export default class App extends React.Component {
|
||||||
const customPricesSignupRegex = /^signup\/?(?:\/(\w+?))?\/?$/;
|
const customPricesSignupRegex = /^signup\/?(?:\/(\w+?))?\/?$/;
|
||||||
const customMonthlyProductSignup = /^signup\/?(?:\/(\w+?))\/monthly\/?$/;
|
const customMonthlyProductSignup = /^signup\/?(?:\/(\w+?))\/monthly\/?$/;
|
||||||
const customYearlyProductSignup = /^signup\/?(?:\/(\w+?))\/yearly\/?$/;
|
const customYearlyProductSignup = /^signup\/?(?:\/(\w+?))\/yearly\/?$/;
|
||||||
if (path === 'signup') {
|
const customOfferRegex = /^offers\/(\w+?)\/?$/;
|
||||||
|
if (customOfferRegex.test(path)) {
|
||||||
|
return {
|
||||||
|
pageQuery: path
|
||||||
|
};
|
||||||
|
} else if (path === 'signup') {
|
||||||
return {
|
return {
|
||||||
page: 'signup'
|
page: 'signup'
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,11 +93,11 @@ async function signin({data, api, state}) {
|
||||||
|
|
||||||
async function signup({data, state, api}) {
|
async function signup({data, state, api}) {
|
||||||
try {
|
try {
|
||||||
const {plan, email, name} = data;
|
const {plan, email, name, offerId} = data;
|
||||||
if (plan.toLowerCase() === 'free') {
|
if (plan.toLowerCase() === 'free') {
|
||||||
await api.member.sendMagicLink(data);
|
await api.member.sendMagicLink(data);
|
||||||
} else {
|
} else {
|
||||||
await api.member.checkoutPlan({plan, email, name});
|
await api.member.checkoutPlan({plan, email, name, offerId});
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
page: 'magiclink',
|
page: 'magiclink',
|
||||||
|
@ -116,9 +116,10 @@ async function signup({data, state, api}) {
|
||||||
|
|
||||||
async function checkoutPlan({data, state, api}) {
|
async function checkoutPlan({data, state, api}) {
|
||||||
try {
|
try {
|
||||||
const {plan} = data;
|
const {plan, offerId} = data;
|
||||||
await api.member.checkoutPlan({
|
await api.member.checkoutPlan({
|
||||||
plan,
|
plan,
|
||||||
|
offerId,
|
||||||
metadata: {
|
metadata: {
|
||||||
checkoutType: 'upgrade'
|
checkoutType: 'upgrade'
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ function setupGhostApi({siteUrl = window.location.origin}) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async checkoutPlan({plan, cancelUrl, successUrl, email: customerEmail, name, metadata = {}} = {}) {
|
async checkoutPlan({plan, cancelUrl, successUrl, email: customerEmail, name, offerId, metadata = {}} = {}) {
|
||||||
const siteUrlObj = new URL(siteUrl);
|
const siteUrlObj = new URL(siteUrl);
|
||||||
const identity = await api.member.identity();
|
const identity = await api.member.identity();
|
||||||
const url = endpointFor({type: 'members', resource: 'create-stripe-checkout-session'});
|
const url = endpointFor({type: 'members', resource: 'create-stripe-checkout-session'});
|
||||||
|
@ -229,6 +229,7 @@ function setupGhostApi({siteUrl = window.location.origin}) {
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
priceId: plan,
|
priceId: plan,
|
||||||
|
offerId,
|
||||||
identity: identity,
|
identity: identity,
|
||||||
metadata: metadataObj,
|
metadata: metadataObj,
|
||||||
successUrl,
|
successUrl,
|
||||||
|
|
Loading…
Add table
Reference in a new issue