mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Fixed Offers portal preview edge cases (#19124)
no issue - cleaned up offers portal preview. - fixes a few logic errors and potential edge cases and making it easier to maintain.
This commit is contained in:
parent
819ddccc72
commit
41ee387af2
3 changed files with 182 additions and 108 deletions
|
@ -5,7 +5,7 @@ import {getOfferPortalPreviewUrl, offerPortalPreviewUrlTypes} from '../../../../
|
||||||
import {getPaidActiveTiers, useBrowseTiers} from '@tryghost/admin-x-framework/api/tiers';
|
import {getPaidActiveTiers, useBrowseTiers} from '@tryghost/admin-x-framework/api/tiers';
|
||||||
import {getTiersCadences} from '../../../../utils/getTiersCadences';
|
import {getTiersCadences} from '../../../../utils/getTiersCadences';
|
||||||
import {useAddOffer} from '@tryghost/admin-x-framework/api/offers';
|
import {useAddOffer} from '@tryghost/admin-x-framework/api/offers';
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useMemo, useState} from 'react';
|
||||||
import {useForm} from '@tryghost/admin-x-framework/hooks';
|
import {useForm} from '@tryghost/admin-x-framework/hooks';
|
||||||
import {useGlobalData} from '../../../providers/GlobalDataProvider';
|
import {useGlobalData} from '../../../providers/GlobalDataProvider';
|
||||||
import {useModal} from '@ebay/nice-modal-react';
|
import {useModal} from '@ebay/nice-modal-react';
|
||||||
|
@ -45,12 +45,52 @@ const ButtonSelect: React.FC<{type: OfferType, checked: boolean, onClick: () =>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type formStateTypes = {
|
||||||
|
disableBackground?: boolean;
|
||||||
|
name: string;
|
||||||
|
code: {
|
||||||
|
isDirty: boolean;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
displayTitle: {
|
||||||
|
isDirty: boolean;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
displayDescription: string;
|
||||||
|
type: string;
|
||||||
|
cadence: string;
|
||||||
|
amount: number;
|
||||||
|
duration: string;
|
||||||
|
durationInMonths: number;
|
||||||
|
currency: string;
|
||||||
|
status: string;
|
||||||
|
tierId: string;
|
||||||
|
fixedAmount?: number;
|
||||||
|
trialAmount?: number;
|
||||||
|
percentAmount?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateAmount = (formState: formStateTypes): number => {
|
||||||
|
const {fixedAmount = 0, percentAmount = 0, trialAmount = 0, amount = 0} = formState;
|
||||||
|
|
||||||
|
switch (formState.type) {
|
||||||
|
case 'fixed':
|
||||||
|
return fixedAmount * 100;
|
||||||
|
case 'percent':
|
||||||
|
return percentAmount;
|
||||||
|
case 'trial':
|
||||||
|
return trialAmount;
|
||||||
|
default:
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
type SidebarProps = {
|
type SidebarProps = {
|
||||||
tierOptions: SelectOption[];
|
tierOptions: SelectOption[];
|
||||||
handleTierChange: (tier: SelectOption) => void;
|
handleTierChange: (tier: SelectOption) => void;
|
||||||
selectedTier: SelectOption;
|
selectedTier: SelectOption;
|
||||||
overrides: offerPortalPreviewUrlTypes
|
overrides: formStateTypes;
|
||||||
handleTextInput: (e: React.ChangeEvent<HTMLInputElement>, key: keyof offerPortalPreviewUrlTypes) => void;
|
// handleTextInput: (e: React.ChangeEvent<HTMLInputElement>, key: keyof offerPortalPreviewUrlTypes) => void;
|
||||||
amountOptions: SelectOption[];
|
amountOptions: SelectOption[];
|
||||||
typeOptions: OfferType[];
|
typeOptions: OfferType[];
|
||||||
durationOptions: SelectOption[];
|
durationOptions: SelectOption[];
|
||||||
|
@ -59,12 +99,16 @@ type SidebarProps = {
|
||||||
handleAmountTypeChange: (amountType: string) => void;
|
handleAmountTypeChange: (amountType: string) => void;
|
||||||
handleNameInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
handleNameInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
handleTextAreaInput: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
handleTextAreaInput: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
||||||
|
handleDisplayTitleInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
handleAmountInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
handleDurationInMonthsInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
handleCodeInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
handleTierChange,
|
handleTierChange,
|
||||||
selectedTier,
|
selectedTier,
|
||||||
handleTextInput,
|
// handleTextInput,
|
||||||
typeOptions,
|
typeOptions,
|
||||||
durationOptions,
|
durationOptions,
|
||||||
handleTypeChange,
|
handleTypeChange,
|
||||||
|
@ -73,6 +117,10 @@ const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
handleAmountTypeChange,
|
handleAmountTypeChange,
|
||||||
handleNameInput,
|
handleNameInput,
|
||||||
handleTextAreaInput,
|
handleTextAreaInput,
|
||||||
|
handleDisplayTitleInput,
|
||||||
|
handleDurationInMonthsInput,
|
||||||
|
handleAmountInput,
|
||||||
|
handleCodeInput,
|
||||||
amountOptions}) => {
|
amountOptions}) => {
|
||||||
const getFilteredDurationOptions = () => {
|
const getFilteredDurationOptions = () => {
|
||||||
// Check if the selected tier's cadence is 'yearly'
|
// Check if the selected tier's cadence is 'yearly'
|
||||||
|
@ -117,15 +165,15 @@ const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
overrides.type !== 'trial' && <> <div className='relative'>
|
overrides.type !== 'trial' && <> <div className='relative'>
|
||||||
<TextField title='Amount off' type='number' onChange={(e) => {
|
<TextField title='Amount off' type='number' value={overrides.type === 'fixed' ? overrides.fixedAmount?.toString() : overrides.percentAmount?.toString()} onChange={(e) => {
|
||||||
handleTextInput(e, 'discountAmount');
|
handleAmountInput(e);
|
||||||
}} />
|
}} />
|
||||||
<div className='absolute bottom-0 right-1.5 z-10'>
|
<div className='absolute bottom-0 right-1.5 z-10'>
|
||||||
<Select
|
<Select
|
||||||
clearBg={true}
|
clearBg={true}
|
||||||
controlClasses={{menu: 'w-20 right-0'}}
|
controlClasses={{menu: 'w-20 right-0'}}
|
||||||
options={amountOptions}
|
options={amountOptions}
|
||||||
selectedOption={overrides.amountType === 'percent' ? amountOptions[0] : amountOptions[1]}
|
selectedOption={overrides.type === 'percent' ? amountOptions[0] : amountOptions[1]}
|
||||||
onSelect={(e) => {
|
onSelect={(e) => {
|
||||||
handleAmountTypeChange(e?.value || '');
|
handleAmountTypeChange(e?.value || '');
|
||||||
}}
|
}}
|
||||||
|
@ -141,7 +189,7 @@ const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
|
|
||||||
{
|
{
|
||||||
overrides.duration === 'repeating' && <TextField title='Duration in months' type='number' onChange={(e) => {
|
overrides.duration === 'repeating' && <TextField title='Duration in months' type='number' onChange={(e) => {
|
||||||
handleTextInput(e, 'durationInMonths');
|
handleDurationInMonthsInput(e);
|
||||||
}} />
|
}} />
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
@ -149,7 +197,7 @@ const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
|
|
||||||
{
|
{
|
||||||
overrides.type === 'trial' && <TextField title='Trial duration' type='number' value={overrides.trialAmount?.toString()} onChange={(e) => {
|
overrides.type === 'trial' && <TextField title='Trial duration' type='number' value={overrides.trialAmount?.toString()} onChange={(e) => {
|
||||||
handleTextInput(e, 'trialAmount');
|
handleAmountInput(e);
|
||||||
}} />
|
}} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +211,7 @@ const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
title='Display title'
|
title='Display title'
|
||||||
value={overrides.displayTitle.value}
|
value={overrides.displayTitle.value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
handleTextInput(e, 'displayTitle');
|
handleDisplayTitleInput(e);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
|
@ -171,7 +219,7 @@ const Sidebar: React.FC<SidebarProps> = ({tierOptions,
|
||||||
title='Offer code'
|
title='Offer code'
|
||||||
value={overrides.code.value}
|
value={overrides.code.value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
handleTextInput(e, 'code');
|
handleCodeInput(e);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextArea
|
<TextArea
|
||||||
|
@ -226,19 +274,22 @@ const AddOfferModal = () => {
|
||||||
currency: tierCadenceOptions[0]?.value ? parseData(tierCadenceOptions[0]?.value).currency : ''
|
currency: tierCadenceOptions[0]?.value ? parseData(tierCadenceOptions[0]?.value).currency : ''
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const getDiscountAmount = (discount: number, dctype: string) => {
|
|
||||||
if (dctype === 'percent') {
|
// const calculateAmount = useCallback(() => {
|
||||||
return discount.toString();
|
// if (formState.type === 'fixed') {
|
||||||
}
|
// return formState.fixedAmount;
|
||||||
if (dctype === 'fixed') {
|
// } else if (formState.type === 'percent') {
|
||||||
let calcDiscount = discount * 100;
|
// return formState.percentAmount;
|
||||||
return calcDiscount.toString();
|
// } else if (formState.type === 'trial') {
|
||||||
}
|
// return formState.trialAmount;
|
||||||
};
|
// } else {
|
||||||
|
// return formState.amount; // default case
|
||||||
|
// }
|
||||||
|
// }, [f;
|
||||||
|
|
||||||
const {formState, updateForm, handleSave, saveState, okProps} = useForm({
|
const {formState, updateForm, handleSave, saveState, okProps} = useForm({
|
||||||
initialState: {
|
initialState: {
|
||||||
disableBackground: true,
|
disableBackground: false,
|
||||||
name: '',
|
name: '',
|
||||||
code: {
|
code: {
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
|
@ -251,14 +302,15 @@ const AddOfferModal = () => {
|
||||||
displayDescription: '',
|
displayDescription: '',
|
||||||
type: 'percent',
|
type: 'percent',
|
||||||
cadence: selectedTier?.dataset?.period || '',
|
cadence: selectedTier?.dataset?.period || '',
|
||||||
trialAmount: 7,
|
amount: 0,
|
||||||
discountAmount: 0,
|
|
||||||
duration: 'once',
|
duration: 'once',
|
||||||
durationInMonths: 0,
|
durationInMonths: 0,
|
||||||
currency: selectedTier?.dataset?.currency || '',
|
currency: selectedTier?.dataset?.currency || 'USD',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
tierId: selectedTier?.dataset?.id || '',
|
tierId: selectedTier?.dataset?.id || '',
|
||||||
amountType: 'percent'
|
trialAmount: 7,
|
||||||
|
fixedAmount: 0,
|
||||||
|
percentAmount: 0
|
||||||
},
|
},
|
||||||
onSave: async () => {
|
onSave: async () => {
|
||||||
const dataset = {
|
const dataset = {
|
||||||
|
@ -267,7 +319,7 @@ const AddOfferModal = () => {
|
||||||
display_title: formState.displayTitle.value,
|
display_title: formState.displayTitle.value,
|
||||||
display_description: formState.displayDescription,
|
display_description: formState.displayDescription,
|
||||||
cadence: formState.cadence,
|
cadence: formState.cadence,
|
||||||
amount: formState.type === 'trial' ? Number(getDiscountAmount(formState.trialAmount, formState.amountType)) : Number(getDiscountAmount(formState.discountAmount, formState.amountType)),
|
amount: calculateAmount(formState) || 0,
|
||||||
duration: formState.type === 'trial' ? 'trial' : formState.duration,
|
duration: formState.type === 'trial' ? 'trial' : formState.duration,
|
||||||
duration_in_months: Number(formState.durationInMonths),
|
duration_in_months: Number(formState.durationInMonths),
|
||||||
currency: formState.currency,
|
currency: formState.currency,
|
||||||
|
@ -320,39 +372,37 @@ const AddOfferModal = () => {
|
||||||
const handleAmountTypeChange = (amountType: string) => {
|
const handleAmountTypeChange = (amountType: string) => {
|
||||||
updateForm(state => ({
|
updateForm(state => ({
|
||||||
...state,
|
...state,
|
||||||
amountType: amountType,
|
|
||||||
type: amountType === 'percent' ? 'percent' : 'fixed' || state.type
|
type: amountType === 'percent' ? 'percent' : 'fixed' || state.type
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTextInput = (
|
const handleAmountInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
e: React.ChangeEvent<HTMLInputElement>,
|
const target = e.target as HTMLInputElement;
|
||||||
key: keyof offerPortalPreviewUrlTypes
|
|
||||||
) => {
|
|
||||||
const target = e.target as HTMLInputElement | HTMLTextAreaElement;
|
|
||||||
updateForm((state) => {
|
|
||||||
// Extract the current value for the key
|
|
||||||
const currentValue = (state as offerPortalPreviewUrlTypes)[key];
|
|
||||||
// Check if the current value is an object and has 'isDirty' and 'value' properties
|
|
||||||
if (currentValue && typeof currentValue === 'object' && 'isDirty' in currentValue && 'value' in currentValue) {
|
|
||||||
// Determine if the field has been modified
|
|
||||||
|
|
||||||
return {
|
if (formState.type === 'fixed') {
|
||||||
|
updateForm(state => ({
|
||||||
...state,
|
...state,
|
||||||
[key]: {
|
fixedAmount: Number(target.value)
|
||||||
...currentValue,
|
}));
|
||||||
isDirty: true,
|
} else if (formState.type === 'percent') {
|
||||||
value: target.value
|
updateForm(state => ({
|
||||||
}
|
...state,
|
||||||
};
|
percentAmount: Number(target.value)
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
// For simple properties, update the value directly
|
updateForm(state => ({
|
||||||
return {
|
|
||||||
...state,
|
...state,
|
||||||
[key]: target.value
|
amount: Number(target.value)
|
||||||
};
|
}));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const handleDurationInMonthsInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
updateForm(state => ({
|
||||||
|
...state,
|
||||||
|
durationInMonths: Number(target.value)
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNameInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleNameInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
@ -376,6 +426,18 @@ const AddOfferModal = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDisplayTitleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
updateForm(state => ({
|
||||||
|
...state,
|
||||||
|
displayTitle: {
|
||||||
|
...state.displayTitle,
|
||||||
|
isDirty: true,
|
||||||
|
value: target.value
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const handleTextAreaInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleTextAreaInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
const target = e.target as HTMLTextAreaElement;
|
const target = e.target as HTMLTextAreaElement;
|
||||||
updateForm(state => ({
|
updateForm(state => ({
|
||||||
|
@ -391,6 +453,18 @@ const AddOfferModal = () => {
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCodeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
updateForm(state => ({
|
||||||
|
...state,
|
||||||
|
code: {
|
||||||
|
...state.code,
|
||||||
|
isDirty: true,
|
||||||
|
value: target.value
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasOffers) {
|
if (!hasOffers) {
|
||||||
modal.remove();
|
modal.remove();
|
||||||
|
@ -402,19 +476,54 @@ const AddOfferModal = () => {
|
||||||
updateRoute('offers/edit');
|
updateRoute('offers/edit');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const overrides : offerPortalPreviewUrlTypes = {
|
||||||
|
// name: formState.name,
|
||||||
|
// code: formState.code.value,
|
||||||
|
// displayTitle: formState.displayTitle.value,
|
||||||
|
// displayDescription: formState.displayDescription,
|
||||||
|
// type: formState.type,
|
||||||
|
// cadence: formState.cadence,
|
||||||
|
// amount: calculateAmount(),
|
||||||
|
// duration: formState.type === 'trial' ? 'trial' : formState.duration,
|
||||||
|
// durationInMonths: formState.durationInMonths,
|
||||||
|
// currency: formState.currency,
|
||||||
|
// status: formState.status,
|
||||||
|
// tierId: formState.tierId
|
||||||
|
// };
|
||||||
|
|
||||||
|
const overrides : offerPortalPreviewUrlTypes = useMemo(() => {
|
||||||
|
return {
|
||||||
|
name: formState.name,
|
||||||
|
code: formState.code.value,
|
||||||
|
displayTitle: formState.displayTitle.value,
|
||||||
|
displayDescription: formState.displayDescription,
|
||||||
|
type: formState.type,
|
||||||
|
cadence: formState.cadence,
|
||||||
|
amount: calculateAmount(formState) || 0,
|
||||||
|
duration: formState.type === 'trial' ? 'trial' : formState.duration,
|
||||||
|
durationInMonths: formState.durationInMonths,
|
||||||
|
currency: formState.currency,
|
||||||
|
status: formState.status,
|
||||||
|
tierId: formState.tierId
|
||||||
|
};
|
||||||
|
}, [formState]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newHref = getOfferPortalPreviewUrl(formState, siteData.url);
|
const newHref = getOfferPortalPreviewUrl(overrides, siteData.url);
|
||||||
setHref(newHref);
|
setHref(newHref);
|
||||||
}, [formState, siteData.url]);
|
}, [formState, siteData.url, formState.type, overrides]);
|
||||||
|
|
||||||
const sidebar = <Sidebar
|
const sidebar = <Sidebar
|
||||||
amountOptions={amountOptions as SelectOption[]}
|
amountOptions={amountOptions as SelectOption[]}
|
||||||
durationOptions={durationOptions}
|
durationOptions={durationOptions}
|
||||||
|
handleAmountInput={handleAmountInput}
|
||||||
handleAmountTypeChange={handleAmountTypeChange}
|
handleAmountTypeChange={handleAmountTypeChange}
|
||||||
|
handleCodeInput={handleCodeInput}
|
||||||
|
handleDisplayTitleInput={handleDisplayTitleInput}
|
||||||
handleDurationChange={handleDurationChange}
|
handleDurationChange={handleDurationChange}
|
||||||
|
handleDurationInMonthsInput={handleDurationInMonthsInput}
|
||||||
handleNameInput={handleNameInput}
|
handleNameInput={handleNameInput}
|
||||||
handleTextAreaInput={handleTextAreaInput}
|
handleTextAreaInput={handleTextAreaInput}
|
||||||
handleTextInput={handleTextInput}
|
|
||||||
handleTierChange={handleTierChange}
|
handleTierChange={handleTierChange}
|
||||||
handleTypeChange={handleTypeChange}
|
handleTypeChange={handleTypeChange}
|
||||||
overrides={formState}
|
overrides={formState}
|
||||||
|
|
|
@ -237,23 +237,17 @@ const EditOfferModal: React.FC<{id: string}> = ({id}) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dataset : offerPortalPreviewUrlTypes = {
|
const dataset : offerPortalPreviewUrlTypes = {
|
||||||
name: formState?.name || '',
|
name: formState?.name || '',
|
||||||
code: {
|
code: formState?.code || '',
|
||||||
value: formState?.code || ''
|
displayTitle: formState?.display_title || '',
|
||||||
},
|
|
||||||
displayTitle: {
|
|
||||||
value: formState?.display_title || ''
|
|
||||||
},
|
|
||||||
displayDescription: formState?.display_description || '',
|
displayDescription: formState?.display_description || '',
|
||||||
type: formState?.type || '',
|
type: formState?.type || '',
|
||||||
cadence: formState?.cadence || '',
|
cadence: formState?.cadence || '',
|
||||||
trialAmount: formState?.amount,
|
amount: formState?.amount,
|
||||||
discountAmount: formState?.amount,
|
|
||||||
duration: formState?.duration || '',
|
duration: formState?.duration || '',
|
||||||
durationInMonths: formState?.duration_in_months || 0,
|
durationInMonths: formState?.duration_in_months || 0,
|
||||||
currency: formState?.currency || '',
|
currency: formState?.currency || '',
|
||||||
status: formState?.status || '',
|
status: formState?.status || '',
|
||||||
tierId: formState?.tier.id || '',
|
tierId: formState?.tier.id || ''
|
||||||
amountType: formState?.type === 'percent' ? 'percent' : 'amount'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const newHref = getOfferPortalPreviewUrl(dataset, siteData.url);
|
const newHref = getOfferPortalPreviewUrl(dataset, siteData.url);
|
||||||
|
|
|
@ -1,46 +1,29 @@
|
||||||
export type offerPortalPreviewUrlTypes = {
|
export type offerPortalPreviewUrlTypes = {
|
||||||
disableBackground?: boolean;
|
disableBackground?: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
code: {
|
code: string;
|
||||||
isDirty?: boolean;
|
displayTitle: string;
|
||||||
value: string;
|
displayDescription: string;
|
||||||
}
|
|
||||||
displayTitle: {
|
|
||||||
isDirty?: boolean;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
displayDescription?: string;
|
|
||||||
type: string;
|
type: string;
|
||||||
cadence: string;
|
cadence: string;
|
||||||
trialAmount?: number;
|
amount: number;
|
||||||
discountAmount?: number;
|
|
||||||
percentageOff?: number;
|
|
||||||
duration: string;
|
duration: string;
|
||||||
durationInMonths: number;
|
durationInMonths: number;
|
||||||
currency?: string;
|
currency: string;
|
||||||
status: string;
|
status: string;
|
||||||
tierId: string;
|
tierId: string;
|
||||||
amountType?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getOfferPortalPreviewUrl = (overrides:offerPortalPreviewUrlTypes, baseUrl: string) : string => {
|
export const getOfferPortalPreviewUrl = (overrides:offerPortalPreviewUrlTypes, baseUrl: string) : string => {
|
||||||
const {
|
const {
|
||||||
disableBackground = false,
|
disableBackground = false,
|
||||||
name,
|
name,
|
||||||
code = {
|
code,
|
||||||
isDirty: false,
|
displayTitle = '',
|
||||||
value: ''
|
|
||||||
},
|
|
||||||
displayTitle = {
|
|
||||||
isDirty: false,
|
|
||||||
value: ''
|
|
||||||
},
|
|
||||||
displayDescription = '',
|
displayDescription = '',
|
||||||
type,
|
type,
|
||||||
cadence,
|
cadence,
|
||||||
trialAmount = 7,
|
amount = 0,
|
||||||
discountAmount = 0,
|
|
||||||
amountType,
|
|
||||||
duration,
|
duration,
|
||||||
durationInMonths,
|
durationInMonths,
|
||||||
currency = 'usd',
|
currency = 'usd',
|
||||||
|
@ -51,30 +34,18 @@ export const getOfferPortalPreviewUrl = (overrides:offerPortalPreviewUrlTypes, b
|
||||||
const portalBase = '/#/portal/preview/offer';
|
const portalBase = '/#/portal/preview/offer';
|
||||||
const settingsParam = new URLSearchParams();
|
const settingsParam = new URLSearchParams();
|
||||||
|
|
||||||
settingsParam.append('type', encodeURIComponent(type));
|
|
||||||
|
|
||||||
const getDiscountAmount = (discount: number, dctype: string) => {
|
|
||||||
if (dctype === 'percent') {
|
|
||||||
return discount.toString();
|
|
||||||
}
|
|
||||||
if (dctype === 'fixed') {
|
|
||||||
settingsParam.append('type', encodeURIComponent('fixed'));
|
|
||||||
let calcDiscount = discount * 100;
|
|
||||||
return calcDiscount.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
settingsParam.append('name', encodeURIComponent(name));
|
settingsParam.append('name', encodeURIComponent(name));
|
||||||
settingsParam.append('code', encodeURIComponent(code.value));
|
settingsParam.append('code', encodeURIComponent(code));
|
||||||
settingsParam.append('display_title', encodeURIComponent(displayTitle.value));
|
settingsParam.append('display_title', encodeURIComponent(displayTitle));
|
||||||
settingsParam.append('display_description', encodeURIComponent(displayDescription));
|
settingsParam.append('display_description', encodeURIComponent(displayDescription));
|
||||||
|
settingsParam.append('type', encodeURIComponent(type));
|
||||||
settingsParam.append('cadence', encodeURIComponent(cadence));
|
settingsParam.append('cadence', encodeURIComponent(cadence));
|
||||||
|
settingsParam.append('amount', encodeURIComponent(amount));
|
||||||
settingsParam.append('duration', encodeURIComponent(duration));
|
settingsParam.append('duration', encodeURIComponent(duration));
|
||||||
settingsParam.append('duration_in_months', encodeURIComponent(durationInMonths));
|
settingsParam.append('duration_in_months', encodeURIComponent(durationInMonths));
|
||||||
settingsParam.append('currency', encodeURIComponent(currency));
|
settingsParam.append('currency', encodeURIComponent(currency));
|
||||||
settingsParam.append('status', encodeURIComponent(status));
|
settingsParam.append('status', encodeURIComponent(status));
|
||||||
settingsParam.append('tier_id', encodeURIComponent(tierId));
|
settingsParam.append('tier_id', encodeURIComponent(tierId));
|
||||||
settingsParam.append('amount', encodeURIComponent(type === 'trial' ? trialAmount.toString() : getDiscountAmount(discountAmount, amountType ? amountType : 'fixed') || '0'));
|
|
||||||
|
|
||||||
if (disableBackground) {
|
if (disableBackground) {
|
||||||
settingsParam.append('disableBackground', 'true');
|
settingsParam.append('disableBackground', 'true');
|
||||||
|
|
Loading…
Add table
Reference in a new issue