Use Pro paywall for scan access
This commit is contained in:
@@ -14,7 +14,7 @@ const TELEGRAM_GROUP_URL = String(
|
||||
const SUBSCRIPTION_HELP_HREF = "/subscription-help";
|
||||
|
||||
type ProFeaturePaywallProps = {
|
||||
feature: "today" | "history" | "future" | "assistant";
|
||||
feature: "today" | "history" | "future" | "assistant" | "scan";
|
||||
onClose?: () => void;
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import { MapCanvas } from "@/components/dashboard/MapCanvas";
|
||||
import { getWindowPhaseMeta } from "@/components/dashboard/OpportunityTable";
|
||||
import { ScanKPIBar } from "@/components/dashboard/ScanKPIBar";
|
||||
import { OpportunityTable } from "@/components/dashboard/OpportunityTable";
|
||||
import { ProFeaturePaywall } from "@/components/dashboard/ProFeaturePaywall";
|
||||
import {
|
||||
DashboardStoreProvider,
|
||||
useDashboardStore,
|
||||
@@ -243,6 +244,7 @@ function ScanTerminalScreen() {
|
||||
const [selectedRowId, setSelectedRowId] = useState<string | null>(null);
|
||||
const [activeView, setActiveView] = useState<ContentView>("map");
|
||||
const [mapSelectedCityName, setMapSelectedCityName] = useState<string | null>(null);
|
||||
const [showScanPaywall, setShowScanPaywall] = useState(false);
|
||||
const [userLocalTime, setUserLocalTime] = useState("--");
|
||||
const [themeMode, setThemeMode] = useState<ThemeMode>("dark");
|
||||
const deferredRows = useDeferredValue(terminalData?.rows || []);
|
||||
@@ -490,6 +492,10 @@ function ScanTerminalScreen() {
|
||||
void store.selectCity(row.city);
|
||||
}, [store]);
|
||||
|
||||
const openScanPaywall = useCallback(() => {
|
||||
setShowScanPaywall(true);
|
||||
}, []);
|
||||
|
||||
const renderMainView = () => {
|
||||
if (resolvedView === "map") {
|
||||
return (
|
||||
@@ -635,12 +641,16 @@ function ScanTerminalScreen() {
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<Link href={accountHref} className="scan-primary-button">
|
||||
<button
|
||||
type="button"
|
||||
className="scan-primary-button"
|
||||
onClick={openScanPaywall}
|
||||
>
|
||||
<UserRound size={14} />
|
||||
{store.proAccess.authenticated
|
||||
? isEn ? "Upgrade Pro" : "升级 Pro"
|
||||
: isEn ? "Sign in" : "登录"}
|
||||
</Link>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
@@ -692,10 +702,12 @@ function ScanTerminalScreen() {
|
||||
<button
|
||||
type="button"
|
||||
className={resolvedView === "list" ? "active" : ""}
|
||||
disabled={!isPro}
|
||||
title={!isPro ? (isEn ? "Pro scan required" : "扫描需 Pro") : undefined}
|
||||
onClick={() => {
|
||||
if (!isPro) return;
|
||||
if (!isPro) {
|
||||
openScanPaywall();
|
||||
return;
|
||||
}
|
||||
setActiveView("list");
|
||||
}}
|
||||
>
|
||||
@@ -704,10 +716,12 @@ function ScanTerminalScreen() {
|
||||
<button
|
||||
type="button"
|
||||
className={resolvedView === "calendar" ? "active" : ""}
|
||||
disabled={!isPro}
|
||||
title={!isPro ? (isEn ? "Pro scan required" : "扫描需 Pro") : undefined}
|
||||
onClick={() => {
|
||||
if (!isPro) return;
|
||||
if (!isPro) {
|
||||
openScanPaywall();
|
||||
return;
|
||||
}
|
||||
setActiveView("calendar");
|
||||
}}
|
||||
>
|
||||
@@ -749,6 +763,24 @@ function ScanTerminalScreen() {
|
||||
<CityDetailPanel variant="rail" />
|
||||
</div>
|
||||
<FutureForecastModal />
|
||||
{showScanPaywall ? (
|
||||
<div
|
||||
className="modal-overlay"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label={isEn ? "Unlock market scan" : "解锁市场扫描"}
|
||||
onClick={(event) => {
|
||||
if (event.target === event.currentTarget) {
|
||||
setShowScanPaywall(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ProFeaturePaywall
|
||||
feature="scan"
|
||||
onClose={() => setShowScanPaywall(false)}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,11 +56,13 @@ type UnlockProOverlayProps = {
|
||||
|
||||
const FEATURES = {
|
||||
"zh-CN": [
|
||||
"市场扫描台 + V4-Flash 深度复核",
|
||||
"今日日内机场报文规则分析(含高温时段)",
|
||||
"历史对账 + 未来日期分析",
|
||||
"全平台智能气象推送",
|
||||
],
|
||||
"en-US": [
|
||||
"Market Scan Terminal + V4-Flash review",
|
||||
"Intraday METAR rule-based analysis with peak-time window",
|
||||
"Historical reconciliation + future-date analysis",
|
||||
"Cross-platform alerts",
|
||||
|
||||
Reference in New Issue
Block a user