diff --git a/src/components/Sidebar/SubscriptionCard/index.tsx b/src/components/Sidebar/SubscriptionCard/index.tsx index 34478ec9a..c38554053 100644 --- a/src/components/Sidebar/SubscriptionCard/index.tsx +++ b/src/components/Sidebar/SubscriptionCard/index.tsx @@ -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 ( - {!userDetails ? ( - - - - ) : ( - - - {hasNonAdminFamilyMembers(userDetails.familyData) ? ( - - ) : ( - - )} - - - )} + + + {hasNonAdminFamilyMembers(userDetails.familyData) ? ( + + ) : ( + + )} + + ); } diff --git a/src/components/Sidebar/SubscriptionCard/storageSection.tsx b/src/components/Sidebar/SubscriptionCard/storageSection.tsx index 470748512..6fd313ec6 100644 --- a/src/components/Sidebar/SubscriptionCard/storageSection.tsx +++ b/src/components/Sidebar/SubscriptionCard/storageSection.tsx @@ -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 ( @@ -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}`} ); diff --git a/src/components/Sidebar/SubscriptionStatus.tsx b/src/components/Sidebar/SubscriptionStatus.tsx deleted file mode 100644 index 8ceed3ca4..000000000 --- a/src/components/Sidebar/SubscriptionStatus.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import React from 'react'; - -export default function SubscriptionStatus() { - return
SubscriptionStatus
; - - { - // 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) ? ( -
- {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 - ) - ) - ) : ( -

{constants.SUBSCRIPTION_EXPIRED(onManageClick)}

- )} - -
- ) : ( -
- {constants.FAMILY_PLAN_MANAGE_ADMIN_ONLY( - getFamilyPlanAdmin(userDetails.familyData)?.email - )} - -
- )} - - {hasNonAdminFamilyMembers(userDetails.familyData) - ? constants.FAMILY_USAGE_INFO( - userDetails.usage, - convertBytesToHumanReadable( - getStorage(userDetails.familyData) - ) - ) - : constants.USAGE_INFO( - userDetails.usage, - convertBytesToHumanReadable( - userDetails.subscription?.storage - ) - )} */ - } -} diff --git a/src/components/Sidebar/SubscriptionStatus/admin.tsx b/src/components/Sidebar/SubscriptionStatus/admin.tsx new file mode 100644 index 000000000..ee046f1e2 --- /dev/null +++ b/src/components/Sidebar/SubscriptionStatus/admin.tsx @@ -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 ( + + {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)} + + ); +} diff --git a/src/components/Sidebar/SubscriptionStatus/index.tsx b/src/components/Sidebar/SubscriptionStatus/index.tsx new file mode 100644 index 000000000..6cd7b15c4 --- /dev/null +++ b/src/components/Sidebar/SubscriptionStatus/index.tsx @@ -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 ( + + {!hasNonAdminFamilyMembers(userDetails.familyData) || + isFamilyAdmin(userDetails.familyData) ? ( + + ) : ( + + )} + + ); +} diff --git a/src/components/Sidebar/SubscriptionStatus/member.tsx b/src/components/Sidebar/SubscriptionStatus/member.tsx new file mode 100644 index 000000000..c5a4dc82c --- /dev/null +++ b/src/components/Sidebar/SubscriptionStatus/member.tsx @@ -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 ( + + + {constants.FAMILY_PLAN_MANAGE_ADMIN_ONLY( + getFamilyPlanAdmin(userDetails.familyData)?.email + )} + + + + ); +} diff --git a/src/components/Sidebar/userDetailsSection.tsx b/src/components/Sidebar/userDetailsSection.tsx index b3edf2cc2..f08fcef2d 100644 --- a/src/components/Sidebar/userDetailsSection.tsx +++ b/src/components/Sidebar/userDetailsSection.tsx @@ -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( LS_KEYS.USER_DETAILS ); - const [theme, setTheme] = useLocalState(LS_KEYS.THEME, THEMES.DARK); useEffect(() => { if (!sidebarView) { @@ -28,16 +25,13 @@ export default function UserDetailsSection({ sidebarView, closeSidebar }) { }, [sidebarView]); return ( - <> - - {userDetails?.email} - - - + + {userDetails?.email} - + + ); } diff --git a/src/utils/strings/englishConstants.tsx b/src/utils/strings/englishConstants.tsx index ff4cb9faf..72d5735d4 100644 --- a/src/utils/strings/englishConstants.tsx +++ b/src/utils/strings/englishConstants.tsx @@ -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{' '} + renew + + ), 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) => ( <> -

- Only your family plan admin {adminEmail} can - change the plan -

+ Only your family plan admin {adminEmail} 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;