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:
parent
42a1630740
commit
83c736cc2c
6 changed files with 137 additions and 1 deletions
|
@ -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 {};
|
||||
}
|
||||
|
|
11
apps/portal/src/components/pages/SupportError.js
Normal file
11
apps/portal/src/components/pages/SupportError.js
Normal 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;
|
57
apps/portal/src/components/pages/SupportPage.js
Normal file
57
apps/portal/src/components/pages/SupportPage.js
Normal 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;
|
9
apps/portal/src/components/pages/SupportSuccess.js
Normal file
9
apps/portal/src/components/pages/SupportSuccess.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
const SupportSuccess = () => {
|
||||
const message = 'Thank you for your support!';
|
||||
|
||||
return (
|
||||
<div>{message}</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupportSuccess;
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue