diff options
Diffstat (limited to 'frontend/src/components/ContractCreateModal.tsx')
| -rw-r--r-- | frontend/src/components/ContractCreateModal.tsx | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/frontend/src/components/ContractCreateModal.tsx b/frontend/src/components/ContractCreateModal.tsx new file mode 100644 index 0000000..e1d9732 --- /dev/null +++ b/frontend/src/components/ContractCreateModal.tsx @@ -0,0 +1,185 @@ +import React, { useState } from 'react' + +interface ContractCreateModalProps { + isOpen: boolean + onClose: () => void + onCreated: () => void +} + +interface CreateContractForm { + name: string + description: string + contractType: string + redTeamEnabled: boolean + redTeamPrompt: string +} + +export function ContractCreateModal({ isOpen, onClose, onCreated }: ContractCreateModalProps) { + const [form, setForm] = useState<CreateContractForm>({ + name: '', + description: '', + contractType: 'simple', + redTeamEnabled: false, + redTeamPrompt: '', + }) + const [loading, setLoading] = useState(false) + const [error, setError] = useState<string | null>(null) + + if (!isOpen) return null + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + setError(null) + + try { + const response = await fetch('/api/v1/contracts', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: form.name, + description: form.description || undefined, + contract_type: form.contractType, + red_team_enabled: form.redTeamEnabled, + red_team_prompt: form.redTeamEnabled && form.redTeamPrompt ? form.redTeamPrompt : undefined, + }), + }) + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})) + throw new Error(errorData.message || `Failed to create contract: ${response.statusText}`) + } + + // Reset form and close modal + setForm({ + name: '', + description: '', + contractType: 'simple', + redTeamEnabled: false, + redTeamPrompt: '', + }) + onCreated() + onClose() + } catch (err) { + setError(err instanceof Error ? err.message : 'Unknown error') + } finally { + setLoading(false) + } + } + + return ( + <div className="modal-overlay" onClick={onClose}> + <div className="settings-modal contract-create-modal" onClick={(e) => e.stopPropagation()}> + <div className="modal-header"> + <h2 className="modal-title">Create Contract</h2> + <button className="modal-close-btn" onClick={onClose}> + × + </button> + </div> + + <form onSubmit={handleSubmit}> + <div className="modal-content"> + {error && ( + <div className="form-error"> + {error} + </div> + )} + + <div className="settings-section"> + <h3>Contract Details</h3> + + <div className="setting-item"> + <label> + Name + <input + type="text" + value={form.name} + onChange={(e) => setForm({ ...form, name: e.target.value })} + placeholder="Enter contract name" + required + className="form-input" + /> + </label> + </div> + + <div className="setting-item"> + <label> + Description + <textarea + value={form.description} + onChange={(e) => setForm({ ...form, description: e.target.value })} + placeholder="Enter contract description (optional)" + className="form-textarea" + rows={3} + /> + </label> + </div> + + <div className="setting-item"> + <label> + Contract Type + <select + value={form.contractType} + onChange={(e) => setForm({ ...form, contractType: e.target.value })} + className="form-select" + > + <option value="simple">Simple</option> + <option value="specification">Specification</option> + <option value="execute">Execute</option> + </select> + </label> + </div> + </div> + + <div className="settings-section"> + <h3>Red Team Monitoring</h3> + + <div className="setting-item"> + <label className="checkbox-label"> + <input + type="checkbox" + checked={form.redTeamEnabled} + onChange={(e) => setForm({ ...form, redTeamEnabled: e.target.checked })} + /> + <span>Enable Red Team monitoring</span> + </label> + <div className="setting-description"> + Spawns a parallel task that monitors work output for quality and compliance + </div> + </div> + + {form.redTeamEnabled && ( + <div className="setting-item red-team-prompt-container"> + <label> + Custom review criteria (optional) + <textarea + value={form.redTeamPrompt} + onChange={(e) => setForm({ ...form, redTeamPrompt: e.target.value })} + placeholder="Enter custom criteria for the red team to evaluate against... (e.g., 'Ensure all functions have proper error handling', 'Verify security best practices are followed')" + className="form-textarea" + rows={4} + /> + </label> + <div className="setting-description"> + Provide specific criteria for the red team to focus on during reviews + </div> + </div> + )} + </div> + </div> + + <div className="modal-footer"> + <button type="button" className="modal-btn secondary" onClick={onClose} disabled={loading}> + Cancel + </button> + <button type="submit" className="modal-btn primary" disabled={loading || !form.name.trim()}> + {loading ? 'Creating...' : 'Create Contract'} + </button> + </div> + </form> + </div> + </div> + ) +} |
