diff --git a/client/components/mma/accountoverview/AccountOverview.stories.tsx b/client/components/mma/accountoverview/AccountOverview.stories.tsx index 41bc79395..a5a6349d1 100644 --- a/client/components/mma/accountoverview/AccountOverview.stories.tsx +++ b/client/components/mma/accountoverview/AccountOverview.stories.tsx @@ -17,6 +17,7 @@ import { contributionCancelled, contributionPaidByPayPal, digitalPackPaidByDirectDebit, + guardianLight, guardianWeeklyCancelled, guardianWeeklyGiftPurchase, guardianWeeklyGiftRecipient, @@ -335,3 +336,28 @@ export const WithSupporterPlusDuringOffer: StoryObj = { ], }, }; + +export const WithGuardianLight: StoryObj = { + render: () => { + return ; + }, + + parameters: { + msw: [ + http.get('/api/cancelled/', () => { + return HttpResponse.json([]); + }), + http.get('/mpapi/user/mobile-subscriptions', () => { + return HttpResponse.json({ subscriptions: [] }); + }), + http.get('/api/me/mma', () => { + return HttpResponse.json( + toMembersDataApiResponse(guardianLight()), + ); + }), + http.get('/api/me/one-off-contributions', () => { + return HttpResponse.json([]); + }), + ], + }, +}; diff --git a/client/components/mma/accountoverview/ManageProduct.stories.tsx b/client/components/mma/accountoverview/ManageProduct.stories.tsx index 7f3953955..c361ccbb9 100644 --- a/client/components/mma/accountoverview/ManageProduct.stories.tsx +++ b/client/components/mma/accountoverview/ManageProduct.stories.tsx @@ -4,6 +4,7 @@ import { featureSwitches } from '../../../../shared/featureSwitches'; import { PRODUCT_TYPES } from '../../../../shared/productTypes'; import { digitalPackPaidByDirectDebit, + guardianLight, guardianWeeklyPaidByCard, monthlyContributionPaidByCard, newspaperVoucherPaidByPaypal, @@ -107,3 +108,15 @@ export const SupporterPlusAllAccessDigital: StoryObj = { }, }, }; + +export const GuardianLight: StoryObj = { + render: () => { + return ; + }, + + parameters: { + reactRouter: { + state: { productDetail: guardianLight() }, + }, + }, +}; diff --git a/client/components/mma/accountoverview/ProductCardConfiguration.ts b/client/components/mma/accountoverview/ProductCardConfiguration.ts index 8afea8741..a6eb30b74 100644 --- a/client/components/mma/accountoverview/ProductCardConfiguration.ts +++ b/client/components/mma/accountoverview/ProductCardConfiguration.ts @@ -44,6 +44,9 @@ export const productCardConfiguration: { contributions: { colour: productColour.recurringContribution, }, + guardianlight: { + colour: productColour.recurringContribution, + }, supporterplus: { colour: productColour.supporterPlus, showBenefitsSection: true, diff --git a/client/components/mma/shared/benefits/BenefitsConfiguration.ts b/client/components/mma/shared/benefits/BenefitsConfiguration.ts index 275cbd9a3..0c1a1b47c 100755 --- a/client/components/mma/shared/benefits/BenefitsConfiguration.ts +++ b/client/components/mma/shared/benefits/BenefitsConfiguration.ts @@ -100,6 +100,7 @@ export const benefitsConfiguration: { nationaldelivery: [], voucher: [], guardianweekly: [], + guardianlight: [], guardianpatron: [], }; diff --git a/client/fixtures/productBuilder/baseProducts.ts b/client/fixtures/productBuilder/baseProducts.ts index 6ea83ea62..7896627d2 100644 --- a/client/fixtures/productBuilder/baseProducts.ts +++ b/client/fixtures/productBuilder/baseProducts.ts @@ -11,6 +11,7 @@ import type { ProductDetail } from '../../../shared/productResponse'; // | 'digipack' // | 'supporterplus' // | 'guardianpatron'; +// | 'guardianlight'; export function baseMembership(): ProductDetail { return { @@ -509,6 +510,61 @@ export function baseNationalDelivery(): ProductDetail { }; } +export function baseGuardianLight(): ProductDetail { + return { + tier: 'Guardian Light', + isPaidTier: true, + selfServiceCancellation: { + isAllowed: true, + shouldDisplayEmail: true, + phoneRegionsToDisplay: ['UK & ROW', 'US', 'AUS'], + }, + joinDate: '2022-07-20', + optIn: true, + subscription: { + contactId: '0039E00001KA26BQAT', + deliveryAddress: { + addressLine1: 'Kings Place', + addressLine2: '90 York Place', + town: 'London', + postcode: 'N1 9GU', + country: 'United Kingdom', + }, + safeToUpdatePaymentMethod: true, + start: '2022-07-20', + end: '2022-08-20', + nextPaymentPrice: 700, + nextPaymentDate: '2022-08-20', + lastPaymentDate: '2022-07-20', + potentialCancellationDate: null, + chargedThroughDate: '2022-08-20', + renewalDate: '2023-07-20', + anniversaryDate: '2023-07-20', + cancelledAt: false, + subscriptionId: 'A-S00303371', + trialLength: -2, + autoRenew: true, + currentPlans: [ + { + name: null, + start: '2022-07-20', + end: '2023-07-20', + shouldBeVisible: true, + chargedThrough: '2022-08-20', + price: 700, + currency: '£', + currencyISO: 'GBP', + billingPeriod: 'month', + }, + ], + futurePlans: [], + readerType: 'Direct', + accountId: '8ad09f8a7e25bda3017e296317464818', + }, + isTestUser: false, + }; +} + export function baseSupporterPlus(): ProductDetail { return { tier: 'Supporter Plus', diff --git a/client/fixtures/productBuilder/testProducts.ts b/client/fixtures/productBuilder/testProducts.ts index 7715b6c16..4b3bc2285 100644 --- a/client/fixtures/productBuilder/testProducts.ts +++ b/client/fixtures/productBuilder/testProducts.ts @@ -3,6 +3,7 @@ import { baseContribution, baseDigitalPack, baseDigitalVoucher, + baseGuardianLight, baseGuardianWeekly, baseHomeDelivery, baseMembership, @@ -259,6 +260,12 @@ export function supporterPlusInOfferPeriod() { .getProductDetailObject(); } +export function guardianLight() { + return new ProductBuilder(baseGuardianLight()) + .payByCard() + .getProductDetailObject(); +} + export function tierThree() { return new ProductBuilder(baseTierThree()) .payByCard() diff --git a/shared/ophanTypes.ts b/shared/ophanTypes.ts index 1b39c17bd..5190f1886 100644 --- a/shared/ophanTypes.ts +++ b/shared/ophanTypes.ts @@ -12,6 +12,7 @@ export type OphanProduct = | 'PAPER_SUBSCRIPTION_SUNDAY' | 'PRINT_SUBSCRIPTION' | 'APP_PREMIUM_TIER' + | 'GUARDIAN_LIGHT' | 'GUARDIAN_PATRON'; type OphanAction = diff --git a/shared/productResponse.ts b/shared/productResponse.ts index 6f8beae73..1a3e23f3c 100644 --- a/shared/productResponse.ts +++ b/shared/productResponse.ts @@ -86,6 +86,7 @@ export const productTiers = [ 'Newspaper Delivery', 'Patron', 'Partner', + 'Guardian Light', ]; export type ProductTier = typeof productTiers[number]; @@ -295,6 +296,9 @@ export function getSpecificProductTypeFromTier( case 'Newspaper Digital Voucher': productType = PRODUCT_TYPES.digitalvoucher; break; + case 'Guardian Light': + productType = PRODUCT_TYPES.guardianlight; + break; case 'guardianpatron': productType = PRODUCT_TYPES.guardianpatron; break; diff --git a/shared/productTypes.ts b/shared/productTypes.ts index 1af898c82..0321fcdf1 100644 --- a/shared/productTypes.ts +++ b/shared/productTypes.ts @@ -46,6 +46,7 @@ type ProductFriendlyName = | 'subscription' | 'support' | 'recurring support' + | 'guardian light' | 'guardian patron'; type ProductUrlPart = | 'membership' @@ -61,6 +62,7 @@ type ProductUrlPart = | 'digital+print' | 'subscriptions' | 'recurringsupport' + | 'guardianlight' | 'guardianpatron'; type SfCaseProduct = | 'Membership' @@ -70,6 +72,7 @@ type SfCaseProduct = | 'Digital Pack Subscriptions' | 'Supporter Plus' | 'Tier Three' + | 'Guardian Light' | 'Guardian Patron'; export type AllProductsProductTypeFilterString = | 'Weekly' @@ -83,12 +86,12 @@ export type AllProductsProductTypeFilterString = | 'SupporterPlus' | 'ContentSubscription' | 'GuardianPatron' + | 'GuardianLight' | 'TierThree'; interface CancellationFlowProperties { reasons: CancellationReason[]; sfCaseProduct: SfCaseProduct; - linkOnProductPage?: true; checkForOutstandingCredits?: true; flowWrapper?: ( productDetail: ProductDetail, @@ -175,7 +178,6 @@ export interface ProductType { showSupporterId?: boolean; tierLabel?: string; renewalMetadata?: SupportTheGuardianButtonProps; - noProductSupportUrlSuffix?: string; cancellation?: CancellationFlowProperties; // undefined 'cancellation' means no cancellation flow cancelledCopy?: string; showTrialRemainingIfApplicable?: true; @@ -263,6 +265,7 @@ export type ProductTypeKeys = | 'digipack' | 'supporterplus' | 'tierthree' + | 'guardianlight' | 'guardianpatron'; export type GroupedProductTypeKeys = @@ -325,7 +328,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { allProductsProductTypeFilterString: 'Contribution', urlPart: 'contributions', getOphanProductType: () => 'RECURRING_CONTRIBUTION', - noProductSupportUrlSuffix: '/contribute', updateAmountMdaEndpoint: 'contribution-update-amount', softOptInIDs: [ SoftOptInIDs.SupportOnboarding, @@ -334,7 +336,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { cancellation: { alternateSummaryMainPara: 'This is immediate and you will not be charged again.', - linkOnProductPage: true, reasons: shuffledContributionsCancellationReasons, sfCaseProduct: 'Recurring - Contributions', startPageBody: contributionsCancellationFlowStart, @@ -510,7 +511,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { enableDeliveryInstructionsUpdate: true, }, cancellation: { - linkOnProductPage: true, reasons: voucherCancellationReasons, sfCaseProduct: 'Voucher Subscriptions', checkForOutstandingCredits: true, @@ -582,7 +582,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { }, }, cancellation: { - linkOnProductPage: true, reasons: gwCancellationReasons, sfCaseProduct: 'Guardian Weekly', checkForOutstandingCredits: true, @@ -628,7 +627,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { }, }, cancellation: { - linkOnProductPage: true, reasons: gwCancellationReasons, sfCaseProduct: 'Tier Three', checkForOutstandingCredits: true, @@ -667,7 +665,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { SoftOptInIDs.SupporterNewsletter, ], cancellation: { - linkOnProductPage: true, reasons: digipackCancellationReasons, sfCaseProduct: 'Digital Pack Subscriptions', startPageBody: digipackCancellationFlowStart, @@ -698,7 +695,6 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { cancellation: { alternateSummaryMainPara: "This is immediate and you will not be charged again. If you've cancelled within the first 14 days, we'll send you a full refund.", - linkOnProductPage: true, reasons: shuffledSupporterPlusCancellationReasons, sfCaseProduct: 'Supporter Plus', startPageBody: supporterplusCancellationFlowStart, @@ -725,6 +721,64 @@ export const PRODUCT_TYPES: { [productKey in ProductTypeKeys]: ProductType } = { SoftOptInIDs.SupporterNewsletter, ], }, + guardianlight: { + productTitle: () => 'Guardian Light', + friendlyName: 'guardian light', + productType: 'guardianlight', + groupedProductType: 'recurringSupport', + allProductsProductTypeFilterString: 'GuardianLight', + urlPart: 'guardianlight', + getOphanProductType: () => 'GUARDIAN_LIGHT', + softOptInIDs: [ + SoftOptInIDs.SupportOnboarding, + SoftOptInIDs.SupporterNewsletter, + ], + cancellation: { + alternateSummaryMainPara: + 'This is immediate and you will not be charged again.', + reasons: shuffledContributionsCancellationReasons, + sfCaseProduct: 'Guardian Light', + startPageBody: contributionsCancellationFlowStart, + shouldHideSummaryMainPara: true, + summaryReasonSpecificPara: ( + reasonId: OptionalCancellationReasonId, + ) => { + switch (reasonId) { + case 'mma_financial_circumstances': + case 'mma_value_for_money': + case 'mma_one_off': + return 'You can support The Guardian’s independent journalism with a One-time contribution, from as little as £1 – and it only takes a minute.'; + case 'mma_wants_annual_contribution': + return 'You can support The Guardian’s independent journalism for the long term with an annual contribution.'; + case 'mma_wants_monthly_contribution': + return 'You can support The Guardian’s independent journalism for the long term with a monthly contribution.'; + default: + return undefined; + } + }, + onlyShowSupportSectionIfAlternateText: true, + alternateSupportButtonText: ( + reasonId: OptionalCancellationReasonId, + ) => { + switch (reasonId) { + case 'mma_financial_circumstances': + case 'mma_value_for_money': + case 'mma_one_off': + return 'Make a One-time contribution'; + case 'mma_wants_annual_contribution': + return 'Make an annual contribution'; + case 'mma_wants_monthly_contribution': + return 'Make a monthly contribution'; + default: + return undefined; + } + }, + alternateSupportButtonUrlSuffix: () => undefined, + swapFeedbackAndContactUs: true, + shouldHideThrasher: true, + shouldShowReminder: true, + }, + }, }; export const GROUPED_PRODUCT_TYPES: {