/** * MotherShip 登录后二级右侧报价栏 * 对齐官网 Choose your carrier + coverage + checkout 信息密度 */ "use client"; import { useEffect, useMemo, useState } from "react"; import { CheckCircle, Warning } from "@phosphor-icons/react"; import type { MothershipLoggedInShipmentPayload } from "@/components/mothership/mothership-logged-in-shipment-form"; import type { QuoteDetail, QuoteItem, QuotePageStatus, } from "@/lib/frontend/types"; import { getMotherShipRateOptionLabel, getMotherShipServiceLevelLabel, } from "@/lib/constants/mothership-ui-tiers"; import { LoadingSpinner } from "@/components/ui/loading-spinner"; import { formatUSD } from "@/lib/frontend/format"; function parseTransitDays(item: QuoteItem): number | null { const raw = `${item.transit_days ?? ""} ${item.transit_description ?? ""}`; const m = raw.match(/(\d+)/); if (!m) return null; return Number(m[1]); } function addBusinessDays(isoDate: string, days: number): Date | null { const start = new Date(`${isoDate}T12:00:00`); if (Number.isNaN(start.getTime())) return null; let left = Math.max(0, days); const d = new Date(start); while (left > 0) { d.setDate(d.getDate() + 1); const wd = d.getDay(); if (wd !== 0 && wd !== 6) left -= 1; } return d; } function formatLongDate(d: Date): string { return d.toLocaleDateString("zh-CN", { weekday: "short", month: "short", day: "numeric", year: "numeric", }); } function rateKey(item: QuoteItem): string { return `${item.service_level}|${item.rate_option}|${item.carrier}`; } function isGuaranteed(item: QuoteItem): boolean { return /guaranteed/i.test(item.service_level); } function isStandard(item: QuoteItem): boolean { return /standard/i.test(item.service_level) || !isGuaranteed(item); } function carrierTitle(item: QuoteItem): string { const name = item.carrier?.trim(); if (name) { return /direct/i.test(name) ? name : `${name}`; } return "MotherShip"; } function findGuaranteeUpsell( base: QuoteItem, all: QuoteItem[], ): QuoteItem | null { if (isGuaranteed(base)) return null; const sameCarrier = all.filter( (q) => isGuaranteed(q) && (q.carrier || "").trim().toLowerCase() === (base.carrier || "").trim().toLowerCase(), ); if (sameCarrier.length > 0) { return sameCarrier.sort((a, b) => a.final_total - b.final_total)[0] ?? null; } // 无同承运商保证档时:取最低保证送达价作加价提示 const anyG = all .filter(isGuaranteed) .sort((a, b) => a.final_total - b.final_total); return anyG[0] ?? null; } export interface MothershipLoggedInQuoteSidebarProps { payload: MothershipLoggedInShipmentPayload; quote: QuoteDetail | null; status: QuotePageStatus; error: string | null; } export function MothershipLoggedInQuoteSidebar({ payload, quote, status, error, }: MothershipLoggedInQuoteSidebarProps) { const rates = useMemo(() => { const list = [...(quote?.quotes ?? [])]; return list.sort((a, b) => a.final_total - b.final_total); }, [quote]); const [selectedId, setSelectedId] = useState(null); const [preferGuaranteed, setPreferGuaranteed] = useState(false); const [coverage, setCoverage] = useState<"basic" | "full">("basic"); const [cargoValue, setCargoValue] = useState(""); useEffect(() => { if (rates.length === 0) { setSelectedId(null); return; } setSelectedId((prev) => { if (prev && rates.some((r) => rateKey(r) === prev)) return prev; const preferred = rates.find(isStandard) ?? rates[0]!; return rateKey(preferred); }); setPreferGuaranteed(false); }, [rates]); const selectedBase = rates.find((r) => rateKey(r) === selectedId) ?? rates[0] ?? null; const upsell = selectedBase ? findGuaranteeUpsell(selectedBase, rates) : null; const selected = preferGuaranteed && upsell ? upsell : selectedBase; const loading = status === "validating" || status === "processing" || status === "resolving_address"; const pickupEta = useMemo(() => { if (!payload.readyDate) return "—"; const d = new Date(`${payload.readyDate}T12:00:00`); if (Number.isNaN(d.getTime())) return payload.readyDate; const datePart = formatLongDate(d); const timePart = payload.readyTime ? ` ${payload.readyTime} 之后` : " 当日结束前"; return `${datePart}${timePart}`; }, [payload.readyDate, payload.readyTime]); const deliveryEta = useMemo(() => { if (!selected) return "以所选费率时效为准"; const days = parseTransitDays(selected); if (days == null || !payload.readyDate) { return ( selected.transit_description || (selected.transit_days ? `预计 ${selected.transit_days} 个工作日` : "以所选费率时效为准") ); } const end = addBusinessDays(payload.readyDate, days); if (!end) return `预计 ${days} 个工作日`; return `${formatLongDate(end)} 当日结束前`; }, [selected, payload.readyDate]); const unavailableHint = useMemo(() => { if (loading || error) return null; if (rates.length === 0) return null; const looksMarketplace = rates.every( (r) => /tforce|daylight|echo/i.test(r.carrier ?? "") || !/direct/i.test(r.carrier ?? ""), ); if (looksMarketplace && rates.length > 0) { return "当前价源非登录态 Direct 承运商列表。请确认客户已配置 MotherShip 账密且 Worker 可打开 dashboard。"; } if (rates.length < 3) { return "部分承运商无法服务此票货;完整不可用列表以官网为准。"; } return null; }, [rates, loading, error]); return ( ); }