0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-04 02:01:58 -05:00

Added support pages to Portal (#17539)

refs https://github.com/TryGhost/Product/issues/3650

- adds '/support', '/support/success' and 'support/error' pages
- support page calls the '/members/api/create-stripe-checkout-session'
backend endpoint on mount, then renders an error or success page
accordingly
This commit is contained in:
Sag 2023-07-31 15:15:22 +02:00 committed by GitHub
parent 42a1630740
commit 83c736cc2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 137 additions and 1 deletions

View file

@ -780,6 +780,18 @@ export default class App extends React.Component {
return {
page: 'accountEmail'
};
} else if (path === 'support') {
return {
page: 'support'
};
} else if (path === 'support/success') {
return {
page: 'supportSuccess'
};
} else if (path === 'support/error') {
return {
page: 'supportError'
};
}
return {};
}

View file

@ -0,0 +1,11 @@
const SupportError = ({error}) => {
const errorMessage = error || 'There was an error processing your payment. Please try again.';
return (
<div>
{errorMessage}
</div>
);
};
export default SupportError;

View file

@ -0,0 +1,57 @@
import {useEffect, useState, useContext} from 'react';
import SupportError from './SupportError';
import SupportSuccess from './SupportSuccess';
import LoadingPage from './LoadingPage';
import setupGhostApi from '../../utils/api';
import AppContext from '../../AppContext';
const SupportPage = () => {
const {site} = useContext(AppContext);
const [isLoading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function checkoutDonation() {
const siteUrl = window.location.origin;
const currentUrl = siteUrl + window.location.pathname;
const api = setupGhostApi({siteUrl});
const successUrl = `${currentUrl}#/portal/support/success`;
const cancelUrl = `${currentUrl}#/portal/support/error`;
try {
await api.member.checkoutDonation({successUrl, cancelUrl});
} catch (err) {
if (err.message) {
setError(err.message);
} else {
setError('There was an error processing your payment. Please try again.');
}
} finally {
setLoading(false);
}
}
checkoutDonation();
// Do it once
// eslint-disable-next-line
}, []);
if (isLoading) {
const title = `Support ${site.title}`;
return (
<div>
<h1>{title}</h1>
<LoadingPage />
</div>
);
}
if (error) {
return <SupportError error={error} />;
}
return <SupportSuccess />;
};
export default SupportPage;

View file

@ -0,0 +1,9 @@
const SupportSuccess = () => {
const message = 'Thank you for your support!';
return (
<div>{message}</div>
);
};
export default SupportSuccess;

View file

@ -13,6 +13,9 @@ import FeedbackPage from './components/pages/FeedbackPage';
import EmailSuppressedPage from './components/pages/EmailSuppressedPage';
import EmailSuppressionFAQ from './components/pages/EmailSuppressionFAQ';
import EmailReceivingFAQ from './components/pages/EmailReceivingFAQ';
import SupportPage from './components/pages/SupportPage';
import SupportSuccess from './components/pages/SupportSuccess';
import SupportError from './components/pages/SupportError';
/** List of all available pages in Portal, mapped to their UI component
* Any new page added to portal needs to be mapped here
@ -32,7 +35,10 @@ const Pages = {
feedback: FeedbackPage,
emailSuppressed: EmailSuppressedPage,
emailSuppressionFAQ: EmailSuppressionFAQ,
emailReceivingFAQ: EmailReceivingFAQ
emailReceivingFAQ: EmailReceivingFAQ,
support: SupportPage,
supportSuccess: SupportSuccess,
supportError: SupportError
};
/** Return page if valid, fallback to signup */
@ -51,4 +57,8 @@ export const isOfferPage = function ({page}) {
return page.includes('offer');
};
export const isSupportPage = function ({page}) {
return page.includes('support');
};
export default Pages;

View file

@ -397,6 +397,43 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) {
});
},
async checkoutDonation({successUrl, cancelUrl, metadata = {}} = {}) {
const identity = await api.member.identity();
const url = endpointFor({type: 'members', resource: 'create-stripe-checkout-session'});
const metadataObj = {
fp_tid: (window.FPROM || window.$FPROM)?.data?.tid,
urlHistory: getUrlHistory(),
...metadata
};
const body = {
identity: identity,
metadata: metadataObj,
successUrl,
cancelUrl,
type: 'donation'
};
const response = await makeRequest({
url,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
if (!response.ok) {
const errorData = await response.json();
const errorMessage = errorData?.errors?.[0]?.message || 'There was an error processing your payment. Please try again.';
throw new Error(errorMessage);
}
return response.json();
},
async editBilling({successUrl, cancelUrl, subscriptionId} = {}) {
const siteUrlObj = new URL(siteUrl);
const identity = await api.member.identity();