Merge pull request #631 from ente-io/plan-selector-ui-fixes
Plan selector UI fixes
This commit is contained in:
commit
aaec3e0592
48
src/components/pages/gallery/PlanSelector/card/free.tsx
Normal file
48
src/components/pages/gallery/PlanSelector/card/free.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { Stack } from '@mui/material';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import React from 'react';
|
||||||
|
import constants from 'utils/strings/constants';
|
||||||
|
import { PeriodToggler } from '../periodToggler';
|
||||||
|
import Plans from '../plans';
|
||||||
|
|
||||||
|
export default function FreeSubscriptionPlanSelectorCard({
|
||||||
|
plans,
|
||||||
|
subscription,
|
||||||
|
closeModal,
|
||||||
|
planPeriod,
|
||||||
|
togglePeriod,
|
||||||
|
onPlanSelect,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography variant="h3" fontWeight={'bold'}>
|
||||||
|
{constants.CHOOSE_PLAN}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<Box>
|
||||||
|
<PeriodToggler
|
||||||
|
planPeriod={planPeriod}
|
||||||
|
togglePeriod={togglePeriod}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
mt={0.5}
|
||||||
|
color="text.secondary">
|
||||||
|
{constants.TWO_MONTHS_FREE}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Plans
|
||||||
|
plans={plans}
|
||||||
|
planPeriod={planPeriod}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
|
subscription={subscription}
|
||||||
|
closeModal={closeModal}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
import { PeriodToggler } from './periodToggler';
|
|
||||||
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import constants from 'utils/strings/constants';
|
import constants from 'utils/strings/constants';
|
||||||
import { Plan } from 'types/billing';
|
import { Plan } from 'types/billing';
|
||||||
|
@ -13,9 +12,8 @@ import {
|
||||||
hasPaypalSubscription,
|
hasPaypalSubscription,
|
||||||
getLocalUserSubscription,
|
getLocalUserSubscription,
|
||||||
hasPaidSubscription,
|
hasPaidSubscription,
|
||||||
convertBytesToGBs,
|
|
||||||
getTotalFamilyUsage,
|
getTotalFamilyUsage,
|
||||||
makeHumanReadableStorage,
|
isPartOfFamily,
|
||||||
} from 'utils/billing';
|
} from 'utils/billing';
|
||||||
import { reverseString } from 'utils/common';
|
import { reverseString } from 'utils/common';
|
||||||
import { GalleryContext } from 'pages/gallery';
|
import { GalleryContext } from 'pages/gallery';
|
||||||
|
@ -23,15 +21,13 @@ import billingService from 'services/billingService';
|
||||||
import { SetLoading } from 'types/gallery';
|
import { SetLoading } from 'types/gallery';
|
||||||
import { logError } from 'utils/sentry';
|
import { logError } from 'utils/sentry';
|
||||||
import { AppContext } from 'pages/_app';
|
import { AppContext } from 'pages/_app';
|
||||||
import Plans from './plans';
|
import { Stack } from '@mui/material';
|
||||||
import { Box, IconButton, Stack, Typography } from '@mui/material';
|
|
||||||
import { useLocalState } from 'hooks/useLocalState';
|
import { useLocalState } from 'hooks/useLocalState';
|
||||||
import { LS_KEYS } from 'utils/storage/localStorage';
|
import { LS_KEYS } from 'utils/storage/localStorage';
|
||||||
import { getLocalUserDetails } from 'utils/user';
|
import { getLocalUserDetails } from 'utils/user';
|
||||||
import { ManageSubscription } from './manageSubscription';
|
|
||||||
import { SpaceBetweenFlex } from 'components/Container';
|
|
||||||
import Close from '@mui/icons-material/Close';
|
|
||||||
import { PLAN_PERIOD } from 'constants/gallery';
|
import { PLAN_PERIOD } from 'constants/gallery';
|
||||||
|
import FreeSubscriptionPlanSelectorCard from './free';
|
||||||
|
import PaidSubscriptionPlanSelectorCard from './paid';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
closeModal: any;
|
closeModal: any;
|
||||||
|
@ -48,9 +44,11 @@ function PlanSelectorCard(props: Props) {
|
||||||
const galleryContext = useContext(GalleryContext);
|
const galleryContext = useContext(GalleryContext);
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
const totalFamilyUsage = useMemo(() => {
|
const usage = useMemo(() => {
|
||||||
const familyData = getLocalUserDetails()?.familyData;
|
const userDetails = getLocalUserDetails();
|
||||||
return familyData ? getTotalFamilyUsage(familyData) : 0;
|
return isPartOfFamily(userDetails?.familyData)
|
||||||
|
? getTotalFamilyUsage(userDetails?.familyData)
|
||||||
|
: userDetails.usage;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const togglePeriod = () => {
|
const togglePeriod = () => {
|
||||||
|
@ -158,84 +156,25 @@ function PlanSelectorCard(props: Props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack spacing={3} p={1.5}>
|
<Stack spacing={3} p={1.5}>
|
||||||
<Box py={0.5} px={1.5}>
|
{hasPaidSubscription(subscription) ? (
|
||||||
{hasPaidSubscription(subscription) ? (
|
<PaidSubscriptionPlanSelectorCard
|
||||||
<SpaceBetweenFlex>
|
plans={plans}
|
||||||
<Box>
|
|
||||||
<Typography variant="h3" fontWeight={'bold'}>
|
|
||||||
{constants.SUBSCRIPTION}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
color={'text.secondary'}>
|
|
||||||
{convertBytesToGBs(subscription.storage, 2)}{' '}
|
|
||||||
{constants.GB}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<IconButton onClick={props.closeModal}>
|
|
||||||
<Close />
|
|
||||||
</IconButton>
|
|
||||||
</SpaceBetweenFlex>
|
|
||||||
) : (
|
|
||||||
<Typography variant="h3" fontWeight={'bold'}>
|
|
||||||
{constants.CHOOSE_PLAN}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
{totalFamilyUsage > 0 && (
|
|
||||||
<Box px={1.5}>
|
|
||||||
<Typography
|
|
||||||
color={'text.secondary'}
|
|
||||||
fontWeight={'bold'}>
|
|
||||||
{constants.CURRENT_USAGE(
|
|
||||||
makeHumanReadableStorage(totalFamilyUsage)
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
<Box>
|
|
||||||
<Stack
|
|
||||||
spacing={3}
|
|
||||||
border={(theme) =>
|
|
||||||
hasPaidSubscription(subscription) &&
|
|
||||||
`1px solid ${theme.palette.divider}`
|
|
||||||
}
|
|
||||||
p={1.5}
|
|
||||||
borderRadius={(theme) =>
|
|
||||||
`${theme.shape.borderRadius}px`
|
|
||||||
}>
|
|
||||||
<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}
|
|
||||||
closeModal={props.closeModal}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
{hasPaidSubscription(subscription) && (
|
|
||||||
<Box py={1} px={1.5}>
|
|
||||||
<Typography color={'text.secondary'}>
|
|
||||||
{constants.RENEWAL_ACTIVE_SUBSCRIPTION_INFO(
|
|
||||||
subscription.expiryTime
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
{hasPaidSubscription(subscription) && (
|
|
||||||
<ManageSubscription
|
|
||||||
subscription={subscription}
|
subscription={subscription}
|
||||||
closeModal={props.closeModal}
|
closeModal={props.closeModal}
|
||||||
|
planPeriod={planPeriod}
|
||||||
|
togglePeriod={togglePeriod}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
setLoading={props.setLoading}
|
setLoading={props.setLoading}
|
||||||
|
usage={usage}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FreeSubscriptionPlanSelectorCard
|
||||||
|
plans={plans}
|
||||||
|
subscription={subscription}
|
||||||
|
closeModal={props.closeModal}
|
||||||
|
planPeriod={planPeriod}
|
||||||
|
togglePeriod={togglePeriod}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
93
src/components/pages/gallery/PlanSelector/card/paid.tsx
Normal file
93
src/components/pages/gallery/PlanSelector/card/paid.tsx
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import Close from '@mui/icons-material/Close';
|
||||||
|
import { IconButton, Stack } from '@mui/material';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { SpaceBetweenFlex } from 'components/Container';
|
||||||
|
import React from 'react';
|
||||||
|
import { convertBytesToGBs } from 'utils/billing';
|
||||||
|
import constants from 'utils/strings/constants';
|
||||||
|
import { ManageSubscription } from '../manageSubscription';
|
||||||
|
import { PeriodToggler } from '../periodToggler';
|
||||||
|
import Plans from '../plans';
|
||||||
|
|
||||||
|
export default function PaidSubscriptionPlanSelectorCard({
|
||||||
|
plans,
|
||||||
|
subscription,
|
||||||
|
closeModal,
|
||||||
|
usage,
|
||||||
|
planPeriod,
|
||||||
|
togglePeriod,
|
||||||
|
onPlanSelect,
|
||||||
|
setLoading,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box px={1.5} py={0.5}>
|
||||||
|
<SpaceBetweenFlex>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h3" fontWeight={'bold'}>
|
||||||
|
{constants.SUBSCRIPTION}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color={'text.secondary'}>
|
||||||
|
{convertBytesToGBs(subscription.storage, 2)}{' '}
|
||||||
|
{constants.GB}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<IconButton onClick={closeModal}>
|
||||||
|
<Close />
|
||||||
|
</IconButton>
|
||||||
|
</SpaceBetweenFlex>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box px={1.5}>
|
||||||
|
<Typography color={'text.secondary'} fontWeight={'bold'}>
|
||||||
|
{constants.CURRENT_USAGE(
|
||||||
|
`${convertBytesToGBs(usage, 2)} ${constants.GB}`
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Stack
|
||||||
|
spacing={3}
|
||||||
|
border={(theme) => `1px solid ${theme.palette.divider}`}
|
||||||
|
p={1.5}
|
||||||
|
borderRadius={(theme) => `${theme.shape.borderRadius}px`}>
|
||||||
|
<Box>
|
||||||
|
<PeriodToggler
|
||||||
|
planPeriod={planPeriod}
|
||||||
|
togglePeriod={togglePeriod}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
mt={0.5}
|
||||||
|
color="text.secondary">
|
||||||
|
{constants.TWO_MONTHS_FREE}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Plans
|
||||||
|
plans={plans}
|
||||||
|
planPeriod={planPeriod}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
|
subscription={subscription}
|
||||||
|
closeModal={closeModal}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Box py={1} px={1.5}>
|
||||||
|
<Typography color={'text.secondary'}>
|
||||||
|
{constants.RENEWAL_ACTIVE_SUBSCRIPTION_INFO(
|
||||||
|
subscription.expiryTime
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<ManageSubscription
|
||||||
|
subscription={subscription}
|
||||||
|
closeModal={closeModal}
|
||||||
|
setLoading={setLoading}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ const CustomToggleButton = styled(ToggleButton)(({ theme }) => ({
|
||||||
padding: '12px 16px',
|
padding: '12px 16px',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
backgroundColor: theme.palette.fill.dark,
|
backgroundColor: theme.palette.fill.dark,
|
||||||
|
border: `1px solid transparent`,
|
||||||
color: theme.palette.text.disabled,
|
color: theme.palette.text.disabled,
|
||||||
'&.Mui-selected': {
|
'&.Mui-selected': {
|
||||||
backgroundColor: theme.palette.accent.main,
|
backgroundColor: theme.palette.accent.main,
|
||||||
|
|
|
@ -79,16 +79,24 @@ export function PlanRow({
|
||||||
</FlexWrapper>
|
</FlexWrapper>
|
||||||
</TopAlignedFluidContainer>
|
</TopAlignedFluidContainer>
|
||||||
<Box width="136px">
|
<Box width="136px">
|
||||||
<PlanButton size="large" onClick={handleClick}>
|
<PlanButton
|
||||||
<Box>
|
sx={{
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
borderTopLeftRadius: 0,
|
||||||
|
borderBottomLeftRadius: 0,
|
||||||
|
}}
|
||||||
|
size="large"
|
||||||
|
onClick={handleClick}>
|
||||||
|
<Box textAlign={'right'}>
|
||||||
<Typography fontWeight={'bold'} variant="h4">
|
<Typography fontWeight={'bold'} variant="h4">
|
||||||
{plan.price}{' '}
|
{plan.price}{' '}
|
||||||
</Typography>{' '}
|
</Typography>{' '}
|
||||||
<Typography color="text.secondary" variant="body2">
|
<Typography color="text.secondary" variant="body2">
|
||||||
/ $
|
{`/ ${
|
||||||
{plan.period === PLAN_PERIOD.MONTH
|
plan.period === PLAN_PERIOD.MONTH
|
||||||
? constants.MONTH_SHORT
|
? constants.MONTH_SHORT
|
||||||
: constants.YEAR_SHORT}
|
: constants.YEAR
|
||||||
|
}`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</PlanButton>
|
</PlanButton>
|
||||||
|
|
|
@ -279,7 +279,7 @@ const englishConstants = {
|
||||||
FAMILY_SUBSCRIPTION_INFO: 'You are on a family plan managed by',
|
FAMILY_SUBSCRIPTION_INFO: 'You are on a family plan managed by',
|
||||||
|
|
||||||
RENEWAL_ACTIVE_SUBSCRIPTION_INFO: (expiryTime) => (
|
RENEWAL_ACTIVE_SUBSCRIPTION_INFO: (expiryTime) => (
|
||||||
<>Renew on {dateString(expiryTime)}</>
|
<>Renews on {dateString(expiryTime)}</>
|
||||||
),
|
),
|
||||||
|
|
||||||
RENEWAL_CANCELLED_SUBSCRIPTION_INFO: (expiryTime) => (
|
RENEWAL_CANCELLED_SUBSCRIPTION_INFO: (expiryTime) => (
|
||||||
|
@ -750,7 +750,7 @@ const englishConstants = {
|
||||||
FREE: 'free',
|
FREE: 'free',
|
||||||
OF: 'of',
|
OF: 'of',
|
||||||
MONTH_SHORT: 'mo',
|
MONTH_SHORT: 'mo',
|
||||||
YEAR_SHORT: 'yr',
|
YEAR: 'year',
|
||||||
FAMILY_PLAN: 'Family plan',
|
FAMILY_PLAN: 'Family plan',
|
||||||
DOWNLOAD_LOGS: 'Download logs',
|
DOWNLOAD_LOGS: 'Download logs',
|
||||||
DOWNLOAD_LOGS_MESSAGE: () => (
|
DOWNLOAD_LOGS_MESSAGE: () => (
|
||||||
|
|
Loading…
Reference in a new issue