TradingAgents/frontend/app/analysis/results/page.tsx

137 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { useAnalysisContext } from "@/context/AnalysisContext";
import { PriceChart } from "@/components/analysis/PriceChart";
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 } from "lucide-react";
const ANALYSTS = [
{ key: "market", label: "市場分析師", reportKey: "market_report" },
{ key: "social", label: "社群媒體分析師", reportKey: "sentiment_report" },
{ key: "news", label: "新聞分析師", reportKey: "news_report" },
{ key: "fundamentals", label: "基本面分析師", reportKey: "fundamentals_report" },
];
export default function AnalysisResultsPage() {
const router = useRouter();
const { analysisResult } = useAnalysisContext();
const [selectedAnalyst, setSelectedAnalyst] = useState("market");
// 如果沒有結果,重定向到分析頁面
useEffect(() => {
if (!analysisResult) {
router.push("/analysis");
}
}, [analysisResult, router]);
if (!analysisResult) {
return (
<div className="container mx-auto px-4 py-12">
<div className="text-center">
<h1 className="text-2xl font-bold mb-4"></h1>
<p className="text-gray-600 mb-4"></p>
<Button onClick={() => router.push("/analysis")}>
</Button>
</div>
</div>
);
}
const currentAnalyst = ANALYSTS.find(a => a.key === selectedAnalyst);
const currentReport = analysisResult.reports?.[currentAnalyst?.reportKey || ""];
return (
<div className="container mx-auto px-4 py-12">
<div className="max-w-7xl mx-auto space-y-8">
{/* Header */}
<div className="flex flex-col md:flex-row md:justify-between md:items-center gap-4">
<div>
<h1 className="text-4xl font-bold mb-2">
{analysisResult.ticker}
</h1>
<p className="text-gray-600 dark:text-gray-400">
{analysisResult.analysis_date}
</p>
</div>
<Button
variant="outline"
onClick={() => router.push("/analysis")}
className="gap-2"
>
<ChevronLeft className="h-4 w-4" />
</Button>
</div>
{/* 分析師選擇 Tabs */}
<Tabs value={selectedAnalyst} onValueChange={setSelectedAnalyst} className="w-full">
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4 h-auto gap-2">
{ANALYSTS.map(analyst => (
<TabsTrigger
key={analyst.key}
value={analyst.key}
className="text-sm md:text-base py-2"
>
{analyst.label}
</TabsTrigger>
))}
</TabsList>
{ANALYSTS.map(analyst => (
<TabsContent key={analyst.key} value={analyst.key} className="mt-6">
<div className="space-y-6">
{/* 價格圖表 - 每個分析師都有 */}
{analysisResult.price_data && analysisResult.price_stats && (
<PriceChart
priceData={analysisResult.price_data}
priceStats={analysisResult.price_stats}
ticker={analysisResult.ticker}
/>
)}
{/* 分析師報告 */}
<Card>
<CardHeader>
<CardTitle>{analyst.label} </CardTitle>
<CardDescription>
{analyst.key === "market" && "技術分析與市場趨勢評估"}
{analyst.key === "social" && "社群情緒與市場氛圍分析"}
{analyst.key === "news" && "新聞事件與影響分析"}
{analyst.key === "fundamentals" && "財務數據與基本面分析"}
</CardDescription>
</CardHeader>
<CardContent>
{currentReport ? (
<div className="prose prose-sm max-w-none dark:prose-invert">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{currentReport}
</ReactMarkdown>
</div>
) : (
<div className="text-center py-8">
<p className="text-gray-500 dark:text-gray-400">
</p>
<p className="text-sm text-gray-400 dark:text-gray-500 mt-2">
</p>
</div>
)}
</CardContent>
</Card>
</div>
</TabsContent>
))}
</Tabs>
</div>
</div>
);
}