'use client'; import React, { useState } from 'react'; import { IncidentSeverity } from './types'; interface OperationsCreateIncidentProps { onIncidentCreated: (caseRef: string) => void; onCancel: () => void; } export function OperationsCreateIncident({ onIncidentCreated, onCancel, }: OperationsCreateIncidentProps) { const [title, setTitle] = useState(''); const [summary, setSummary] = useState(''); const [severity, setSeverity] = useState('medium'); const [isSubmitting, setIsSubmitting] = useState(false); const [errorMessage, setErrorMessage] = useState(null); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!title.trim()) { setErrorMessage('Incident title is required.'); return; } if (!summary.trim()) { setErrorMessage('Incident summary is required.'); return; } setIsSubmitting(true); setErrorMessage(null); try { const response = await fetch('/api/ops/incidents', { method: 'POST', headers: { 'content-type': 'application/json', accept: 'application/json', }, body: JSON.stringify({ title: title.trim(), summary: summary.trim(), severity, }), }); if (response.status === 401) { setErrorMessage('Your Operations session has expired.'); setIsSubmitting(false); return; } if (response.status === 403) { setErrorMessage('You do not have authority to create incidents.'); setIsSubmitting(false); return; } if (response.status === 422) { const data = await response.json().catch(() => null); setErrorMessage(data?.detail ?? 'Please check the incident fields and try again.'); setIsSubmitting(false); return; } if (!response.ok) { const data = await response.json().catch(() => null); setErrorMessage(data?.detail ?? 'Operations platform is temporarily unavailable.'); setIsSubmitting(false); return; } const data = await response.json(); if (data?.case_reference) { onIncidentCreated(data.case_reference); } else { onCancel(); } } catch { setErrorMessage('Unable to connect to Operations platform.'); setIsSubmitting(false); } } return (
{/* Header */}
New Incident Record

Create Operational Incident

Case reference and open status will be generated automatically.

{/* Error Alert */} {errorMessage && (
error {errorMessage}
)} {/* Form Card */}
{/* Title */}
setTitle(e.target.value)} placeholder="e.g. Ingress latency spike on edge cluster" className="w-full bg-surface-container px-4 py-2.5 rounded-xl border border-outline-variant/40 text-xs sm:text-sm text-on-surface placeholder:text-outline focus-visible:ring-2 focus-visible:ring-primary-container focus-visible:outline-none" />
{/* Severity Selection */}
{(['low', 'medium', 'high', 'critical'] as IncidentSeverity[]).map((sev) => { const isSelected = severity === sev; return ( ); })}
{/* Summary */}
{summary.length} / 4000