diff --git a/apps/rowboat/app/projects/[projectId]/simulation/app.tsx b/apps/rowboat/app/projects/[projectId]/simulation/app.tsx index ed409c2d..f119dc38 100644 --- a/apps/rowboat/app/projects/[projectId]/simulation/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/simulation/app.tsx @@ -18,6 +18,8 @@ import { import { type WithStringId } from '../../../lib/types/types'; import { Scenario, SimulationRun, SimulationResult } from "../../../lib/types/testing_types"; import { z } from 'zod'; +import { SimulationResultCard, ScenarioResultCard } from './components/RunComponents'; +import { ScenarioViewer, ScenarioEditor } from './components/ScenarioComponents'; type ScenarioType = WithStringId>; type SimulationRunType = WithStringId>; @@ -58,256 +60,6 @@ const dummySimulator = async (scenario: ScenarioType, runId: string, projectId: return result; }; -interface SimulationResultCardProps { - run: SimulationRunType; - results: SimulationResultType[]; - scenarios: ScenarioType[]; -} - -interface ScenarioResultCardProps { - scenario: ScenarioType; - result?: SimulationResultType; -} - -const SimulationResultCard = ({ run, results, scenarios }: SimulationResultCardProps) => { - const [isExpanded, setIsExpanded] = useState(false); - const [expandedScenarios, setExpandedScenarios] = useState>(new Set()); - - const statusLabelClass = "px-3 py-1 rounded text-xs min-w-[60px] text-center uppercase font-semibold"; - - const formatMainTitle = (date: string) => { - return `Run from ${new Date(date).toLocaleString('en-US', { - month: 'numeric', - day: 'numeric', - year: 'numeric', - hour: 'numeric', - minute: '2-digit', - second: '2-digit', - hour12: true - })}`; - }; - - const formatDateTime = (date: string) => { - return new Date(date).toLocaleString('en-US', { - month: 'numeric', - day: 'numeric', - year: 'numeric', - hour: 'numeric', - minute: '2-digit', - second: '2-digit', - hour12: true - }); - }; - - // Calculate statistics and duration - const totalScenarios = run.scenarioIds.length; - const passedScenarios = results.filter(r => r.result === 'pass').length; - const failedScenarios = results.filter(r => r.result === 'fail').length; - - const getDuration = () => { - if (!run.completedAt) return 'In Progress'; - const start = new Date(run.startedAt); - const end = new Date(run.completedAt); - const diff = end.getTime() - start.getTime(); - return `${(diff / 1000).toFixed(1)}s`; - }; - - const toggleScenario = (scenarioId: string, e: React.MouseEvent) => { - e.stopPropagation(); // Prevent triggering parent's onClick - setExpandedScenarios(prev => { - const newSet = new Set(prev); - if (newSet.has(scenarioId)) { - newSet.delete(scenarioId); - } else { - newSet.add(scenarioId); - } - return newSet; - }); - }; - - return ( -
-
setIsExpanded(!isExpanded)} - > -
- {isExpanded ? ( - - ) : ( - - )} -
- {formatMainTitle(run.startedAt)} -
-
- - {run.status} - -
- - {isExpanded && ( -
- {/* Simplified timing information */} -
-
- Completed: - {run.completedAt ? formatDateTime(run.completedAt) : 'Not completed'} -
-
- Duration: - {getDuration()} -
-
- - {/* Results statistics */} -
-
-
Total Scenarios
-
{totalScenarios}
-
-
-
Passed
-
{passedScenarios}
-
-
-
Failed
-
{failedScenarios}
-
-
- -
- {run.scenarioIds.map(scenarioId => { - const scenario = scenarios.find(s => s._id === scenarioId); - const result = results.find(r => r.scenarioId === scenarioId); - const isScenarioExpanded = expandedScenarios.has(scenarioId); - - return scenario && ( -
-
toggleScenario(scenarioId, e)} - > -
- {isScenarioExpanded ? ( - - ) : ( - - )} - {scenario.name} -
- {result && ( - - {result.result} - - )} -
- - {isScenarioExpanded && ( -
-
-
Description
-
- {scenario.description} -
-
-
-
Criteria
-
- {scenario.criteria || 'No criteria specified'} -
-
-
-
Context
-
- {scenario.context || 'No context provided'} -
-
- {result && ( -
-
Result Details
-
- {result.details} -
-
- )} -
- )} -
- ); - })} -
-
- )} -
- ); -}; - -const ScenarioResultCard = ({ scenario, result }: ScenarioResultCardProps) => { - const [isExpanded, setIsExpanded] = useState(false); - - return ( -
-
setIsExpanded(!isExpanded)} - > -
- {isExpanded ? ( - - ) : ( - - )} - {scenario.name} -
- {result && ( - - {result.result} - - )} -
- - {isExpanded && ( -
-
-
Description
-
{scenario.description}
-
-
-
Criteria
-
{scenario.criteria}
-
-
-
Context
-
{scenario.context}
-
- {result && ( -
-
Result Details
-
{result.details}
-
- )} -
- )} -
- ); -}; - export default function SimulationApp() { const { projectId } = useParams(); const router = useRouter(); @@ -639,165 +391,3 @@ export default function SimulationApp() { ); } - -function ScenarioViewer({ - scenario, - onEdit, - onClose, -}: { - scenario: ScenarioType; - onEdit: () => void; - onClose: () => void; -}) { - return ( -
-
-

{scenario.name}

-
- - -
-
-
-
-
NAME
-
{scenario.name}
-
- -
- -
-
DESCRIPTION
-
{scenario.description}
-
- -
- -
-
CRITERIA
-
{scenario.criteria}
-
- -
- -
-
CONTEXT
-
{scenario.context}
-
-
-
- ); -} - -function ScenarioEditor({ - scenario, - onSave, - onCancel, -}: { - scenario: ScenarioType; - onSave: (scenario: ScenarioType) => void; - onCancel: () => void; -}) { - const [name, setName] = useState(scenario.name); - const [description, setDescription] = useState(scenario.description); - const [criteria, setCriteria] = useState(scenario.criteria || ''); - const [context, setContext] = useState(scenario.context || ''); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - onSave({ - ...scenario, - name, - description, - criteria, - context, - }); - }; - - return ( -
-
-

Edit Scenario

-
- - -
-
-
-
-
NAME
- setName(e.target.value)} - className="mt-1 block w-full rounded-md border-2 border-gray-300 shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 px-3 py-2" - placeholder="An identifiable scenario name" - /> -
- -
- -
-
DESCRIPTION
-