t2av_eval / frontend /src /components /AxisItemRow.jsx
Youngsun's picture
fix rational optional
f839bd4
Raw
History Blame Contribute Delete
2.37 kB
import React from "react";
// One graded row: a PASS/FAIL toggle (kind="verdict") or a numeric count input
// (kind="count"), plus a rationale textarea. Used by EventCard, VideoLevelAxes,
// and the Training page's qualification quiz - the single place PASS/FAIL and
// count UI is implemented.
//
// Rationale is always optional (never blocks saving/continuing) - it's
// strongly encouraged on real videos, especially for FAIL, but not required.
export default function AxisItemRow({
axisKey,
title,
summary,
kind,
value,
rationale,
onChangeValue,
onChangeRationale,
isPractice = false,
grading
}) {
const showGrade = grading && grading.checked;
return (
<div className="axis-item-row">
<div className="axis-item-row-header">
<span className="axis">{axisKey}</span>
<span className="axis-item-title">{title}</span>
{showGrade && (
<span className={`grade-mark ${grading.correct ? "ok" : "bad"}`}>
{grading.correct ? "✓ correct" : "✗ incorrect"}
</span>
)}
</div>
{summary && <p className="axis-item-summary muted">{summary}</p>}
{kind === "count" ? (
<label className="count-field">
Observed count
<input
type="number"
min={0}
value={value}
onChange={(e) => onChangeValue(e.target.value)}
/>
</label>
) : (
<div className="verdict-toggle">
{["PASS", "FAIL"].map((option) => (
<button
key={option}
type="button"
className={`verdict-btn ${option === "PASS" ? "pass-option" : "fail-option"} ${
value === option ? "selected" : ""
}`}
onClick={() => onChangeValue(option)}
>
{option}
</button>
))}
</div>
)}
<textarea
className="rationale-input"
placeholder={
isPractice ? "Rationale (optional for practice)" : "Rationale (optional, but encouragedespecially for FAIL)"
}
value={rationale}
onChange={(e) => onChangeRationale(e.target.value)}
/>
{showGrade && !grading.correct && grading.explanation && (
<div className="explanation-box">{grading.explanation}</div>
)}
</div>
);
}