Upgrade dialog looks nice now
This commit is contained in:
parent
695c1349e8
commit
4092f7fd51
9 changed files with 160 additions and 85 deletions
|
@ -199,6 +199,13 @@ export const formatBytes = (bytes, decimals = 2) => {
|
|||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
export const formatNumber = (n) => {
|
||||
if (n % 1000 === 0) {
|
||||
return `${n/1000}k`;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
export const openUrl = (url) => {
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
|||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import {Alert, CardActionArea, CardContent, useMediaQuery} from "@mui/material";
|
||||
import {Alert, CardActionArea, CardContent, ListItem, useMediaQuery} from "@mui/material";
|
||||
import theme from "./theme";
|
||||
import DialogFooter from "./DialogFooter";
|
||||
import Button from "@mui/material/Button";
|
||||
|
@ -13,16 +13,20 @@ import {useContext, useEffect, useState} from "react";
|
|||
import Card from "@mui/material/Card";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import {AccountContext} from "./App";
|
||||
import {formatShortDate} from "../app/utils";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {formatBytes, formatNumber, formatShortDate} from "../app/utils";
|
||||
import {Trans, useTranslation} from "react-i18next";
|
||||
import subscriptionManager from "../app/SubscriptionManager";
|
||||
import List from "@mui/material/List";
|
||||
import {Check} from "@mui/icons-material";
|
||||
import ListItemIcon from "@mui/material/ListItemIcon";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
|
||||
const UpgradeDialog = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const { account } = useContext(AccountContext);
|
||||
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const [tiers, setTiers] = useState(null);
|
||||
const [newTier, setNewTier] = useState(account?.tier?.code || null);
|
||||
const [newTier, setNewTier] = useState(account?.tier?.code); // May be undefined
|
||||
const [errorText, setErrorText] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -35,22 +39,22 @@ const UpgradeDialog = (props) => {
|
|||
return <></>;
|
||||
}
|
||||
|
||||
const currentTier = account.tier?.code || null;
|
||||
const currentTier = account.tier?.code; // May be undefined
|
||||
let action, submitButtonLabel, submitButtonEnabled;
|
||||
if (currentTier === newTier) {
|
||||
submitButtonLabel = "Update subscription";
|
||||
submitButtonLabel = t("account_upgrade_dialog_button_update_subscription");
|
||||
submitButtonEnabled = false;
|
||||
action = null;
|
||||
} else if (currentTier === null) {
|
||||
submitButtonLabel = "Pay $5 now and subscribe";
|
||||
} else if (!currentTier) {
|
||||
submitButtonLabel = t("account_upgrade_dialog_button_pay_now");
|
||||
submitButtonEnabled = true;
|
||||
action = Action.CREATE;
|
||||
} else if (newTier === null) {
|
||||
submitButtonLabel = "Cancel subscription";
|
||||
} else if (!newTier) {
|
||||
submitButtonLabel = t("account_upgrade_dialog_button_cancel_subscription");
|
||||
submitButtonEnabled = true;
|
||||
action = Action.CANCEL;
|
||||
} else {
|
||||
submitButtonLabel = "Update subscription";
|
||||
submitButtonLabel = t("account_upgrade_dialog_button_update_subscription");
|
||||
submitButtonEnabled = true;
|
||||
action = Action.UPDATE;
|
||||
}
|
||||
|
@ -76,7 +80,13 @@ const UpgradeDialog = (props) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Dialog open={props.open} onClose={props.onCancel} maxWidth="md" fullScreen={fullScreen}>
|
||||
<Dialog
|
||||
open={props.open}
|
||||
onClose={props.onCancel}
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
fullScreen={fullScreen}
|
||||
>
|
||||
<DialogTitle>{t("account_upgrade_dialog_title")}</DialogTitle>
|
||||
<DialogContent>
|
||||
<div style={{
|
||||
|
@ -85,33 +95,25 @@ const UpgradeDialog = (props) => {
|
|||
marginBottom: "8px",
|
||||
width: "100%"
|
||||
}}>
|
||||
<TierCard
|
||||
code={null}
|
||||
name={t("account_usage_tier_free")}
|
||||
price={null}
|
||||
selected={newTier === null}
|
||||
onClick={() => setNewTier(null)}
|
||||
/>
|
||||
{tiers.map(tier =>
|
||||
<TierCard
|
||||
key={`tierCard${tier.code}`}
|
||||
code={tier.code}
|
||||
name={tier.name}
|
||||
price={tier.price}
|
||||
features={tier.features}
|
||||
selected={newTier === tier.code}
|
||||
onClick={() => setNewTier(tier.code)}
|
||||
key={`tierCard${tier.code || '_free'}`}
|
||||
tier={tier}
|
||||
selected={newTier === tier.code} // tier.code may be undefined!
|
||||
onClick={() => setNewTier(tier.code)} // tier.code may be undefined!
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{action === Action.CANCEL &&
|
||||
<Alert severity="warning">
|
||||
{t("account_upgrade_dialog_cancel_warning", { date: formatShortDate(account.billing.paid_until) })}
|
||||
<Trans
|
||||
i18nKey="account_upgrade_dialog_cancel_warning"
|
||||
values={{ date: formatShortDate(account.billing.paid_until) }} />
|
||||
</Alert>
|
||||
}
|
||||
{action === Action.UPDATE &&
|
||||
{currentTier && (!action || action === Action.UPDATE) &&
|
||||
<Alert severity="info">
|
||||
{t("account_upgrade_dialog_proration_info")}
|
||||
<Trans i18nKey="account_upgrade_dialog_proration_info" />
|
||||
</Alert>
|
||||
}
|
||||
</DialogContent>
|
||||
|
@ -124,12 +126,18 @@ const UpgradeDialog = (props) => {
|
|||
};
|
||||
|
||||
const TierCard = (props) => {
|
||||
const cardStyle = (props.selected) ? { background: "#eee", border: "2px solid #338574" } : {};
|
||||
const { t } = useTranslation();
|
||||
const cardStyle = (props.selected) ? { background: "#eee", border: "2px solid #338574" } : { border: "2px solid transparent" };
|
||||
const tier = props.tier;
|
||||
|
||||
return (
|
||||
<Card sx={{
|
||||
m: 1,
|
||||
minWidth: "190px",
|
||||
maxWidth: "250px",
|
||||
flexGrow: 1,
|
||||
flexShrink: 1,
|
||||
flexBasis: 0,
|
||||
"&:first-child": { ml: 0 },
|
||||
"&:last-child": { mr: 0 },
|
||||
...cardStyle
|
||||
|
@ -145,19 +153,21 @@ const TierCard = (props) => {
|
|||
background: "#338574",
|
||||
color: "white",
|
||||
borderRadius: "3px",
|
||||
}}>Selected</div>
|
||||
}}>{t("account_upgrade_dialog_tier_selected_label")}</div>
|
||||
}
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
{props.name}
|
||||
<Typography variant="h5" component="div">
|
||||
{tier.name || t("account_usage_tier_free")}
|
||||
</Typography>
|
||||
{props.features &&
|
||||
<Typography variant="body2" color="text.secondary" sx={{whiteSpace: "pre-wrap"}}>
|
||||
{props.features}
|
||||
</Typography>
|
||||
}
|
||||
{props.price &&
|
||||
<Typography variant="subtitle1" sx={{mt: 1}}>
|
||||
{props.price} / month
|
||||
<List dense>
|
||||
{tier.limits.reservations > 0 && <FeatureItem>{t("account_upgrade_dialog_tier_features_reservations", { reservations: tier.limits.reservations })}</FeatureItem>}
|
||||
<FeatureItem>{t("account_upgrade_dialog_tier_features_messages", { messages: formatNumber(tier.limits.messages) })}</FeatureItem>
|
||||
<FeatureItem>{t("account_upgrade_dialog_tier_features_emails", { emails: formatNumber(tier.limits.emails) })}</FeatureItem>
|
||||
<FeatureItem>{t("account_upgrade_dialog_tier_features_attachment_file_size", { filesize: formatBytes(tier.limits.attachment_file_size, 0) })}</FeatureItem>
|
||||
<FeatureItem>{t("account_upgrade_dialog_tier_features_attachment_total_size", { totalsize: formatBytes(tier.limits.attachment_total_size, 0) })}</FeatureItem>
|
||||
</List>
|
||||
{tier.price &&
|
||||
<Typography variant="subtitle1" sx={{fontWeight: 500}}>
|
||||
{tier.price} / month
|
||||
</Typography>
|
||||
}
|
||||
</CardContent>
|
||||
|
@ -166,6 +176,25 @@ const TierCard = (props) => {
|
|||
);
|
||||
}
|
||||
|
||||
const FeatureItem = (props) => {
|
||||
return (
|
||||
<ListItem disableGutters sx={{m: 0, p: 0}}>
|
||||
<ListItemIcon sx={{minWidth: "24px"}}>
|
||||
<Check fontSize="small" sx={{ color: "#338574" }}/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
sx={{mt: "2px", mb: "2px"}}
|
||||
primary={
|
||||
<Typography variant="body2">
|
||||
{props.children}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
const Action = {
|
||||
CREATE: 1,
|
||||
UPDATE: 2,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue