"use client"; import { useState, useEffect, useMemo } from "react"; import { useRouter } from "next/navigation"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { useAnalysisContext } from "@/context/AnalysisContext"; import { useAuth } from "@/contexts/auth-context"; import { useLanguage } from "@/contexts/LanguageContext"; import { PriceChart } from "@/components/analysis/PriceChart"; import { DownloadReports } from "@/components/analysis/DownloadReports"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { ChevronLeft, Save, Check, AlertCircle, Cloud } from "lucide-react"; import { saveReport, checkDuplicateReport } from "@/lib/reports-db"; import { saveCloudReport, isCloudSyncEnabled } from "@/lib/user-api"; // Analyst keys for mapping to translation keys const ANALYST_KEYS = [ // === Analysts Team === { key: "market", reportKey: "market_report" }, { key: "social", reportKey: "sentiment_report" }, { key: "news", reportKey: "news_report" }, { key: "fundamentals", reportKey: "fundamentals_report" }, // === Research Team === { key: "bull", reportKey: "investment_debate_state.bull_history" }, { key: "bear", reportKey: "investment_debate_state.bear_history" }, { key: "research_manager", reportKey: "investment_debate_state.judge_decision" }, // === Trader === { key: "trader", reportKey: "trader_investment_plan" }, // === Risk Management Team === { key: "risky", reportKey: "risk_debate_state.risky_history" }, { key: "safe", reportKey: "risk_debate_state.safe_history" }, { key: "neutral", reportKey: "risk_debate_state.neutral_history" }, { key: "risk_manager", reportKey: "risk_debate_state.judge_decision" }, ]; // 獲取嵌套對象的值 const getNestedValue = (obj: any, path: string) => { return path.split('.').reduce((current, key) => current?.[key], obj); }; export default function AnalysisResultsPage() { const router = useRouter(); const { analysisResult, taskId, marketType } = useAnalysisContext(); const { isAuthenticated } = useAuth(); const { t, locale } = useLanguage(); const [selectedAnalyst, setSelectedAnalyst] = useState("market"); // Save report states const [saving, setSaving] = useState(false); const [saveSuccess, setSaveSuccess] = useState(false); const [saveError, setSaveError] = useState(null); const [savedToCloud, setSavedToCloud] = useState(false); // Build analysts array with translations const ANALYSTS = useMemo(() => ANALYST_KEYS.map(analyst => ({ key: analyst.key, label: t.results.analysts[analyst.key as keyof typeof t.results.analysts] || analyst.key, description: t.results.analysts[`${analyst.key}Desc` as keyof typeof t.results.analysts] || "", reportKey: analyst.reportKey, })), [t]); // 如果沒有結果,重定向到分析頁面 useEffect(() => { if (!analysisResult) { router.push("/analysis"); } }, [analysisResult, router]); // Handle save report const handleSaveReport = async () => { if (!analysisResult) return; setSaving(true); setSaveError(null); setSaveSuccess(false); setSavedToCloud(false); try { // Check for duplicate in local storage const duplicate = await checkDuplicateReport( analysisResult.ticker, analysisResult.analysis_date ); if (duplicate) { setSaveError(t.results.duplicateReport); setSaving(false); return; } // Save to local IndexedDB await saveReport( analysisResult.ticker, marketType, analysisResult.analysis_date, analysisResult, taskId || undefined, locale as "en" | "zh-TW" // Pass current language for filtering ); // If authenticated, also save to cloud if (isAuthenticated && isCloudSyncEnabled()) { const cloudId = await saveCloudReport({ ticker: analysisResult.ticker, market_type: marketType, analysis_date: analysisResult.analysis_date, result: analysisResult, language: locale as "en" | "zh-TW", }); if (cloudId) { setSavedToCloud(true); } } setSaveSuccess(true); // Reset success message after 3 seconds setTimeout(() => { setSaveSuccess(false); setSavedToCloud(false); }, 3000); } catch (error) { console.error("Save report error:", error); setSaveError(t.results.saveError); } finally { setSaving(false); } }; if (!analysisResult) { return (

{t.results.noResults}

{t.results.runAnalysisFirst}

); } return (
{/* Header */}

{analysisResult.ticker} {t.results.detailedResults}

{t.results.analysisDate}:{analysisResult.analysis_date}

{/* Save success/error feedback */} {saveSuccess && ( {t.results.saved} )} {saveError && ( {saveError} )} {/* Download PDF Button */} {analysisResult.reports && ( )} {/* Save Report Button */}
{/* 分析師選擇 Tabs */} {ANALYSTS.map(analyst => ( {analyst.label} ))} {ANALYSTS.map(analyst => (
{/* 價格圖表 - 每個分析師都有 */} {analysisResult.price_data && analysisResult.price_stats && ( )} {/* 分析師報告 */}
{analyst.label} {t.results.report} {analyst.description}
{getNestedValue(analysisResult.reports, analyst.reportKey) ? (
{getNestedValue(analysisResult.reports, analyst.reportKey)}
) : (

{t.results.noReportGenerated}

{t.results.notSelectedOrNoReport}

)}
))}
); }