import { toast } from 'react-toastify'; import ReactModal from 'react-modal'; import { useState } from 'react'; import { BoltProblemStatus, updateProblem } from '~/lib/replay/Problems'; import type { BoltProblem, BoltProblemInput } from '~/lib/replay/Problems'; import { getOrFetchLastLoadedProblem } from '~/components/chat/LoadProblemButton'; import { getLastUserSimulationData, getLastSimulationChatMessages, getSimulationRecordingId, isSimulatingOrHasFinished, } from '~/lib/replay/SimulationPrompt'; ReactModal.setAppElement('#root'); /* * Component for saving input simulation and prompt information for * the problem the current chat was loaded from. */ export function SaveSolution() { const [isModalOpen, setIsModalOpen] = useState(false); const [formData, setFormData] = useState({ evaluator: '', }); const [savedSolution, setSavedSolution] = useState(false); const [problem, setProblem] = useState(null); const handleSaveSolution = async () => { const loadId = toast.loading('Loading problem...'); try { const savedProblem = await getOrFetchLastLoadedProblem(); if (!savedProblem) { toast.error('No problem loaded'); return; } setProblem(savedProblem); setFormData({ evaluator: savedProblem.solution?.evaluator || '', }); } finally { toast.dismiss(loadId); } setSavedSolution(false); setIsModalOpen(true); }; const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value, })); }; const handleSubmitSolution = async () => { if (!problem) { toast.error('No problem loaded'); return; } if (!isSimulatingOrHasFinished()) { toast.error('No simulation found (neither in progress nor finished)'); return; } try { const loadId = toast.loading('Waiting for recording...'); try { /* * Wait for simulation to finish. * const recordingId = */ await getSimulationRecordingId(); } finally { toast.dismiss(loadId); } toast.info('Submitting solution...'); console.log('SubmitSolution', formData); const simulationData = getLastUserSimulationData(); if (!simulationData) { toast.error('No simulation data found'); return; } const messages = getLastSimulationChatMessages(); if (!messages) { toast.error('No user prompt found'); return; } /* * The evaluator is only present when the problem has been solved. * We still create a "solution" object even if it hasn't been * solved quite yet, which is used for working on the problem. * * TODO: Split `solution` into `reproData` and `evaluator`. */ const evaluator = formData.evaluator.length ? formData.evaluator : undefined; const problemUpdatePacket: BoltProblemInput = { version: 2, title: problem.title, description: problem.description, username: problem.username, repositoryContents: problem.repositoryContents, status: evaluator ? BoltProblemStatus.Solved : BoltProblemStatus.Unsolved, solution: { simulationData, messages, evaluator, /* * TODO: Also store recordingId for easier debugging. * recordingId, */ }, }; await updateProblem(problem.problemId, problemUpdatePacket); setSavedSolution(true); } catch (error: any) { console.error('Error saving solution', error?.stack || error); toast.error(`Error saving solution: ${error?.message}`); } }; return ( <> Save Solution setIsModalOpen(false)} className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg p-6 max-w-2xl w-full z-50" overlayClassName="fixed inset-0 bg-black bg-opacity-50 z-40" > {savedSolution && ( <>
Solution Saved
)} {!savedSolution && ( <>
Save solution for loaded problem from last prompt and recording.
Evaluator describes a condition the explanation must satisfy.
Leave the evaluator blank if the API explanation is not right and the problem isn't solved yet.
Evaluator:
)}
); }