diff --git a/frontend/components/dashboard/HistoryModal.tsx b/frontend/components/dashboard/HistoryModal.tsx index 5257c9e0..ea4a4978 100644 --- a/frontend/components/dashboard/HistoryModal.tsx +++ b/frontend/components/dashboard/HistoryModal.tsx @@ -92,7 +92,17 @@ export function HistoryModal() { ) : !isPro ? ( - + <> +
+

+ {t("history.previewTitle")} +

+

+ {t("history.previewDesc")} +

+
+ + ) : (
diff --git a/frontend/components/dashboard/ScanTerminalDashboard.tsx b/frontend/components/dashboard/ScanTerminalDashboard.tsx index 9170c880..a0c81f3b 100644 --- a/frontend/components/dashboard/ScanTerminalDashboard.tsx +++ b/frontend/components/dashboard/ScanTerminalDashboard.tsx @@ -5,6 +5,7 @@ import dynamic from "next/dynamic"; import Link from "next/link"; import { LogIn, + MessageCircle, Moon, RefreshCw, Sun, @@ -31,6 +32,7 @@ import type { } from "@/lib/dashboard-types"; import { AiPinnedForecastView } from "@/components/dashboard/scan-terminal/AiPinnedForecastView"; import { LoadingSignal } from "@/components/dashboard/scan-terminal/LoadingSignal"; +import { WelcomeOverlay } from "@/components/dashboard/scan-terminal/WelcomeOverlay"; import { findDetailForCity } from "@/components/dashboard/scan-terminal/city-detail-utils"; import { findRowForCity, @@ -451,6 +453,16 @@ function ScanTerminalScreen() { ) : null} + + +
@@ -575,6 +587,7 @@ function ScanTerminalScreen() { + {}} /> {showScanPaywall ? (
void; +}; + +const steps = [ + { + icon: MapPin, + titleEn: "Pick a city on the map", + titleZh: "从地图选城市", + descEn: "Click any colored bubble to view real-time weather and forecasts.", + descZh: "点击地图上的彩色气泡,查看实时天气和预报。", + }, + { + icon: FileText, + titleEn: "Read the city briefing", + titleZh: "查看城市简报", + descEn: "The right panel shows current temperature, DEB forecast, and detailed metrics.", + descZh: "右侧面板展示当前温度、DEB 预报和各项指标。", + }, + { + icon: Crown, + titleEn: "Unlock Pro for deep analysis", + titleZh: "解锁 Pro 深入分析", + descEn: "Pro unlocks AI-powered METAR reads, model evidence, market layer, and intraday analysis.", + descZh: "Pro 解锁 AI 机场报文解读、模型证据、市场层、日内分析。", + }, +]; + +export function WelcomeOverlay({ locale, onDismiss }: Props) { + const [visible, setVisible] = useState(false); + const [step, setStep] = useState(0); + const isEn = locale === "en-US"; + + useEffect(() => { + const seen = localStorage.getItem(STORAGE_KEY); + if (!seen) { + setVisible(true); + } + }, []); + + if (!visible) return null; + + const current = steps[step]; + const isLast = step === steps.length - 1; + + const handleDismiss = () => { + localStorage.setItem(STORAGE_KEY, "1"); + setVisible(false); + onDismiss(); + }; + + const handleNext = () => { + if (isLast) { + handleDismiss(); + } else { + setStep(step + 1); + } + }; + + return ( +
+
e.stopPropagation()} + > +
+ {steps.map((_, i) => ( + + ))} +
+ +
+ +
+ +

+ {isEn ? current.titleEn : current.titleZh} +

+

+ {isEn ? current.descEn : current.descZh} +

+ +
+ + +
+
+
+ ); +} diff --git a/frontend/lib/i18n.ts b/frontend/lib/i18n.ts index 3a8fdfad..4f98d8e1 100644 --- a/frontend/lib/i18n.ts +++ b/frontend/lib/i18n.ts @@ -77,6 +77,8 @@ const MESSAGES: Record> = { "history.loading": "正在获取历史数据...", "history.error": "获取历史信息失败", "history.empty": "近 15 天暂无该城市历史数据", + "history.previewTitle": "历史准确率对账", + "history.previewDesc": "对比 DEB 预报与实际结算温度,查看命中率、MAE 和模型对比。升级 Pro 即可解锁。", "history.hitRate": "DEB 结算胜率 (METAR)", "history.mae": "DEB MAE", "history.debHitRate": "DEB 结算胜率 (METAR)", @@ -274,6 +276,8 @@ const MESSAGES: Record> = { "history.loading": "Loading historical data...", "history.error": "Failed to load historical data", "history.empty": "No historical records for this city in the last 15 days", + "history.previewTitle": "Historical Reconciliation", + "history.previewDesc": "Compare DEB forecasts to actual settlement temperatures with hit rate, MAE, and model comparison. Unlock Pro to access.", "history.hitRate": "DEB Settlement Hit Rate (METAR)", "history.mae": "DEB MAE", "history.debHitRate": "DEB Settlement Hit Rate (METAR)",