diff --git a/apps/photos/public/locales/en/translation.json b/apps/photos/public/locales/en/translation.json index f24b50748..ba1b1b250 100644 --- a/apps/photos/public/locales/en/translation.json +++ b/apps/photos/public/locales/en/translation.json @@ -157,6 +157,7 @@ "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renews on {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Ends on {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Your subscription will be cancelled on {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "You have exceeded your storage quota, please upgrade", "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", @@ -171,6 +172,7 @@ "UPDATE_SUBSCRIPTION": "Change plan", "CANCEL_SUBSCRIPTION": "Cancel subscription", "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

Your data will be scheduled for deletion at the end of your add-on pack's validity.

", "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", "REACTIVATE_SUBSCRIPTION": "Reactivate subscription", diff --git a/apps/photos/src/components/Sidebar/SubscriptionStatus/index.tsx b/apps/photos/src/components/Sidebar/SubscriptionStatus/index.tsx index 113228c34..40f02bd1d 100644 --- a/apps/photos/src/components/Sidebar/SubscriptionStatus/index.tsx +++ b/apps/photos/src/components/Sidebar/SubscriptionStatus/index.tsx @@ -69,6 +69,48 @@ export default function SubscriptionStatus({ return <>; } + const messages = []; + if (!hasAddOnBonus(userDetails.bonusData)) { + if (isSubscriptionActive(userDetails.subscription)) { + if (isOnFreePlan(userDetails.subscription)) { + messages.push( + + ); + } else if (isSubscriptionCancelled(userDetails.subscription)) { + messages.push( + t('RENEWAL_CANCELLED_SUBSCRIPTION_INFO', { + date: userDetails.subscription?.expiryTime, + }) + ); + } + } else { + messages.push( + , + }} + /> + ); + } + } + + if (hasExceededStorageQuota(userDetails) && messages.length === 0) { + messages.push( + , + }} + /> + ); + } + return ( - {isSubscriptionActive(userDetails.subscription) ? ( - isOnFreePlan(userDetails.subscription) ? ( - hasAddOnBonus(userDetails.bonusData) ? ( - '' - ) : ( - - ) - ) : isSubscriptionCancelled(userDetails.subscription) ? ( - t('RENEWAL_CANCELLED_SUBSCRIPTION_INFO', { - date: userDetails.subscription?.expiryTime, - }) - ) : ( - hasExceededStorageQuota(userDetails) && ( - , - }} - /> - ) - ) - ) : ( - , - }} - /> - )} + {messages} ); diff --git a/apps/photos/src/components/pages/gallery/PlanSelector/card/free.tsx b/apps/photos/src/components/pages/gallery/PlanSelector/card/free.tsx index 3e9bb5ad0..71e772391 100644 --- a/apps/photos/src/components/pages/gallery/PlanSelector/card/free.tsx +++ b/apps/photos/src/components/pages/gallery/PlanSelector/card/free.tsx @@ -5,10 +5,13 @@ import React from 'react'; import { t } from 'i18next'; import { PeriodToggler } from '../periodToggler'; import Plans from '../plans'; +import { hasAddOnBonus } from 'utils/billing'; +import { BFAddOnRow } from '../plans/BfAddOnRow'; export default function FreeSubscriptionPlanSelectorCard({ plans, subscription, + bonusData, closeModal, planPeriod, togglePeriod, @@ -36,8 +39,15 @@ export default function FreeSubscriptionPlanSelectorCard({ planPeriod={planPeriod} onPlanSelect={onPlanSelect} subscription={subscription} + bonusData={bonusData} closeModal={closeModal} /> + {hasAddOnBonus(bonusData) && ( + + )} diff --git a/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx b/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx index 5be0507b8..5e0985797 100644 --- a/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx +++ b/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx @@ -44,6 +44,13 @@ function PlanSelectorCard(props: Props) { ); const galleryContext = useContext(GalleryContext); const appContext = useContext(AppContext); + const bonusData = useMemo(() => { + const userDetails = getLocalUserDetails(); + if (!userDetails) { + return null; + } + return userDetails.bonusData; + }, []); const usage = useMemo(() => { const userDetails = getLocalUserDetails(); @@ -170,6 +177,7 @@ function PlanSelectorCard(props: Props) { @@ -85,11 +92,18 @@ export default function PaidSubscriptionPlanSelectorCard({ date: subscription.expiryTime, })} + {hasAddOnBonus(bonusData) && ( + + )} diff --git a/apps/photos/src/components/pages/gallery/PlanSelector/manageSubscription/index.tsx b/apps/photos/src/components/pages/gallery/PlanSelector/manageSubscription/index.tsx index fcde5465b..31b34ce16 100644 --- a/apps/photos/src/components/pages/gallery/PlanSelector/manageSubscription/index.tsx +++ b/apps/photos/src/components/pages/gallery/PlanSelector/manageSubscription/index.tsx @@ -12,16 +12,21 @@ import { manageFamilyMethod, hasStripeSubscription, isSubscriptionCancelled, + hasAddOnBonus, } from 'utils/billing'; import ManageSubscriptionButton from './button'; +import { BonusData } from 'types/user'; + interface Iprops { subscription: Subscription; + bonusData?: BonusData; closeModal: () => void; setLoading: SetLoading; } export function ManageSubscription({ subscription, + bonusData, closeModal, setLoading, }: Iprops) { @@ -34,6 +39,7 @@ export function ManageSubscription({ {hasStripeSubscription(subscription) && ( @@ -49,6 +55,7 @@ export function ManageSubscription({ function StripeSubscriptionOptions({ subscription, + bonusData, setLoading, closeModal, }: Iprops) { @@ -77,7 +84,11 @@ function StripeSubscriptionOptions({ const confirmCancel = () => appContext.setDialogMessage({ title: t('CANCEL_SUBSCRIPTION'), - content: , + content: hasAddOnBonus(bonusData) ? ( + + ) : ( + + ), proceed: { text: t('CANCEL_SUBSCRIPTION'), action: cancelSubscription.bind( diff --git a/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx b/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx new file mode 100644 index 000000000..46584cde7 --- /dev/null +++ b/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx @@ -0,0 +1,43 @@ +import { Box, styled, Typography } from '@mui/material'; +import { SpaceBetweenFlex } from '@ente/shared/components/Container'; +import React from 'react'; + +import { Trans } from 'react-i18next'; +import { makeHumanReadableStorage } from 'utils/billing'; + +const RowContainer = styled(SpaceBetweenFlex)(({ theme }) => ({ + // gap: theme.spacing(1.5), + padding: theme.spacing(1, 0), + cursor: 'pointer', + '&:hover .endIcon': { + backgroundColor: 'rgba(255,255,255,0.08)', + }, +})); +export function BFAddOnRow({ bonusData, closeModal }) { + return ( + <> + {bonusData.storageBonuses.map((bonus) => { + if (bonus.type.startsWith('ADD_ON')) { + return ( + + + + + + + + ); + } + return null; + })} + + ); +} diff --git a/apps/photos/src/components/pages/gallery/PlanSelector/plans/index.tsx b/apps/photos/src/components/pages/gallery/PlanSelector/plans/index.tsx index bfd13ecaf..e68b4fddc 100644 --- a/apps/photos/src/components/pages/gallery/PlanSelector/plans/index.tsx +++ b/apps/photos/src/components/pages/gallery/PlanSelector/plans/index.tsx @@ -2,6 +2,7 @@ import { FreePlanRow } from './FreePlanRow'; import { Stack } from '@mui/material'; import React from 'react'; import { + hasAddOnBonus, hasPaidSubscription, isPopularPlan, isUserSubscribedPlan, @@ -9,11 +10,13 @@ import { import { PlanRow } from './planRow'; import { Plan, Subscription } from 'types/billing'; import { PLAN_PERIOD } from 'constants/gallery'; +import { BonusData } from 'types/user'; interface Iprops { plans: Plan[]; planPeriod: PLAN_PERIOD; subscription: Subscription; + bonusData?: BonusData; onPlanSelect: (plan: Plan) => void; closeModal: () => void; } @@ -22,6 +25,7 @@ const Plans = ({ plans, planPeriod, subscription, + bonusData, onPlanSelect, closeModal, }: Iprops) => ( @@ -38,7 +42,7 @@ const Plans = ({ onPlanSelect={onPlanSelect} /> ))} - {!hasPaidSubscription(subscription) && ( + {!hasPaidSubscription(subscription) && !hasAddOnBonus(bonusData) && ( )}