diff --git a/app/components/evaluations/EvalRunCard.tsx b/app/components/evaluations/EvalRunCard.tsx index c50db96..e6f6027 100644 --- a/app/components/evaluations/EvalRunCard.tsx +++ b/app/components/evaluations/EvalRunCard.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { colors } from "@/app/lib/colors"; import { @@ -8,7 +8,7 @@ import { AssistantConfig, getScoreObject, } from "@/app/components/types"; -import { getStatusColor } from "@/app/components/utils"; +import { getStatusColor, formatCostUSD } from "@/app/components/utils"; import { timeAgo } from "@/app/lib/utils"; import ConfigModal from "@/app/components/ConfigModal"; import ScoreDisplay from "@/app/components/ScoreDisplay"; @@ -24,11 +24,20 @@ export default function EvalRunCard({ }: EvalRunCardProps) { const router = useRouter(); const [isConfigModalOpen, setIsConfigModalOpen] = useState(false); + const [isCostTooltipOpen, setIsCostTooltipOpen] = useState(false); + const [costTooltipPos, setCostTooltipPos] = useState({ top: 0, left: 0 }); const isCompleted = job.status?.toLowerCase() === "completed"; const scoreObj = getScoreObject(job); const statusColor = getStatusColor(job.status || ""); + useEffect(() => { + if (!isCostTooltipOpen) return; + const handleScroll = () => setIsCostTooltipOpen(false); + window.addEventListener("scroll", handleScroll, true); + return () => window.removeEventListener("scroll", handleScroll, true); + }, [isCostTooltipOpen]); + return (
)} - {/* Row 3: Dataset + Config (left) | Actions (right) */} + {/* Row 3: Dataset + Config + Cost (left) | Actions (right) */}
)} + {job.cost?.total_cost_usd != null && ( + + + + + {formatCostUSD(job.cost.total_cost_usd)} +
{ + const rect = e.currentTarget.getBoundingClientRect(); + const tooltipWidth = 280; + const centerX = rect.left + rect.width / 2; + const clampedLeft = Math.min( + Math.max(centerX - tooltipWidth / 2, 8), + window.innerWidth - tooltipWidth - 8, + ); + setCostTooltipPos({ + top: rect.top - 8, + left: clampedLeft, + }); + setIsCostTooltipOpen(true); + }} + onMouseLeave={() => setIsCostTooltipOpen(false)} + > + i +
+ {isCostTooltipOpen && ( +
+ {job.cost.response && ( +
+ + Response generation + + {formatCostUSD(job.cost.response.cost_usd)} +
+ )} + {job.cost.embedding && ( +
+ + Cosine similarity calculation + + + {formatCostUSD(job.cost.embedding.cost_usd)} + +
+ )} +
+ )} +
+ )}