add subscription details to sidebar
This commit is contained in:
parent
fa802e253c
commit
fde43182ac
95
src/components/Sidebar/SubscriptionDetails.tsx
Normal file
95
src/components/Sidebar/SubscriptionDetails.tsx
Normal file
|
@ -0,0 +1,95 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
CircularProgress,
|
||||
LinearProgress,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { FlexWrapper, SpaceBetweenFlex } from 'components/Container';
|
||||
import { UserDetails } from 'types/user';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { formatDateShort } from 'utils/time';
|
||||
import { convertBytesToHumanReadable } from 'utils/billing';
|
||||
|
||||
interface Iprops {
|
||||
userDetails: UserDetails;
|
||||
}
|
||||
export default function SubscriptionDetails({ userDetails }: Iprops) {
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection={'column'}
|
||||
height={160}
|
||||
bgcolor="accent.main"
|
||||
borderRadius={'8px'}
|
||||
position={'relative'}>
|
||||
{userDetails ? (
|
||||
<>
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection={'column'}
|
||||
padding="16px"
|
||||
height="96px">
|
||||
<SpaceBetweenFlex>
|
||||
<Typography variant="subtitle2">
|
||||
Current Plan
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{ color: 'text.secondary' }}>
|
||||
{`${constants.ENDS} ${formatDateShort(
|
||||
userDetails.subscription.expiryTime / 1000
|
||||
)}`}
|
||||
</Typography>
|
||||
</SpaceBetweenFlex>
|
||||
<Typography
|
||||
sx={{ fontWeight: '700', fontSize: '24px' }}>
|
||||
{convertBytesToHumanReadable(
|
||||
userDetails.subscription.storage,
|
||||
0
|
||||
)}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
position={'absolute'}
|
||||
right="17px"
|
||||
top="10px"
|
||||
component={'img'}
|
||||
src="/images/locker.png"
|
||||
/>
|
||||
<Box
|
||||
position={'relative'}
|
||||
zIndex="100"
|
||||
height="64px"
|
||||
borderRadius={'0 0 8px 8px'}
|
||||
bgcolor="accent.dark"
|
||||
padding="16px">
|
||||
<LinearProgress
|
||||
sx={{ bgcolor: 'text.secondary' }}
|
||||
variant="determinate"
|
||||
value={70}
|
||||
/>
|
||||
<SpaceBetweenFlex style={{ marginTop: '8px' }}>
|
||||
<Typography variant="caption">
|
||||
{`${convertBytesToHumanReadable(
|
||||
userDetails.usage,
|
||||
1
|
||||
)} of ${convertBytesToHumanReadable(
|
||||
userDetails.subscription.storage,
|
||||
0
|
||||
)}`}
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{`${userDetails.fileCount} Photos`}
|
||||
</Typography>
|
||||
</SpaceBetweenFlex>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<FlexWrapper style={{ flex: '1', justifyContent: 'center' }}>
|
||||
<CircularProgress />
|
||||
</FlexWrapper>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
|
@ -1,16 +1,9 @@
|
|||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
|
||||
import { LS_KEYS, setData } from 'utils/storage/localStorage';
|
||||
import { getToken } from 'utils/common/key';
|
||||
import { getEndpoint } from 'utils/common/apiUtil';
|
||||
import {
|
||||
isSubscriptionActive,
|
||||
getUserSubscription,
|
||||
isOnFreePlan,
|
||||
isSubscriptionCancelled,
|
||||
isSubscribed,
|
||||
convertBytesToHumanReadable,
|
||||
} from 'utils/billing';
|
||||
import { convertBytesToHumanReadable } from 'utils/billing';
|
||||
|
||||
import isElectron from 'is-electron';
|
||||
import { Collection } from 'types/collection';
|
||||
|
@ -19,24 +12,25 @@ import LinkButton from '../pages/gallery/LinkButton';
|
|||
import { downloadApp } from 'utils/common';
|
||||
import { getUserDetails, logoutUser } from 'services/userService';
|
||||
import { SetDialogMessage } from '../MessageDialog';
|
||||
import EnteSpinner from '../EnteSpinner';
|
||||
import RecoveryKeyModal from '../RecoveryKeyModal';
|
||||
import TwoFactorModal from '../TwoFactorModal';
|
||||
import ExportModal from '../ExportModal';
|
||||
import { GalleryContext } from 'pages/gallery';
|
||||
import InProgressIcon from '../icons/InProgressIcon';
|
||||
import exportService from 'services/exportService';
|
||||
import { Subscription } from 'types/billing';
|
||||
import { PAGES } from 'constants/pages';
|
||||
import { ARCHIVE_SECTION, TRASH_SECTION } from 'constants/collection';
|
||||
import FixLargeThumbnails from '../FixLargeThumbnail';
|
||||
import { SetLoading } from 'types/gallery';
|
||||
import { downloadAsFile } from 'utils/file';
|
||||
import { getUploadLogs, logUploadInfo } from 'utils/upload';
|
||||
import { Box, Divider, Drawer, Typography } from '@mui/material';
|
||||
import { Divider, Drawer, Typography } from '@mui/material';
|
||||
import { default as MuiStyled } from '@mui/styled-engine';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import ThemeToggler from './ThemeToggler';
|
||||
import SubscriptionDetails from './SubscriptionDetails';
|
||||
import { SpaceBetweenFlex } from 'components/Container';
|
||||
import { UserDetails } from 'types/user';
|
||||
import { getLocalUserDetails } from 'utils/user';
|
||||
interface Props {
|
||||
collections: Collection[];
|
||||
setDialogMessage: SetDialogMessage;
|
||||
|
@ -50,7 +44,7 @@ export enum THEMES {
|
|||
|
||||
const DrawerSidebar = MuiStyled(Drawer)(() => ({
|
||||
'& .MuiPaper-root': {
|
||||
width: '300px',
|
||||
width: '320px',
|
||||
padding: '20px',
|
||||
},
|
||||
}));
|
||||
|
@ -61,12 +55,9 @@ const WidderDivider = MuiStyled(Divider)(() => ({
|
|||
}));
|
||||
|
||||
export default function Sidebar(props: Props) {
|
||||
const [usage, SetUsage] = useState<string>(null);
|
||||
const [user, setUser] = useState(null);
|
||||
const [subscription, setSubscription] = useState<Subscription>(null);
|
||||
const [userDetails, setUserDetails] = useState<UserDetails>(null);
|
||||
useEffect(() => {
|
||||
setUser(getData(LS_KEYS.USER));
|
||||
setSubscription(getUserSubscription());
|
||||
setUserDetails(getLocalUserDetails());
|
||||
}, []);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [recoverModalView, setRecoveryModalView] = useState(false);
|
||||
|
@ -78,18 +69,9 @@ export default function Sidebar(props: Props) {
|
|||
|
||||
useEffect(() => {
|
||||
const main = async () => {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
const userDetails = await getUserDetails();
|
||||
setUser({ ...user, email: userDetails.email });
|
||||
SetUsage(convertBytesToHumanReadable(userDetails.usage));
|
||||
setSubscription(userDetails.subscription);
|
||||
setData(LS_KEYS.USER, {
|
||||
...getData(LS_KEYS.USER),
|
||||
email: userDetails.email,
|
||||
});
|
||||
setData(LS_KEYS.SUBSCRIPTION, userDetails.subscription);
|
||||
setUserDetails(userDetails);
|
||||
setData(LS_KEYS.USER_DETAILS, userDetails);
|
||||
};
|
||||
main();
|
||||
}, [isOpen]);
|
||||
|
@ -138,10 +120,6 @@ export default function Sidebar(props: Props) {
|
|||
};
|
||||
|
||||
const router = useRouter();
|
||||
function onManageClick() {
|
||||
setIsOpen(false);
|
||||
galleryContext.showPlanSelectorModal();
|
||||
}
|
||||
|
||||
return (
|
||||
<DrawerSidebar
|
||||
|
@ -154,86 +132,14 @@ export default function Sidebar(props: Props) {
|
|||
{constants.ENTE}
|
||||
</Typography>
|
||||
<WidderDivider />
|
||||
<Box
|
||||
display="flex"
|
||||
mb="10px"
|
||||
mt="10px"
|
||||
alignItems="center"
|
||||
justifyContent={'space-between'}>
|
||||
<Typography>{user?.email}</Typography>
|
||||
|
||||
<SpaceBetweenFlex style={{ marginBottom: '20px' }}>
|
||||
<Typography>{userDetails?.email}</Typography>
|
||||
<ThemeToggler theme={theme} setTheme={setTheme} />
|
||||
</Box>
|
||||
<div style={{}}></div>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
overflow: 'auto',
|
||||
outline: 'none',
|
||||
paddingTop: '0',
|
||||
}}>
|
||||
<div style={{ outline: 'none' }}>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<h5 style={{ margin: '4px 0 12px 2px' }}>
|
||||
{constants.SUBSCRIPTION_PLAN}
|
||||
</h5>
|
||||
</div>
|
||||
<div style={{ color: '#959595' }}>
|
||||
{isSubscriptionActive(subscription) ? (
|
||||
isOnFreePlan(subscription) ? (
|
||||
constants.FREE_SUBSCRIPTION_INFO(
|
||||
subscription?.expiryTime
|
||||
)
|
||||
) : isSubscriptionCancelled(subscription) ? (
|
||||
constants.RENEWAL_CANCELLED_SUBSCRIPTION_INFO(
|
||||
subscription?.expiryTime
|
||||
)
|
||||
) : (
|
||||
constants.RENEWAL_ACTIVE_SUBSCRIPTION_INFO(
|
||||
subscription?.expiryTime
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<p>{constants.SUBSCRIPTION_EXPIRED}</p>
|
||||
)}
|
||||
<Button
|
||||
variant="outline-success"
|
||||
block
|
||||
size="sm"
|
||||
onClick={onManageClick}>
|
||||
{isSubscribed(subscription)
|
||||
? constants.MANAGE
|
||||
: constants.SUBSCRIBE}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ outline: 'none', marginTop: '30px' }} />
|
||||
<div>
|
||||
<h5 style={{ marginBottom: '12px' }}>
|
||||
{constants.USAGE_DETAILS}
|
||||
</h5>
|
||||
<div style={{ color: '#959595' }}>
|
||||
{usage ? (
|
||||
constants.USAGE_INFO(
|
||||
usage,
|
||||
convertBytesToHumanReadable(
|
||||
subscription?.storage
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<EnteSpinner
|
||||
style={{
|
||||
borderWidth: '2px',
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Divider />
|
||||
</SpaceBetweenFlex>
|
||||
<SubscriptionDetails userDetails={userDetails} />
|
||||
|
||||
<WidderDivider />
|
||||
|
||||
<LinkButton
|
||||
style={{ marginTop: '30px' }}
|
||||
onClick={() => {
|
||||
|
@ -331,7 +237,9 @@ export default function Sidebar(props: Props) {
|
|||
<ExportModal
|
||||
show={exportModalView}
|
||||
onHide={() => setExportModalView(false)}
|
||||
usage={usage}
|
||||
usage={convertBytesToHumanReadable(
|
||||
userDetails?.usage ?? 0
|
||||
)}
|
||||
/>
|
||||
<LinkButton
|
||||
style={{ marginTop: '30px' }}
|
||||
|
@ -375,9 +283,7 @@ export default function Sidebar(props: Props) {
|
|||
proceed: {
|
||||
text: constants.DELETE_ACCOUNT,
|
||||
action: () => {
|
||||
initiateEmail(
|
||||
'account-deletion@ente.io'
|
||||
);
|
||||
initiateEmail('account-deletion@ente.io');
|
||||
},
|
||||
variant: 'danger',
|
||||
},
|
||||
|
@ -405,7 +311,6 @@ export default function Sidebar(props: Props) {
|
|||
{constants.DOWNLOAD_UPLOAD_LOGS}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DrawerSidebar>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ export enum LS_KEYS {
|
|||
LIVE_PHOTO_INFO_SHOWN_COUNT = 'livePhotoInfoShownCount',
|
||||
FAILED_UPLOADS = 'failedUploads',
|
||||
LOGS = 'logs',
|
||||
USER_DETAILS = 'userDetails',
|
||||
}
|
||||
|
||||
export const setData = (key: LS_KEYS, value: object) => {
|
||||
|
|
|
@ -718,6 +718,7 @@ const englishConstants = {
|
|||
ALL_ALBUMS: 'All Albums',
|
||||
PHOTOS: 'Photos',
|
||||
ENTE: 'ente',
|
||||
ENDS: 'Ends',
|
||||
};
|
||||
|
||||
export default englishConstants;
|
||||
|
|
|
@ -15,6 +15,15 @@ export function dateStringWithMMH(unixTimeInMicroSeconds: number): string {
|
|||
});
|
||||
}
|
||||
|
||||
export function formatDateShort(date: number | Date) {
|
||||
const dateTimeFormat = new Intl.DateTimeFormat('en-IN', {
|
||||
year: '2-digit',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
});
|
||||
return dateTimeFormat.format(date);
|
||||
}
|
||||
|
||||
export function getUnixTimeInMicroSecondsWithDelta(delta: TimeDelta): number {
|
||||
let currentDate = new Date();
|
||||
if (delta?.hours) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { UserDetails } from 'types/user';
|
||||
import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
|
||||
|
||||
export function makeID(length) {
|
||||
|
@ -21,3 +22,7 @@ export function getUserAnonymizedID() {
|
|||
}
|
||||
return anonymizeUserID;
|
||||
}
|
||||
|
||||
export function getLocalUserDetails(): UserDetails {
|
||||
return getData(LS_KEYS.USER_DETAILS);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue