fix(review-gates): green success badges, null-safe preview rows, optional section items
- Extract shared statusBadgeClass() helper (src/viewers/statusBadge.ts) so SqlViewer, CteResultViewer and PhaseSummaryViewer can't drift: ok/success/ passed/promoted render green (--success), warn renders amber (--warning), error/failed stay destructive red, everything else stays neutral outline. Previously CteResultViewer/PhaseSummaryViewer mapped "ok"/"promoted" to the default badge variant, which is bg-primary (GSD red) — success states rendered red. - enrich.js: buildCteResultV2 now falls back preview.rows to [] instead of null when last_test.preview_rows is missing (pre-upgrade ok records), and CteResultViewer reads result.preview?.rows?.length with a null-safe fallback so it degrades to the "No preview rows" empty state instead of crashing. - PhaseSummaryViewer: section.items is optional (model-authored sections can be prose-only); render (section.items ?? []) instead of crashing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,19 +1,14 @@
|
||||
import { Badge } from "../components/ui/badge";
|
||||
import { MarkdownView } from "./MarkdownView";
|
||||
import { statusBadgeClass } from "./statusBadge";
|
||||
import type { PhaseCheck, PhaseSection, PhaseSectionItem, PhaseSummaryV2, PhaseTable } from "./artifactV2";
|
||||
|
||||
const CODE_CHIP = "rounded-md bg-muted px-1.5 py-0.5 font-mono text-xs text-foreground/90";
|
||||
|
||||
function checkBadgeVariant(status: string): "default" | "destructive" | "outline" {
|
||||
if (status === "ok") return "default";
|
||||
if (status === "fail") return "destructive";
|
||||
return "outline";
|
||||
}
|
||||
|
||||
function Check({ check }: { check: PhaseCheck }) {
|
||||
return (
|
||||
<div className="flex items-start gap-2">
|
||||
<Badge variant={checkBadgeVariant(check.status)}>{check.status}</Badge>
|
||||
<Badge variant="outline" className={statusBadgeClass(check.status)}>{check.status}</Badge>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm text-foreground/90">{check.label}</span>
|
||||
{check.detail && <span className="text-xs text-muted-foreground">{check.detail}</span>}
|
||||
@@ -42,7 +37,7 @@ function Section({ section }: { section: PhaseSection }) {
|
||||
<div>
|
||||
<h4 className="thot-label mb-1.5">{section.title}</h4>
|
||||
<div className="flex flex-col gap-2">
|
||||
{section.items.map((item, i) => (
|
||||
{(section.items ?? []).map((item, i) => (
|
||||
<SectionItemRow key={i} item={item} />
|
||||
))}
|
||||
</div>
|
||||
@@ -55,7 +50,7 @@ function TableRecap({ table }: { table: PhaseTable }) {
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-sm">{table.name}</span>
|
||||
<Badge variant={table.role === "promoted" ? "default" : "outline"}>{table.role}</Badge>
|
||||
<Badge variant="outline" className={table.role === "promoted" ? statusBadgeClass(table.role) : undefined}>{table.role}</Badge>
|
||||
</div>
|
||||
{table.description && <p className="text-xs text-muted-foreground">{table.description}</p>}
|
||||
{table.columns && table.columns.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user