Add subscription expiry reminders across account and dashboard

This commit is contained in:
2569718930@qq.com
2026-03-30 00:58:43 +08:00
parent 16404ccf71
commit 538de5cdd8
7 changed files with 209 additions and 6 deletions
@@ -12,6 +12,20 @@ import {
hasSupabasePublicEnv,
} from "@/lib/supabase/client";
function parseExpiryInfo(raw?: string | null) {
const text = String(raw || "").trim();
if (!text) return null;
const dt = new Date(text);
if (Number.isNaN(dt.getTime())) return null;
const diffMs = dt.getTime() - Date.now();
const daysLeft = Math.ceil(diffMs / 86_400_000);
return {
date: dt,
daysLeft,
expired: diffMs <= 0,
};
}
export function HeaderBar() {
const store = useDashboardStore();
const { locale, setLocale, t } = useI18n();
@@ -56,6 +70,36 @@ export function HeaderBar() {
const accountAria = isAuthenticated
? t("header.accountAria")
: t("header.signInAria");
const expiryInfo = parseExpiryInfo(store.proAccess.subscriptionExpiresAt);
const isTrialPlan = /trial/i.test(
String(store.proAccess.subscriptionPlanCode || ""),
);
const showRenewReminder =
isAuthenticated &&
!store.proAccess.loading &&
(
(store.proAccess.subscriptionActive &&
expiryInfo &&
expiryInfo.daysLeft <= 3) ||
(!store.proAccess.subscriptionActive && Boolean(expiryInfo))
);
const renewReminderLabel = !showRenewReminder
? ""
: !store.proAccess.subscriptionActive
? isTrialPlan
? locale === "en-US"
? "Trial ended"
: "试用已结束"
: locale === "en-US"
? "Pro expired"
: "Pro 已到期"
: isTrialPlan
? locale === "en-US"
? `Trial ${Math.max(expiryInfo?.daysLeft || 0, 0)}d left`
: `试用剩余 ${Math.max(expiryInfo?.daysLeft || 0, 0)}`
: locale === "en-US"
? `Pro ${Math.max(expiryInfo?.daysLeft || 0, 0)}d left`
: `Pro 还剩 ${Math.max(expiryInfo?.daysLeft || 0, 0)}`;
return (
<header className="header">
@@ -101,6 +145,20 @@ export function HeaderBar() {
<span>{accountLabel}</span>
</Link>
{showRenewReminder ? (
<Link
href="/account"
className={clsx(
"account-renew-badge",
!store.proAccess.subscriptionActive && "expired",
)}
title={renewReminderLabel}
aria-label={renewReminderLabel}
>
<span>{renewReminderLabel}</span>
</Link>
) : null}
<div className="live-badge" id="liveBadge">
<span className="pulse-dot" />
<span>{t("header.live")}</span>