"use client"; import { useEffect, useMemo, useState } from "react"; import { CheckCircle, Database, ClockClockwise } from "@phosphor-icons/react"; import type { QuoteDetail, QuoteItem, RateOption, ServiceLevel, } from "@/lib/frontend/types"; import { filterQuotesForMotherShipUiDisplay, getMotherShipRateOptionLabel, getMotherShipServiceLevelLabel, listMotherShipUiTabsFromQuotes, listVisibleRateOptionsForTab, resolveDefaultRateOptionForTab, } from "@/lib/constants/mothership-ui-tiers"; import { formatUSD, formatPercent } from "@/lib/frontend/format"; import { Card } from "@/components/ui/card"; const RATE_ORDER: RateOption[] = ["lowest", "bestValue", "fastest"]; interface QuoteCardProps { quote: QuoteDetail; defaultLevel?: ServiceLevel; defaultRate?: RateOption; } function findTier( quotes: QuoteItem[], level: ServiceLevel, rate: RateOption, ): QuoteItem | undefined { return quotes.find( (q) => q.service_level === level && q.rate_option === rate, ); } function SourceBadge({ quote }: { quote: QuoteDetail }) { if (quote.source_type === "cache") { return ( 缓存命中 ); } if (quote.source_type === "stale") { return ( 非实时 ); } return ( 实时报价 ); } export function QuoteCard({ quote, defaultLevel = "standard", defaultRate = "lowest", }: QuoteCardProps) { const displayQuotes = useMemo( () => filterQuotesForMotherShipUiDisplay(quote.quotes ?? []), [quote.quotes], ); const serviceLevels = useMemo( () => listMotherShipUiTabsFromQuotes(displayQuotes), [displayQuotes], ); const [level, setLevel] = useState(defaultLevel); const [rate, setRate] = useState(defaultRate); const availableRates = useMemo( () => listVisibleRateOptionsForTab(displayQuotes, level) as RateOption[], [displayQuotes, level], ); useEffect(() => { if (serviceLevels.length > 0 && !serviceLevels.includes(level as string)) { setLevel(serviceLevels[0] as ServiceLevel); } }, [serviceLevels, level]); useEffect(() => { const preferred = resolveDefaultRateOptionForTab(displayQuotes, level); if (availableRates.length > 0 && !availableRates.includes(rate)) { setRate(preferred as RateOption); } }, [availableRates, rate, displayQuotes, level]); const item = findTier(displayQuotes, level, rate) ?? findTier( displayQuotes, level, resolveDefaultRateOptionForTab(displayQuotes, level) as RateOption, ) ?? displayQuotes.find((q) => q.service_level === level); if (!item) { return ( 暂无报价数据 ); } return ( {!quote.is_realtime && ( 非实时报价,仅供参考 )} {serviceLevels.map((lv) => ( setLevel(lv as ServiceLevel)} className={`rounded-sm px-3 py-1.5 text-sm font-medium transition-colors ${ level === lv ? "bg-surface text-primary shadow-card" : "text-text-secondary" }`} > {getMotherShipServiceLevelLabel(lv)} ))} {(availableRates.length > 0 ? availableRates : RATE_ORDER).map((rt) => { if (!displayQuotes.some( (q) => q.service_level === level && q.rate_option === rt, )) { return null; } return ( setRate(rt)} className={`rounded-sm px-3 py-1.5 text-sm font-medium transition-colors ${ rate === rt ? "bg-surface text-primary shadow-card" : "text-text-secondary" }`} > {getMotherShipRateOptionLabel(level, rt)} ); })} {item.carrier} · {item.transit_description} {formatUSD(item.final_total)} 时效 {item.transit_days} 天 原价 {formatUSD(item.raw_total)} 价格明细 {item.breakdown.map((b) => ( {b.item} {formatUSD(b.amount)} ))} 客户最终价(加价 {formatPercent(item.markup_percent)}) {formatUSD(item.final_total)} 单号 {quote.quote_id} ); }
暂无报价数据
{item.carrier} · {item.transit_description}
{formatUSD(item.final_total)}
时效 {item.transit_days} 天
原价 {formatUSD(item.raw_total)}
价格明细
单号 {quote.quote_id}