feat: AI triage suggestion — severity + DOSH flags pre-fill

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFDuBhMKvoWjrWT3ZnGmmr
This commit is contained in:
2026-07-11 16:27:29 +08:00
co-authored by Claude Sonnet 4.6
parent a5933d2cd9
commit f10fa071f9
3 changed files with 219 additions and 7 deletions
+54 -7
View File
@@ -27,6 +27,8 @@ export function TriageForm({ incidentId, currentSeverity }: Props) {
const [triageNotes, setTriageNotes] = useState('')
const [saving, setSaving] = useState(false)
const [error, setError] = useState<string | null>(null)
const [aiLoading, setAiLoading] = useState(false)
const [aiRationale, setAiRationale] = useState<string | null>(null)
const dosh = computeDoshObligation({
is_fatality: isFatality,
@@ -36,6 +38,33 @@ export function TriageForm({ incidentId, currentSeverity }: Props) {
lost_days: null,
})
async function getAiSuggestion() {
setAiLoading(true)
setAiRationale(null)
try {
const res = await fetch(`/api/incidents/${incidentId}/ai/triage-suggest`, { method: 'POST' })
if (!res.ok) return
const data = await res.json() as {
severity: number
is_fatality: boolean
is_serious_bodily_injury: boolean
is_dangerous_occurrence: boolean
is_occupational_disease: boolean
rationale: string
}
setSeverity(data.severity)
setIsFatality(data.is_fatality)
setIsSBI(data.is_serious_bodily_injury)
setIsDO(data.is_dangerous_occurrence)
setIsOD(data.is_occupational_disease)
setAiRationale(data.rationale)
} catch {
// Non-blocking — user can still triage manually
} finally {
setAiLoading(false)
}
}
async function handleSubmit(e: React.FormEvent) {
e.preventDefault()
setSaving(true)
@@ -120,15 +149,33 @@ export function TriageForm({ incidentId, currentSeverity }: Props) {
/>
</div>
{aiRationale && (
<div className="rounded-lg bg-purple-50 border border-purple-200 p-3">
<p className="text-xs font-semibold text-purple-700 mb-1">AI Suggestion Rationale</p>
<p className="text-xs text-purple-600">{aiRationale}</p>
<p className="text-xs text-purple-400 mt-1">Fields pre-filled review before submitting.</p>
</div>
)}
{error && <p className="text-sm text-red-600">{error}</p>}
<button
type="submit"
disabled={saving}
className="w-full bg-blue-600 text-white rounded-lg py-2 text-sm font-semibold disabled:opacity-50"
>
{saving ? 'Saving…' : 'Complete Triage'}
</button>
<div className="flex gap-3">
<button
type="button"
onClick={getAiSuggestion}
disabled={aiLoading || saving}
className="flex-1 bg-purple-50 text-purple-700 border border-purple-300 rounded-lg py-2 text-sm font-semibold disabled:opacity-50 hover:bg-purple-100"
>
{aiLoading ? 'Getting suggestion…' : 'Get AI Suggestion'}
</button>
<button
type="submit"
disabled={saving}
className="flex-1 bg-blue-600 text-white rounded-lg py-2 text-sm font-semibold disabled:opacity-50"
>
{saving ? 'Saving…' : 'Complete Triage'}
</button>
</div>
</form>
)
}