Re-wording, chips

This commit is contained in:
binwiederhier
2026-06-12 22:33:09 -04:00
parent 4516adea36
commit f558935c1e
7 changed files with 39 additions and 27 deletions
+23 -12
View File
@@ -269,22 +269,23 @@ const AccountType = () => {
}
};
// The account type is a base label ("Admin", "Basic", "Free", or the tier name) plus an optional
// qualifier chip (admin tier status, or the billing interval).
let accountType;
let qualifierChip;
if (account.role === Role.ADMIN) {
const tierSuffix = account.tier
? t("account_basics_tier_admin_suffix_with_tier", {
tier: account.tier.name,
})
accountType = t("account_basics_tier_admin");
qualifierChip = account.tier
? t("account_basics_tier_admin_suffix_with_tier", { tier: account.tier.name })
: t("account_basics_tier_admin_suffix_no_tier");
accountType = `${t("account_basics_tier_admin")} ${tierSuffix}`;
} else if (!account.tier) {
accountType = config.enable_payments ? t("account_basics_tier_free") : t("account_basics_tier_basic");
} else {
accountType = account.tier.name;
if (account.billing?.interval === SubscriptionInterval.MONTH) {
accountType += ` (${t("account_basics_tier_interval_monthly")})`;
qualifierChip = t("account_basics_tier_interval_monthly");
} else if (account.billing?.interval === SubscriptionInterval.YEAR) {
accountType += ` (${t("account_basics_tier_interval_yearly")})`;
qualifierChip = t("account_basics_tier_interval_yearly");
}
}
@@ -296,6 +297,7 @@ const AccountType = () => {
>
<div>
{accountType}
{qualifierChip && <Chip size="small" label={qualifierChip} sx={{ ml: 1 }} />}
{account.provisioned && <Chip size="small" label={t("account_basics_tier_provisioned")} sx={{ ml: 1 }} />}
{account.billing?.paid_until && !account.billing?.cancel_at && (
<Tooltip
@@ -449,9 +451,13 @@ const Emails = () => {
const verifiedEmails = emails.filter((e) => !e.pending);
const pendingEmails = emails.filter((e) => e.pending);
const primaryEmail = verifiedEmails.find((e) => e.primary)?.address ?? "";
// Provisioned users get their password from the server config and cannot reset it, so they don't
// get the "no recovery email" nudge (the Add-email dialog explains the recovery-email limitation).
const showNoRecoveryWarning = config.enable_reset_password && primaryEmail === "" && !account?.provisioned;
// Recovery nudges (skipped for provisioned users -- they can't reset, and the Add-email dialog
// explains the limitation): prompt for a first email when there are none, or for a primary when
// there are emails but none is primary.
const recoveryRelevant = config.enable_reset_password && !account?.provisioned;
const hasNoEmails = verifiedEmails.length === 0 && pendingEmails.length === 0;
const showNoEmailWarning = recoveryRelevant && hasNoEmails;
const showNoPrimaryWarning = recoveryRelevant && !hasNoEmails && primaryEmail === "";
return (
<Pref labelId={labelId} alignTop title={t("account_basics_emails_title")} description={t("account_basics_emails_description")}>
@@ -468,7 +474,7 @@ const Emails = () => {
variant="outlined"
onClick={(ev) => openMenu(ev, email)}
onDelete={() => handleDelete(email.address)}
sx={email.primary ? { "& .MuiChip-icon": { color: "primary.main" } } : undefined}
sx={email.primary ? { "& .MuiChip-icon": { color: "#fbc02d" } } : undefined}
/>
))}
{pendingEmails.map((email) => (
@@ -491,11 +497,16 @@ const Emails = () => {
<IconButton onClick={handleDialogOpen} aria-label={t("account_basics_emails_dialog_title")}>
<AddIcon />
</IconButton>
{showNoRecoveryWarning && (
{showNoEmailWarning && (
<Alert severity="warning" sx={{ mt: 1 }}>
{t("account_basics_emails_no_recovery_warning")}
</Alert>
)}
{showNoPrimaryWarning && (
<Alert severity="warning" sx={{ mt: 1 }}>
{t("account_basics_emails_no_primary_warning")}
</Alert>
)}
</div>
<Menu anchorEl={menuAnchor} open={Boolean(menuAnchor)} onClose={closeMenu}>
<MenuItem onClick={() => runMenuAction(handleCopy)}>
+2 -2
View File
@@ -49,7 +49,7 @@ const EmailVerify = () => {
{status === "success" && (
<>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<CheckCircleOutlineIcon color="success" sx={{ fontSize: 32 }} />
<CheckCircleOutlineIcon color="success" sx={{ fontSize: 28 }} />
<Typography sx={{ typography: "h6" }}>{t("email_verify_success_title")}</Typography>
</Box>
<Typography sx={{ mt: 1, textAlign: "center" }}>{t("email_verify_success_description")}</Typography>
@@ -61,7 +61,7 @@ const EmailVerify = () => {
{status === "error" && (
<>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<ErrorOutlineIcon color="error" sx={{ fontSize: 32 }} />
<ErrorOutlineIcon color="error" sx={{ fontSize: 28 }} />
<Typography sx={{ typography: "h6" }}>{t("email_verify_error_title")}</Typography>
</Box>
<Typography sx={{ mt: 1, textAlign: "center" }}>{t("email_verify_error_description")}</Typography>
+1 -1
View File
@@ -51,7 +51,7 @@ const PasswordReset = () => {
return (
<AvatarBox>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<CheckCircleOutlineIcon color="success" sx={{ fontSize: 32 }} />
<CheckCircleOutlineIcon color="success" sx={{ fontSize: 28 }} />
<Typography sx={{ typography: "h6" }}>{t("reset_password_success_title")}</Typography>
</Box>
<Typography sx={{ mt: 1, textAlign: "center" }}>{t("reset_password_success_description")}</Typography>
+1 -1
View File
@@ -48,7 +48,7 @@ const ResetPassword = () => {
return (
<AvatarBox>
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
<CheckCircleOutlineIcon color="success" sx={{ fontSize: 32 }} />
<CheckCircleOutlineIcon color="success" sx={{ fontSize: 28 }} />
<Typography sx={{ typography: "h6" }}>{t("reset_password_sent_title")}</Typography>
</Box>
<Typography sx={{ mt: 1, textAlign: "center" }}>{t("reset_password_sent_description")}</Typography>