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)",