import React, { useState } from 'react'; import { XCircle } from 'lucide-react'; import { useToast } from '../../contexts/ToastContext'; const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:3001/api'; /** * Shared modal for adding and editing Archer risk acceptance tickets. * Props: * - ticket: existing ticket (edit mode) or null (add mode) * - context: { cve_id, vendor } when adding from a CVE card * - onClose: close handler * - onSuccess: refresh handler */ export default function ArcherTicketModal({ ticket, context, onClose, onSuccess }) { const toast = useToast(); const isEdit = !!ticket; const [form, setForm] = useState({ exc_number: ticket?.exc_number || '', archer_url: ticket?.archer_url || '', status: ticket?.status || 'Draft', cve_id: ticket?.cve_id || context?.cve_id || '', vendor: ticket?.vendor || context?.vendor || '', }); const handleSubmit = async (e) => { e.preventDefault(); try { if (isEdit) { const response = await fetch(`${API_BASE}/archer-tickets/${ticket.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ exc_number: form.exc_number, archer_url: form.archer_url, status: form.status, }), }); if (!response.ok) { const data = await response.json(); throw new Error(data.error || 'Failed to update Archer ticket'); } toast.success('Archer ticket updated'); } else { const response = await fetch(`${API_BASE}/archer-tickets`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify(form), }); if (!response.ok) { const data = await response.json(); throw new Error(data.error || 'Failed to create Archer ticket'); } toast.success('Archer ticket added'); } onSuccess(); onClose(); } catch (err) { toast.error(err.message); } }; return (