add subscription component

This commit is contained in:
Abhinav 2022-06-09 15:44:59 +05:30
parent 9e01516f5d
commit 03228664f6
8 changed files with 168 additions and 126 deletions

View file

@ -1,14 +1,13 @@
import { ClickIndicator } from './clickIndicator';
import { IndividualUsageSection } from './individualUsageSection';
import React, { useContext } from 'react';
import { Box, CircularProgress } from '@mui/material';
import Container from 'components/Container';
import React, { useContext, useMemo } from 'react';
import { Box } from '@mui/material';
import { UserDetails } from 'types/user';
import StorageSection from './storageSection';
import { GalleryContext } from 'pages/gallery';
import { FamilyUsageSection } from './familyUsageSection';
import { hasNonAdminFamilyMembers } from 'utils/billing';
import { hasNonAdminFamilyMembers, isPartOfFamily } from 'utils/billing';
interface Iprops {
userDetails: UserDetails;
closeSidebar: () => void;
@ -17,6 +16,29 @@ interface Iprops {
export default function SubscriptionCard({ userDetails }: Iprops) {
const { showPlanSelectorModal } = useContext(GalleryContext);
if (!userDetails) {
return <></>;
}
const totalUsage = useMemo(() => {
if (isPartOfFamily(userDetails.familyData)) {
return userDetails.familyData.members.reduce(
(sum, currentMember) => sum + currentMember.usage,
0
);
} else {
return userDetails.usage;
}
}, [userDetails]);
const totalStorage = useMemo(() => {
if (isPartOfFamily(userDetails.familyData)) {
return userDetails.familyData.storage;
} else {
return userDetails.subscription.storage;
}
}, [userDetails]);
return (
<Box
display="flex"
@ -27,13 +49,11 @@ export default function SubscriptionCard({ userDetails }: Iprops) {
style={{ position: 'absolute' }}
src="/subscription-card-background.png"
/>
{!userDetails ? (
<Container>
<CircularProgress />
</Container>
) : (
<Box zIndex={1} position={'relative'} height={148}>
<StorageSection userDetails={userDetails} />
<StorageSection
totalStorage={totalStorage}
totalUsage={totalUsage}
/>
{hasNonAdminFamilyMembers(userDetails.familyData) ? (
<FamilyUsageSection userDetails={userDetails} />
) : (
@ -41,7 +61,6 @@ export default function SubscriptionCard({ userDetails }: Iprops) {
)}
<ClickIndicator />
</Box>
)}
</Box>
);
}

View file

@ -3,7 +3,11 @@ import React from 'react';
import { convertBytesToHumanReadable } from 'utils/billing';
import constants from 'utils/strings/constants';
export default function StorageSection({ userDetails }) {
interface Iprops {
totalUsage: number;
totalStorage: number;
}
export default function StorageSection({ totalUsage, totalStorage }: Iprops) {
return (
<Box padding={2}>
<Typography variant="body2" color={'text.secondary'}>
@ -16,12 +20,12 @@ export default function StorageSection({ userDetails }) {
fontSize: '24px',
}}>
{`${convertBytesToHumanReadable(
userDetails.usage,
totalStorage - totalUsage,
1
)} of ${convertBytesToHumanReadable(
userDetails.subscription.storage,
)} ${constants.OF} ${convertBytesToHumanReadable(
totalStorage,
0
)}`}
)} ${constants.FREE}`}
</Typography>
</Box>
);

View file

@ -1,86 +0,0 @@
import React from 'react';
export default function SubscriptionStatus() {
return <div>SubscriptionStatus</div>;
{
// const { setDialogMessage } = useContext(AppContext);
// async function onLeaveFamilyClick() {
// try {
// await billingService.leaveFamily();
// closeSidebar();
// } catch (e) {
// setDialogMessage({
// title: constants.ERROR,
// close: { variant: 'danger' },
// content: constants.UNKNOWN_ERROR,
// });
// }
// }
/* {!hasNonAdminFamilyMembers(userDetails.familyData) ||
isFamilyAdmin(userDetails.familyData) ? (
<div style={{ color: '#959595' }}>
{isSubscriptionActive(userDetails.subscription) ? (
isOnFreePlan(userDetails.subscription) ? (
constants.FREE_SUBSCRIPTION_INFO(
userDetails.subscription?.expiryTime
)
) : isSubscriptionCancelled(
userDetails.subscription
) ? (
constants.RENEWAL_CANCELLED_SUBSCRIPTION_INFO(
userDetails.subscription?.expiryTime
)
) : (
constants.RENEWAL_ACTIVE_SUBSCRIPTION_INFO(
userDetails.subscription?.expiryTime
)
)
) : (
<p>{constants.SUBSCRIPTION_EXPIRED(onManageClick)}</p>
)}
<Button onClick={onManageClick}>
{isSubscribed(userDetails.subscription)
? constants.MANAGE
: constants.SUBSCRIBE}
</Button>
</div>
) : (
<div style={{ color: '#959595' }}>
{constants.FAMILY_PLAN_MANAGE_ADMIN_ONLY(
getFamilyPlanAdmin(userDetails.familyData)?.email
)}
<Button
onClick={() =>
setDialogMessage({
title: `${constants.LEAVE_FAMILY}`,
content: constants.LEAVE_FAMILY_CONFIRM,
staticBackdrop: true,
proceed: {
text: constants.LEAVE_FAMILY,
action: onLeaveFamilyClick,
variant: 'danger',
},
close: { text: constants.CANCEL },
})
}>
{constants.LEAVE_FAMILY}
</Button>
</div>
)}
{hasNonAdminFamilyMembers(userDetails.familyData)
? constants.FAMILY_USAGE_INFO(
userDetails.usage,
convertBytesToHumanReadable(
getStorage(userDetails.familyData)
)
)
: constants.USAGE_INFO(
userDetails.usage,
convertBytesToHumanReadable(
userDetails.subscription?.storage
)
)} */
}
}

View file

@ -0,0 +1,31 @@
import { Typography } from '@mui/material';
import React from 'react';
import {
isSubscriptionActive,
isOnFreePlan,
isSubscriptionCancelled,
} from 'utils/billing';
import constants from 'utils/strings/constants';
export function AdminSubscriptionStatus({
userDetails,
showPlanSelectorModal,
}) {
return (
<Typography
variant="body2"
color={'text.secondary'}
onClick={showPlanSelectorModal}>
{isSubscriptionActive(userDetails.subscription)
? isOnFreePlan(userDetails.subscription)
? constants.FREE_SUBSCRIPTION_INFO(
userDetails.subscription?.expiryTime
)
: isSubscriptionCancelled(userDetails.subscription) &&
constants.RENEWAL_CANCELLED_SUBSCRIPTION_INFO(
userDetails.subscription?.expiryTime
)
: constants.SUBSCRIPTION_EXPIRED_MESSAGE(showPlanSelectorModal)}
</Typography>
);
}

View file

@ -0,0 +1,27 @@
import { MemberSubscriptionStatus } from './member';
import { AdminSubscriptionStatus as AdminSubscriptionStatus } from './admin';
import { GalleryContext } from 'pages/gallery';
import React, { useContext } from 'react';
import { hasNonAdminFamilyMembers, isFamilyAdmin } from 'utils/billing';
import Box from '@mui/material/Box';
export default function SubscriptionStatus({ userDetails }) {
const { showPlanSelectorModal } = useContext(GalleryContext);
if (!userDetails) {
return <></>;
}
return (
<Box px={1}>
{!hasNonAdminFamilyMembers(userDetails.familyData) ||
isFamilyAdmin(userDetails.familyData) ? (
<AdminSubscriptionStatus
userDetails={userDetails}
showPlanSelectorModal={showPlanSelectorModal}
/>
) : (
<MemberSubscriptionStatus userDetails={userDetails} />
)}
</Box>
);
}

View file

@ -0,0 +1,46 @@
import { Button, Stack, Typography } from '@mui/material';
import { AppContext } from 'pages/_app';
import React, { useContext } from 'react';
import billingService from 'services/billingService';
import { getFamilyPlanAdmin } from 'utils/billing';
import constants from 'utils/strings/constants';
export function MemberSubscriptionStatus({ userDetails }) {
const { setDialogMessage } = useContext(AppContext);
async function onLeaveFamilyClick() {
try {
await billingService.leaveFamily();
} catch (e) {
setDialogMessage({
title: constants.ERROR,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
}
}
const confirmLeaveFamily = () =>
setDialogMessage({
title: `${constants.LEAVE_FAMILY}`,
content: constants.LEAVE_FAMILY_CONFIRM,
proceed: {
text: constants.LEAVE_FAMILY,
action: onLeaveFamilyClick,
variant: 'danger',
},
close: {
text: constants.CANCEL,
},
});
return (
<Stack spacing={1}>
<Typography variant="body2" color="text.secondary ">
{constants.FAMILY_PLAN_MANAGE_ADMIN_ONLY(
getFamilyPlanAdmin(userDetails.familyData)?.email
)}
</Typography>
<Button onClick={confirmLeaveFamily}>
{constants.LEAVE_FAMILY}
</Button>
</Stack>
);
}

View file

@ -1,20 +1,17 @@
import React, { useEffect } from 'react';
import { SpaceBetweenFlex } from 'components/Container';
import { PaddedDivider } from './styledComponents';
import SubscriptionCard from './SubscriptionCard';
import { getUserDetailsV2 } from 'services/userService';
import { UserDetails } from 'types/user';
import { LS_KEYS } from 'utils/storage/localStorage';
import { useLocalState } from 'hooks/useLocalState';
import { THEMES } from 'types/theme';
import ThemeSwitcher from './ThemeSwitcher';
import Typography from '@mui/material/Typography';
import SubscriptionStatus from './SubscriptionStatus';
import Stack from '@mui/material/Stack';
export default function UserDetailsSection({ sidebarView, closeSidebar }) {
const [userDetails, setUserDetails] = useLocalState<UserDetails>(
LS_KEYS.USER_DETAILS
);
const [theme, setTheme] = useLocalState<THEMES>(LS_KEYS.THEME, THEMES.DARK);
useEffect(() => {
if (!sidebarView) {
@ -28,16 +25,13 @@ export default function UserDetailsSection({ sidebarView, closeSidebar }) {
}, [sidebarView]);
return (
<>
<SpaceBetweenFlex px={1}>
<Stack spacing={1}>
<Typography>{userDetails?.email}</Typography>
<ThemeSwitcher theme={theme} setTheme={setTheme} />
</SpaceBetweenFlex>
<PaddedDivider invisible />
<SubscriptionCard
userDetails={userDetails}
closeSidebar={closeSidebar}
/>
</>
<SubscriptionStatus userDetails={userDetails} />
</Stack>
);
}

View file

@ -1,5 +1,6 @@
import { Box, Typography } from '@mui/material';
import Link from '@mui/material/Link';
import LinkButton from 'components/pages/gallery/LinkButton';
import { DotSeparator } from 'components/Sidebar/styledComponents';
import React from 'react';
import styled from 'styled-components';
@ -126,6 +127,12 @@ const englishConstants = {
UPLOADING_FILES: 'File upload',
FILE_NOT_UPLOADED_LIST: 'The following files were not uploaded',
SUBSCRIPTION_EXPIRED: 'Subscription expired',
SUBSCRIPTION_EXPIRED_MESSAGE: (onClick) => (
<>
Your subscription has expired, please{' '}
<LinkButton onClick={onClick}> renew </LinkButton>
</>
),
STORAGE_QUOTA_EXCEEDED: 'Storage limit exceeded',
INITIAL_LOAD_DELAY_WARNING: 'First load may take some time',
USER_DOES_NOT_EXIST: 'Sorry, could not find a user with that email',
@ -274,10 +281,8 @@ const englishConstants = {
FAMILY_PLAN_MANAGE_ADMIN_ONLY: (adminEmail) => (
<>
<p>
Only your family plan admin <strong>{adminEmail}</strong> can
change the plan
</p>
Only your family plan admin <strong>{adminEmail}</strong> can change
the plan
</>
),
RENEWAL_ACTIVE_SUBSCRIPTION_INFO: (expiryTime) => (
@ -777,6 +782,8 @@ const englishConstants = {
USED: 'used',
YOU: 'You',
FAMILY: 'Family',
FREE: 'free',
OF: 'of',
};
export default englishConstants;