"use client"; import React from "react"; import { Star } from "lucide-react"; import { useI18n } from "@/hooks/useI18n"; import type { ScanOpportunityRow } from "@/lib/dashboard-types"; import { getLocalizedCityName } from "@/lib/dashboard-home-copy"; function getStatusMeta( row: ScanOpportunityRow, locale: string, ): { label: string; tone: "green" | "amber" | "purple" | "neutral" } { const phase = String(row.window_phase || "").toLowerCase(); if (phase === "active_peak" || phase === "setup_today") { return { label: locale === "en-US" ? "Tradable" : "可交易", tone: "green" }; } if (phase === "tomorrow" || phase === "week_ahead") { return { label: locale === "en-US" ? "Early" : "早期机会", tone: "purple" }; } if (phase === "post_peak") { return { label: locale === "en-US" ? "Post Peak" : "峰后确认", tone: "amber" }; } return { label: locale === "en-US" ? "Watching" : "观察中", tone: "neutral" }; } function formatPercent(value?: number | null, signed = false) { if (value == null || Number.isNaN(Number(value))) return "--"; const numeric = Number(value); if (!signed) return `${numeric.toFixed(1)}%`; return `${numeric >= 0 ? "+" : ""}${numeric.toFixed(1)}%`; } function formatTimeBlock(row: ScanOpportunityRow, locale: string) { const parts: string[] = []; if (row.local_time) { parts.push(row.local_time); } if (row.selected_date) { parts.push(row.selected_date); } return parts.join(" · ") || (locale === "en-US" ? "No time" : "暂无时间"); } function formatAction(row: ScanOpportunityRow, locale: string) { if (row.side === "yes") { return `${locale === "en-US" ? "Buy" : "买入"} Yes ${row.target_label || ""}`.trim(); } if (row.side === "no") { return `${locale === "en-US" ? "Buy" : "买入"} No ${row.target_label || ""}`.trim(); } return row.action || "--"; } function formatProbability(value?: number | null) { if (value == null || Number.isNaN(Number(value))) return "--"; return `${(Number(value) * 100).toFixed(0)}%`; } function ScoreRing({ score }: { score?: number | null }) { const displayScore = Math.max(0, Math.min(100, Number(score || 0))); const radius = 20; const circumference = 2 * Math.PI * radius; const progress = (displayScore / 100) * circumference; const color = displayScore >= 85 ? "#00E0A4" : displayScore >= 70 ? "#FFB020" : "#FF4D6A"; return (
{isEn ? "No opportunity passed the price, spread, liquidity, and edge filters." : "当前没有机会同时满足价格、点差、流动性和 edge 过滤。"}