update plan selector card with active plan
This commit is contained in:
parent
94a408d815
commit
ee03cce577
202
src/components/pages/gallery/PlanSelector/card.tsx
Normal file
202
src/components/pages/gallery/PlanSelector/card.tsx
Normal file
|
@ -0,0 +1,202 @@
|
|||
import { PLAN_PERIOD } from './../../../../constants/gallery/index';
|
||||
import { PeriodToggler } from './periodToggler';
|
||||
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { Plan } from 'types/billing';
|
||||
import {
|
||||
isUserSubscribedPlan,
|
||||
isSubscriptionCancelled,
|
||||
updateSubscription,
|
||||
hasStripeSubscription,
|
||||
isOnFreePlan,
|
||||
planForSubscription,
|
||||
hasMobileSubscription,
|
||||
hasPaypalSubscription,
|
||||
getLocalUserSubscription,
|
||||
hasPaidSubscription,
|
||||
convertBytesToGBs,
|
||||
getTotalFamilyUsage,
|
||||
makeHumanReadableStorage,
|
||||
} from 'utils/billing';
|
||||
import { reverseString } from 'utils/common';
|
||||
import { GalleryContext } from 'pages/gallery';
|
||||
import billingService from 'services/billingService';
|
||||
import { SetLoading } from 'types/gallery';
|
||||
import { logError } from 'utils/sentry';
|
||||
import { AppContext } from 'pages/_app';
|
||||
import Plans from './plans';
|
||||
import { Box, Stack, Typography } from '@mui/material';
|
||||
import { useLocalState } from 'hooks/useLocalState';
|
||||
import { LS_KEYS } from 'utils/storage/localStorage';
|
||||
import { getLocalUserDetails } from 'utils/user';
|
||||
import { ManageSubscription } from './manageSubscription';
|
||||
|
||||
interface Props {
|
||||
closeModal: any;
|
||||
setLoading: SetLoading;
|
||||
}
|
||||
|
||||
function PlanSelectorCard(props: Props) {
|
||||
const subscription = useMemo(() => getLocalUserSubscription(), []);
|
||||
const totalFamilyUsage = useMemo(
|
||||
() => getTotalFamilyUsage(getLocalUserDetails().familyData),
|
||||
[]
|
||||
);
|
||||
const [plans, setPlans] = useLocalState<Plan[]>(LS_KEYS.PLANS);
|
||||
const [planPeriod, setPlanPeriod] = useState<PLAN_PERIOD>(PLAN_PERIOD.YEAR);
|
||||
const galleryContext = useContext(GalleryContext);
|
||||
const appContext = useContext(AppContext);
|
||||
|
||||
const togglePeriod = () => {
|
||||
setPlanPeriod((prevPeriod) =>
|
||||
prevPeriod === PLAN_PERIOD.MONTH
|
||||
? PLAN_PERIOD.YEAR
|
||||
: PLAN_PERIOD.MONTH
|
||||
);
|
||||
};
|
||||
function onReopenClick() {
|
||||
appContext.closeMessageDialog();
|
||||
galleryContext.showPlanSelectorModal();
|
||||
}
|
||||
useEffect(() => {
|
||||
const main = async () => {
|
||||
try {
|
||||
props.setLoading(true);
|
||||
let plans = await billingService.getPlans();
|
||||
|
||||
const planNotListed =
|
||||
plans.filter((plan) =>
|
||||
isUserSubscribedPlan(plan, subscription)
|
||||
).length === 0;
|
||||
if (
|
||||
subscription &&
|
||||
!isOnFreePlan(subscription) &&
|
||||
planNotListed
|
||||
) {
|
||||
plans = [planForSubscription(subscription), ...plans];
|
||||
}
|
||||
setPlans(plans);
|
||||
} catch (e) {
|
||||
logError(e, 'plan selector modal open failed');
|
||||
props.closeModal();
|
||||
appContext.setDialogMessage({
|
||||
title: constants.OPEN_PLAN_SELECTOR_MODAL_FAILED,
|
||||
content: constants.UNKNOWN_ERROR,
|
||||
close: { text: 'close', variant: 'danger' },
|
||||
proceed: {
|
||||
text: constants.REOPEN_PLAN_SELECTOR_MODAL,
|
||||
variant: 'accent',
|
||||
action: onReopenClick,
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
props.setLoading(false);
|
||||
}
|
||||
};
|
||||
main();
|
||||
}, []);
|
||||
|
||||
async function onPlanSelect(plan: Plan) {
|
||||
if (
|
||||
hasMobileSubscription(subscription) &&
|
||||
!isSubscriptionCancelled(subscription)
|
||||
) {
|
||||
appContext.setDialogMessage({
|
||||
title: constants.ERROR,
|
||||
content: constants.CANCEL_SUBSCRIPTION_ON_MOBILE,
|
||||
close: { variant: 'danger' },
|
||||
});
|
||||
} else if (
|
||||
hasPaypalSubscription(subscription) &&
|
||||
!isSubscriptionCancelled(subscription)
|
||||
) {
|
||||
appContext.setDialogMessage({
|
||||
title: constants.MANAGE_PLAN,
|
||||
content: constants.PAYPAL_MANAGE_NOT_SUPPORTED_MESSAGE(),
|
||||
close: { variant: 'danger' },
|
||||
});
|
||||
} else if (hasStripeSubscription(subscription)) {
|
||||
appContext.setDialogMessage({
|
||||
title: `${constants.CONFIRM} ${reverseString(
|
||||
constants.UPDATE_SUBSCRIPTION
|
||||
)}`,
|
||||
content: constants.UPDATE_SUBSCRIPTION_MESSAGE,
|
||||
proceed: {
|
||||
text: constants.UPDATE_SUBSCRIPTION,
|
||||
action: updateSubscription.bind(
|
||||
null,
|
||||
plan,
|
||||
appContext.setDialogMessage,
|
||||
props.setLoading,
|
||||
props.closeModal
|
||||
),
|
||||
variant: 'accent',
|
||||
},
|
||||
close: { text: constants.CANCEL },
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
props.setLoading(true);
|
||||
await billingService.buySubscription(plan.stripeID);
|
||||
} catch (e) {
|
||||
props.setLoading(false);
|
||||
appContext.setDialogMessage({
|
||||
title: constants.ERROR,
|
||||
content: constants.SUBSCRIPTION_PURCHASE_FAILED,
|
||||
close: { variant: 'danger' },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack spacing={3} p={1.5}>
|
||||
{hasPaidSubscription(subscription) ? (
|
||||
<Box>
|
||||
<Typography variant="h3" fontWeight={'bold'}>
|
||||
{constants.SUBSCRIPTION}
|
||||
</Typography>
|
||||
<Typography variant="body2" color={'text.secondary'}>
|
||||
{convertBytesToGBs(subscription.storage)}{' '}
|
||||
{constants.GB}
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<Typography variant="h3" fontWeight={'bold'}>
|
||||
{constants.CHOOSE_PLAN}
|
||||
</Typography>
|
||||
)}
|
||||
{totalFamilyUsage > 0 && (
|
||||
<Typography color={'text.secondary'} fontWeight={'bold'}>
|
||||
{constants.CURRENT_USAGE(
|
||||
makeHumanReadableStorage(totalFamilyUsage)
|
||||
)}
|
||||
</Typography>
|
||||
)}
|
||||
<Box>
|
||||
<PeriodToggler
|
||||
planPeriod={planPeriod}
|
||||
togglePeriod={togglePeriod}
|
||||
/>
|
||||
<Typography mt={0.5} color="text.secondary">
|
||||
{constants.TWO_MONTHS_FREE}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Plans
|
||||
plans={plans}
|
||||
planPeriod={planPeriod}
|
||||
onPlanSelect={onPlanSelect}
|
||||
subscription={subscription}
|
||||
/>
|
||||
<ManageSubscription
|
||||
subscription={subscription}
|
||||
closeModal={props.closeModal}
|
||||
setLoading={props.setLoading}
|
||||
/>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default PlanSelectorCard;
|
|
@ -1,150 +1,19 @@
|
|||
import { PeriodToggler } from './periodToggler';
|
||||
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { Plan } from 'types/billing';
|
||||
import {
|
||||
isUserSubscribedPlan,
|
||||
isSubscriptionCancelled,
|
||||
updateSubscription,
|
||||
hasStripeSubscription,
|
||||
isOnFreePlan,
|
||||
planForSubscription,
|
||||
hasMobileSubscription,
|
||||
hasPaypalSubscription,
|
||||
getLocalUserSubscription,
|
||||
} from 'utils/billing';
|
||||
import { reverseString } from 'utils/common';
|
||||
import { GalleryContext } from 'pages/gallery';
|
||||
import billingService from 'services/billingService';
|
||||
import React, { useContext } from 'react';
|
||||
import { SetLoading } from 'types/gallery';
|
||||
import { logError } from 'utils/sentry';
|
||||
import { AppContext } from 'pages/_app';
|
||||
import Plans from './plans';
|
||||
import { Box, Dialog, Stack, Typography } from '@mui/material';
|
||||
import { useLocalState } from 'hooks/useLocalState';
|
||||
import { LS_KEYS } from 'utils/storage/localStorage';
|
||||
import { Box, Dialog } from '@mui/material';
|
||||
import PlanSelectorCard from './card';
|
||||
|
||||
interface Props {
|
||||
modalView: boolean;
|
||||
closeModal: any;
|
||||
|
||||
setLoading: SetLoading;
|
||||
}
|
||||
export enum PLAN_PERIOD {
|
||||
MONTH = 'month',
|
||||
YEAR = 'year',
|
||||
}
|
||||
|
||||
function PlanSelector(props: Props) {
|
||||
const subscription = useMemo(() => getLocalUserSubscription(), []);
|
||||
const [plans, setPlans] = useLocalState<Plan[]>(LS_KEYS.PLANS);
|
||||
const [planPeriod, setPlanPeriod] = useState<PLAN_PERIOD>(PLAN_PERIOD.YEAR);
|
||||
const galleryContext = useContext(GalleryContext);
|
||||
const appContext = useContext(AppContext);
|
||||
|
||||
const togglePeriod = () => {
|
||||
setPlanPeriod((prevPeriod) =>
|
||||
prevPeriod === PLAN_PERIOD.MONTH
|
||||
? PLAN_PERIOD.YEAR
|
||||
: PLAN_PERIOD.MONTH
|
||||
);
|
||||
};
|
||||
function onReopenClick() {
|
||||
appContext.closeMessageDialog();
|
||||
galleryContext.showPlanSelectorModal();
|
||||
}
|
||||
useEffect(() => {
|
||||
if (!props.modalView) {
|
||||
return;
|
||||
}
|
||||
const main = async () => {
|
||||
try {
|
||||
props.setLoading(true);
|
||||
let plans = await billingService.getPlans();
|
||||
|
||||
const planNotListed =
|
||||
plans.filter((plan) =>
|
||||
isUserSubscribedPlan(plan, subscription)
|
||||
).length === 0;
|
||||
if (
|
||||
subscription &&
|
||||
!isOnFreePlan(subscription) &&
|
||||
planNotListed
|
||||
) {
|
||||
plans = [planForSubscription(subscription), ...plans];
|
||||
}
|
||||
setPlans(plans);
|
||||
} catch (e) {
|
||||
logError(e, 'plan selector modal open failed');
|
||||
props.closeModal();
|
||||
appContext.setDialogMessage({
|
||||
title: constants.OPEN_PLAN_SELECTOR_MODAL_FAILED,
|
||||
content: constants.UNKNOWN_ERROR,
|
||||
close: { text: 'close', variant: 'danger' },
|
||||
proceed: {
|
||||
text: constants.REOPEN_PLAN_SELECTOR_MODAL,
|
||||
variant: 'accent',
|
||||
action: onReopenClick,
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
props.setLoading(false);
|
||||
}
|
||||
};
|
||||
main();
|
||||
}, [props.modalView]);
|
||||
|
||||
async function onPlanSelect(plan: Plan) {
|
||||
if (
|
||||
hasMobileSubscription(subscription) &&
|
||||
!isSubscriptionCancelled(subscription)
|
||||
) {
|
||||
appContext.setDialogMessage({
|
||||
title: constants.ERROR,
|
||||
content: constants.CANCEL_SUBSCRIPTION_ON_MOBILE,
|
||||
close: { variant: 'danger' },
|
||||
});
|
||||
} else if (
|
||||
hasPaypalSubscription(subscription) &&
|
||||
!isSubscriptionCancelled(subscription)
|
||||
) {
|
||||
appContext.setDialogMessage({
|
||||
title: constants.MANAGE_PLAN,
|
||||
content: constants.PAYPAL_MANAGE_NOT_SUPPORTED_MESSAGE(),
|
||||
close: { variant: 'danger' },
|
||||
});
|
||||
} else if (hasStripeSubscription(subscription)) {
|
||||
appContext.setDialogMessage({
|
||||
title: `${constants.CONFIRM} ${reverseString(
|
||||
constants.UPDATE_SUBSCRIPTION
|
||||
)}`,
|
||||
content: constants.UPDATE_SUBSCRIPTION_MESSAGE,
|
||||
proceed: {
|
||||
text: constants.UPDATE_SUBSCRIPTION,
|
||||
action: updateSubscription.bind(
|
||||
null,
|
||||
plan,
|
||||
appContext.setDialogMessage,
|
||||
props.setLoading,
|
||||
props.closeModal
|
||||
),
|
||||
variant: 'accent',
|
||||
},
|
||||
close: { text: constants.CANCEL },
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
props.setLoading(true);
|
||||
await billingService.buySubscription(plan.stripeID);
|
||||
} catch (e) {
|
||||
props.setLoading(false);
|
||||
appContext.setDialogMessage({
|
||||
title: constants.ERROR,
|
||||
content: constants.SUBSCRIPTION_PURCHASE_FAILED,
|
||||
close: { variant: 'danger' },
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!props.modalView) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -154,35 +23,10 @@ function PlanSelector(props: Props) {
|
|||
onClose={props.closeModal}
|
||||
PaperProps={{ sx: { width: '400px' } }}>
|
||||
<Box p={1}>
|
||||
<Stack spacing={3} p={1.5}>
|
||||
<Typography variant="h3" fontWeight={'bold'}>
|
||||
{
|
||||
/* hasPaidSubscription(subscription)
|
||||
? constants.MANAGE_PLAN
|
||||
: */ constants.CHOOSE_PLAN
|
||||
}
|
||||
</Typography>
|
||||
<Box>
|
||||
<PeriodToggler
|
||||
planPeriod={planPeriod}
|
||||
togglePeriod={togglePeriod}
|
||||
/>
|
||||
<Typography mt={0.5} color="text.secondary">
|
||||
{constants.TWO_MONTHS_FREE}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Plans
|
||||
plans={plans}
|
||||
planPeriod={planPeriod}
|
||||
onPlanSelect={onPlanSelect}
|
||||
subscription={subscription}
|
||||
/>
|
||||
{/* <ManageSubscription
|
||||
subscription={subscription}
|
||||
<PlanSelectorCard
|
||||
closeModal={props.closeModal}
|
||||
setLoading={props.setLoading}
|
||||
/> */}
|
||||
</Stack>
|
||||
/>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { styled, ToggleButton, ToggleButtonGroup } from '@mui/material';
|
||||
import { PLAN_PERIOD } from 'constants/gallery';
|
||||
import React from 'react';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { PLAN_PERIOD } from '.';
|
||||
export function PeriodToggler({ planPeriod, togglePeriod }) {
|
||||
const CustomToggleButton = styled(ToggleButton)(({ theme }) => ({
|
||||
textTransform: 'none',
|
||||
|
|
|
@ -2,6 +2,7 @@ import ArrowForward from '@mui/icons-material/ArrowForward';
|
|||
import { Box, Typography } from '@mui/material';
|
||||
import { FlexWrapper, SpaceBetweenFlex } from 'components/Container';
|
||||
import React from 'react';
|
||||
import { isUserSubscribedPlan } from 'utils/billing';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { PlanRow } from './planRow';
|
||||
|
||||
|
@ -11,6 +12,7 @@ const Plans = ({ plans, planPeriod, subscription, onPlanSelect }) => (
|
|||
?.filter((plan) => plan.period === planPeriod)
|
||||
?.map((plan) => (
|
||||
<PlanRow
|
||||
disabled={isUserSubscribedPlan(plan, subscription)}
|
||||
key={plan.stripeID}
|
||||
plan={plan}
|
||||
subscription={subscription}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
import { PlanIconButton } from './button';
|
||||
import { Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { isUserSubscribedPlan, convertBytesToGBs } from 'utils/billing';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { PLAN_PERIOD } from '..';
|
||||
import PlanTile from './planTile';
|
||||
|
||||
export function PlanCard({ plan, subscription, onPlanSelect }) {
|
||||
const handleClick = () => {
|
||||
!isUserSubscribedPlan(plan, subscription) && onPlanSelect(plan);
|
||||
};
|
||||
|
||||
return (
|
||||
<PlanTile
|
||||
key={plan.stripeID}
|
||||
current={isUserSubscribedPlan(plan, subscription)}
|
||||
onClick={handleClick}>
|
||||
<Typography variant="title" fontWeight={'bold'}>
|
||||
{convertBytesToGBs(plan.storage, 0)}
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
color="text.secondary"
|
||||
variant="title"
|
||||
fontWeight={'normal'}>
|
||||
{`${plan.price} / ${
|
||||
plan.period === PLAN_PERIOD.MONTH
|
||||
? constants.MONTH_SHORT
|
||||
: constants.YEAR_SHORT
|
||||
}`}
|
||||
</Typography>
|
||||
|
||||
<PlanIconButton
|
||||
current={isUserSubscribedPlan(plan, subscription)}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
</PlanTile>
|
||||
);
|
||||
}
|
|
@ -1,51 +1,75 @@
|
|||
import { Box, Button, Typography } from '@mui/material';
|
||||
import { Box, Button, ButtonProps, styled, Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { isUserSubscribedPlan, convertBytesToGBs } from 'utils/billing';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { PLAN_PERIOD } from '..';
|
||||
import { FlexWrapper, FluidContainer } from 'components/Container';
|
||||
import ArrowForward from '@mui/icons-material/ArrowForward';
|
||||
import { PLAN_PERIOD } from 'constants/gallery';
|
||||
import Done from '@mui/icons-material/Done';
|
||||
import { Plan, Subscription } from 'types/billing';
|
||||
|
||||
export function PlanRow({ plan, subscription, onPlanSelect }) {
|
||||
interface Iprops {
|
||||
plan: Plan;
|
||||
subscription: Subscription;
|
||||
onPlanSelect: (plan: Plan) => void;
|
||||
disabled: boolean;
|
||||
}
|
||||
const DisabledPlanButton = styled((props: ButtonProps) => (
|
||||
<Button disabled endIcon={<Done />} {...props} />
|
||||
))(({ theme }) => ({
|
||||
'&&': {
|
||||
cursor: 'default',
|
||||
backgroundColor: 'transparent',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}));
|
||||
|
||||
const ActivePlanButton = (props: ButtonProps) => (
|
||||
<Button color="accent" {...props} endIcon={<ArrowForward />} />
|
||||
);
|
||||
|
||||
export function PlanRow({
|
||||
plan,
|
||||
subscription,
|
||||
onPlanSelect,
|
||||
disabled,
|
||||
}: Iprops) {
|
||||
const handleClick = () => {
|
||||
!isUserSubscribedPlan(plan, subscription) && onPlanSelect(plan);
|
||||
};
|
||||
|
||||
const PlanButton = disabled ? DisabledPlanButton : ActivePlanButton;
|
||||
|
||||
return (
|
||||
<FlexWrapper
|
||||
sx={{
|
||||
background:
|
||||
'linear-gradient(268.22deg, rgba(256, 256, 256, 0.08) -3.72%, rgba(256, 256, 256, 0) 85.73%)',
|
||||
}}
|
||||
// current={isUserSubscribedPlan(plan, subscription)}
|
||||
onClick={handleClick}>
|
||||
<FluidContainer sx={{ '&&': { alignItems: 'flex-start' } }}>
|
||||
<Typography variant="h1" fontWeight={'bold'}>
|
||||
{convertBytesToGBs(plan.storage, 0)}
|
||||
{convertBytesToGBs(plan.storage)}
|
||||
</Typography>
|
||||
<Typography variant="h3" color="text.secondary">
|
||||
{constants.GB}
|
||||
</Typography>
|
||||
</FluidContainer>
|
||||
{/* <PlanIconButton
|
||||
current={isUserSubscribedPlan(plan, subscription)} */}
|
||||
<Button
|
||||
onClick={handleClick}
|
||||
sx={{ width: '136px' }}
|
||||
color="accent"
|
||||
endIcon={<ArrowForward />}>
|
||||
<Box>
|
||||
<Typography fontWeight={'bold'} variant="h4">
|
||||
{plan.price}{' '}
|
||||
</Typography>{' '}
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
/ $
|
||||
{plan.period === PLAN_PERIOD.MONTH
|
||||
? constants.MONTH_SHORT
|
||||
: constants.YEAR_SHORT}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Button>
|
||||
<Box width="136px">
|
||||
<PlanButton size="large" onClick={handleClick}>
|
||||
<Box>
|
||||
<Typography fontWeight={'bold'} variant="h4">
|
||||
{plan.price}{' '}
|
||||
</Typography>{' '}
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
/ $
|
||||
{plan.period === PLAN_PERIOD.MONTH
|
||||
? constants.MONTH_SHORT
|
||||
: constants.YEAR_SHORT}
|
||||
</Typography>
|
||||
</Box>
|
||||
</PlanButton>
|
||||
</Box>
|
||||
</FlexWrapper>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,3 +6,8 @@ export const IMAGE_CONTAINER_MAX_WIDTH =
|
|||
IMAGE_CONTAINER_MAX_HEIGHT - GAP_BTW_TILES;
|
||||
export const MIN_COLUMNS = 4;
|
||||
export const SPACE_BTW_DATES = 44;
|
||||
|
||||
export enum PLAN_PERIOD {
|
||||
MONTH = 'month',
|
||||
YEAR = 'year',
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ export function convertBytesToHumanReadable(
|
|||
|
||||
export function makeHumanReadableStorage(
|
||||
bytes: number,
|
||||
|
||||
round: 'round-up' | 'round-down' = 'round-down'
|
||||
): string {
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
|
@ -139,6 +138,13 @@ export function getFamilyPlanAdmin(familyData: FamilyData): FamilyMember {
|
|||
}
|
||||
}
|
||||
|
||||
export function getTotalFamilyUsage(familyData: FamilyData): number {
|
||||
return familyData.members.reduce(
|
||||
(sum, currentMember) => sum + currentMember.usage,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
export function getLocalUserSubscription(): Subscription {
|
||||
return getData(LS_KEYS.SUBSCRIPTION);
|
||||
}
|
||||
|
|
|
@ -754,6 +754,7 @@ const englishConstants = {
|
|||
GB: 'GB',
|
||||
FREE_PLAN_OPTION_LABEL: 'Continue with free trial',
|
||||
FREE_PLAN_DESCRIPTION: '1 GB for 1 year',
|
||||
CURRENT_USAGE: (usage) => `Current usage is ${usage}`,
|
||||
};
|
||||
|
||||
export default englishConstants;
|
||||
|
|
|
@ -24,5 +24,5 @@ export function getUserAnonymizedID() {
|
|||
}
|
||||
|
||||
export function getLocalUserDetails(): UserDetails {
|
||||
return getData(LS_KEYS.USER_DETAILS);
|
||||
return getData(LS_KEYS.USER_DETAILS)?.value;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue