Refactor app.tsx in simulation

This commit is contained in:
akhisud3195 2025-02-14 16:22:12 +05:30
parent d6d2d2bf6b
commit cca55c3773
3 changed files with 430 additions and 412 deletions

View file

@ -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<z.infer<typeof Scenario>>;
type SimulationRunType = WithStringId<z.infer<typeof SimulationRun>>;
@ -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<Set<string>>(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 (
<div className="border rounded-lg mb-4 shadow-sm">
<div
className="p-4 flex items-center justify-between cursor-pointer hover:bg-gray-50"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex items-center space-x-2">
{isExpanded ? (
<ChevronDownIcon className="h-5 w-5 text-gray-400" />
) : (
<ChevronRightIcon className="h-5 w-5 text-gray-400" />
)}
<div className="text-lg font-semibold">
{formatMainTitle(run.startedAt)}
</div>
</div>
<span className={`${statusLabelClass} ${
run.status === 'completed' ? 'bg-green-100 text-green-800' :
run.status === 'failed' ? 'bg-red-100 text-red-800' :
'bg-yellow-100 text-yellow-800'
}`}>
{run.status}
</span>
</div>
{isExpanded && (
<div className="p-4 border-t">
{/* Simplified timing information */}
<div className="mb-6 text-sm text-gray-500 space-y-1">
<div className="flex items-center">
<span className="w-24 text-gray-600">Completed:</span>
<span>{run.completedAt ? formatDateTime(run.completedAt) : 'Not completed'}</span>
</div>
<div className="flex items-center">
<span className="w-24 text-gray-600">Duration:</span>
<span>{getDuration()}</span>
</div>
</div>
{/* Results statistics */}
<div className="grid grid-cols-3 gap-4 mb-6">
<div className="p-4 rounded-lg bg-gray-50">
<div className="text-sm text-gray-600">Total Scenarios</div>
<div className="text-2xl font-semibold">{totalScenarios}</div>
</div>
<div className="p-4 rounded-lg bg-green-50">
<div className="text-sm text-green-600">Passed</div>
<div className="text-2xl font-semibold text-green-700">{passedScenarios}</div>
</div>
<div className="p-4 rounded-lg bg-red-50">
<div className="text-sm text-red-600">Failed</div>
<div className="text-2xl font-semibold text-red-700">{failedScenarios}</div>
</div>
</div>
<div className="space-y-2">
{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 && (
<div
key={scenarioId}
className={`border rounded-lg overflow-hidden ${
result?.result === 'pass' ? 'bg-green-50 border-green-200' :
result?.result === 'fail' ? 'bg-red-50 border-red-200' :
'bg-gray-50 border-gray-200'
}`}
>
<div
className="p-3 flex items-center justify-between cursor-pointer hover:bg-opacity-80"
onClick={(e) => toggleScenario(scenarioId, e)}
>
<div className="flex items-center space-x-2">
{isScenarioExpanded ? (
<ChevronDownIcon className="h-4 w-4 text-gray-600" />
) : (
<ChevronRightIcon className="h-4 w-4 text-gray-600" />
)}
<span className="font-medium text-gray-900">{scenario.name}</span>
</div>
{result && (
<span className={`${statusLabelClass} ${
result.result === 'pass' ? 'bg-green-200 text-green-900' : 'bg-red-200 text-red-900'
}`}>
{result.result}
</span>
)}
</div>
{isScenarioExpanded && (
<div className="p-3 border-t border-opacity-50 space-y-4">
<div>
<div className="text-sm font-medium mb-1">Description</div>
<div className="text-sm text-gray-700">
{scenario.description}
</div>
</div>
<div>
<div className="text-sm font-medium mb-1">Criteria</div>
<div className="text-sm text-gray-700">
{scenario.criteria || 'No criteria specified'}
</div>
</div>
<div>
<div className="text-sm font-medium mb-1">Context</div>
<div className="text-sm text-gray-700">
{scenario.context || 'No context provided'}
</div>
</div>
{result && (
<div>
<div className="text-sm font-medium mb-1">Result Details</div>
<div className="text-sm text-gray-700">
{result.details}
</div>
</div>
)}
</div>
)}
</div>
);
})}
</div>
</div>
)}
</div>
);
};
const ScenarioResultCard = ({ scenario, result }: ScenarioResultCardProps) => {
const [isExpanded, setIsExpanded] = useState(false);
return (
<div className="border rounded-lg mb-2 last:mb-0">
<div
className="p-3 flex items-center justify-between cursor-pointer hover:bg-gray-50"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex items-center space-x-2">
{isExpanded ? (
<ChevronDownIcon className="h-4 w-4 text-gray-400" />
) : (
<ChevronRightIcon className="h-4 w-4 text-gray-400" />
)}
<span className="font-medium">{scenario.name}</span>
</div>
{result && (
<span className={`px-2 py-1 rounded-full text-xs ${
result.result === 'pass' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
}`}>
{result.result}
</span>
)}
</div>
{isExpanded && (
<div className="p-3 border-t space-y-2 bg-gray-50">
<div>
<div className="text-sm font-medium text-gray-600">Description</div>
<div className="text-sm">{scenario.description}</div>
</div>
<div>
<div className="text-sm font-medium text-gray-600">Criteria</div>
<div className="text-sm">{scenario.criteria}</div>
</div>
<div>
<div className="text-sm font-medium text-gray-600">Context</div>
<div className="text-sm">{scenario.context}</div>
</div>
{result && (
<div>
<div className="text-sm font-medium text-gray-600">Result Details</div>
<div className="text-sm">{result.details}</div>
</div>
)}
</div>
)}
</div>
);
};
export default function SimulationApp() {
const { projectId } = useParams();
const router = useRouter();
@ -639,165 +391,3 @@ export default function SimulationApp() {
</div>
);
}
function ScenarioViewer({
scenario,
onEdit,
onClose,
}: {
scenario: ScenarioType;
onEdit: () => void;
onClose: () => void;
}) {
return (
<div>
<div className="flex justify-between items-center mb-6">
<h1 className="text-2xl font-bold">{scenario.name}</h1>
<div className="flex gap-2">
<button
onClick={onEdit}
className="p-2 rounded-full hover:bg-gray-100"
title="Edit"
>
<PencilIcon className="h-5 w-5 text-gray-600" />
</button>
<button
onClick={onClose}
className="p-2 rounded-full hover:bg-gray-100"
title="Close"
>
<XMarkIcon className="h-5 w-5 text-gray-600" />
</button>
</div>
</div>
<div className="flex flex-col gap-4">
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">NAME</div>
<div className="text-base">{scenario.name}</div>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">DESCRIPTION</div>
<div className="text-base whitespace-pre-wrap">{scenario.description}</div>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CRITERIA</div>
<div className="text-base whitespace-pre-wrap">{scenario.criteria}</div>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CONTEXT</div>
<div className="text-base whitespace-pre-wrap">{scenario.context}</div>
</div>
</div>
</div>
);
}
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 (
<div>
<div className="flex justify-between items-center mb-6">
<h1 className="text-2xl font-bold">Edit Scenario</h1>
<div className="flex gap-2">
<button
onClick={() => handleSubmit({ preventDefault: () => {} } as React.FormEvent)}
className="p-2 rounded-full hover:bg-gray-100"
title="Save"
>
<DocumentDuplicateIcon className="h-5 w-5 text-gray-600" />
</button>
<button
onClick={onCancel}
className="p-2 rounded-full hover:bg-gray-100"
title="Close"
>
<XMarkIcon className="h-5 w-5 text-gray-600" />
</button>
</div>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">NAME</div>
<input
type="text"
value={name}
onChange={(e) => 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"
/>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">DESCRIPTION</div>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
rows={4}
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="Specify the user scenario that the simulator should simulate"
/>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CRITERIA</div>
<textarea
value={criteria}
onChange={(e) => setCriteria(e.target.value)}
rows={4}
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="Enter success criteria for this scenario"
/>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CONTEXT</div>
<textarea
value={context}
onChange={(e) => setContext(e.target.value)}
rows={4}
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="Provide context about the user to the assistant at the start of chat"
/>
</div>
</form>
</div>
);
}

View file

@ -0,0 +1,261 @@
'use client';
import { useState } from 'react';
import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
import { WithStringId } from '../../../../lib/types/types';
import { Scenario, SimulationRun, SimulationResult } from "../../../../lib/types/testing_types";
import { z } from 'zod';
type ScenarioType = WithStringId<z.infer<typeof Scenario>>;
type SimulationRunType = WithStringId<z.infer<typeof SimulationRun>>;
type SimulationResultType = WithStringId<z.infer<typeof SimulationResult>>;
interface SimulationResultCardProps {
run: SimulationRunType;
results: SimulationResultType[];
scenarios: ScenarioType[];
}
export const SimulationResultCard = ({ run, results, scenarios }: SimulationResultCardProps) => {
const [isExpanded, setIsExpanded] = useState(false);
const [expandedScenarios, setExpandedScenarios] = useState<Set<string>>(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 (
<div className="border rounded-lg mb-4 shadow-sm">
<div
className="p-4 flex items-center justify-between cursor-pointer hover:bg-gray-50"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex items-center space-x-2">
{isExpanded ? (
<ChevronDownIcon className="h-5 w-5 text-gray-400" />
) : (
<ChevronRightIcon className="h-5 w-5 text-gray-400" />
)}
<div className="text-lg font-semibold">
{formatMainTitle(run.startedAt)}
</div>
</div>
<span className={`${statusLabelClass} ${
run.status === 'completed' ? 'bg-green-100 text-green-800' :
run.status === 'failed' ? 'bg-red-100 text-red-800' :
'bg-yellow-100 text-yellow-800'
}`}>
{run.status}
</span>
</div>
{isExpanded && (
<div className="p-4 border-t">
{/* Simplified timing information */}
<div className="mb-6 text-sm text-gray-500 space-y-1">
<div className="flex items-center">
<span className="w-24 text-gray-600">Completed:</span>
<span>{run.completedAt ? formatDateTime(run.completedAt) : 'Not completed'}</span>
</div>
<div className="flex items-center">
<span className="w-24 text-gray-600">Duration:</span>
<span>{getDuration()}</span>
</div>
</div>
{/* Results statistics */}
<div className="grid grid-cols-3 gap-4 mb-6">
<div className="p-4 rounded-lg bg-gray-50">
<div className="text-sm text-gray-600">Total Scenarios</div>
<div className="text-2xl font-semibold">{totalScenarios}</div>
</div>
<div className="p-4 rounded-lg bg-green-50">
<div className="text-sm text-green-600">Passed</div>
<div className="text-2xl font-semibold text-green-700">{passedScenarios}</div>
</div>
<div className="p-4 rounded-lg bg-red-50">
<div className="text-sm text-red-600">Failed</div>
<div className="text-2xl font-semibold text-red-700">{failedScenarios}</div>
</div>
</div>
<div className="space-y-2">
{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 && (
<div
key={scenarioId}
className={`border rounded-lg overflow-hidden ${
result?.result === 'pass' ? 'bg-green-50 border-green-200' :
result?.result === 'fail' ? 'bg-red-50 border-red-200' :
'bg-gray-50 border-gray-200'
}`}
>
<div
className="p-3 flex items-center justify-between cursor-pointer hover:bg-opacity-80"
onClick={(e) => toggleScenario(scenarioId, e)}
>
<div className="flex items-center space-x-2">
{isScenarioExpanded ? (
<ChevronDownIcon className="h-4 w-4 text-gray-600" />
) : (
<ChevronRightIcon className="h-4 w-4 text-gray-600" />
)}
<span className="font-medium text-gray-900">{scenario.name}</span>
</div>
{result && (
<span className={`${statusLabelClass} ${
result.result === 'pass' ? 'bg-green-200 text-green-900' : 'bg-red-200 text-red-900'
}`}>
{result.result}
</span>
)}
</div>
{isScenarioExpanded && (
<div className="p-3 border-t border-opacity-50 space-y-4">
<div>
<div className="text-sm font-medium mb-1">Description</div>
<div className="text-sm text-gray-700">
{scenario.description}
</div>
</div>
<div>
<div className="text-sm font-medium mb-1">Criteria</div>
<div className="text-sm text-gray-700">
{scenario.criteria || 'No criteria specified'}
</div>
</div>
<div>
<div className="text-sm font-medium mb-1">Context</div>
<div className="text-sm text-gray-700">
{scenario.context || 'No context provided'}
</div>
</div>
{result && (
<div>
<div className="text-sm font-medium mb-1">Result Details</div>
<div className="text-sm text-gray-700">
{result.details}
</div>
</div>
)}
</div>
)}
</div>
);
})}
</div>
</div>
)}
</div>
);
};
interface ScenarioResultCardProps {
scenario: ScenarioType;
result?: SimulationResultType;
}
export const ScenarioResultCard = ({ scenario, result }: ScenarioResultCardProps) => {
const [isExpanded, setIsExpanded] = useState(false);
return (
<div className="border rounded-lg mb-2 last:mb-0">
<div
className="p-3 flex items-center justify-between cursor-pointer hover:bg-gray-50"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex items-center space-x-2">
{isExpanded ? (
<ChevronDownIcon className="h-4 w-4 text-gray-400" />
) : (
<ChevronRightIcon className="h-4 w-4 text-gray-400" />
)}
<span className="font-medium">{scenario.name}</span>
</div>
{result && (
<span className={`px-2 py-1 rounded-full text-xs ${
result.result === 'pass' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
}`}>
{result.result}
</span>
)}
</div>
{isExpanded && (
<div className="p-3 border-t space-y-2 bg-gray-50">
<div>
<div className="text-sm font-medium text-gray-600">Description</div>
<div className="text-sm">{scenario.description}</div>
</div>
<div>
<div className="text-sm font-medium text-gray-600">Criteria</div>
<div className="text-sm">{scenario.criteria}</div>
</div>
<div>
<div className="text-sm font-medium text-gray-600">Context</div>
<div className="text-sm">{scenario.context}</div>
</div>
{result && (
<div>
<div className="text-sm font-medium text-gray-600">Result Details</div>
<div className="text-sm">{result.details}</div>
</div>
)}
</div>
)}
</div>
);
};

View file

@ -0,0 +1,167 @@
'use client';
import { useState } from 'react';
import { PencilIcon, XMarkIcon, DocumentDuplicateIcon } from '@heroicons/react/24/outline';
import { WithStringId } from '../../../../lib/types/types';
import { Scenario } from "../../../../lib/types/testing_types";
import { z } from 'zod';
type ScenarioType = WithStringId<z.infer<typeof Scenario>>;
interface ScenarioViewerProps {
scenario: ScenarioType;
onEdit: () => void;
onClose: () => void;
}
export function ScenarioViewer({ scenario, onEdit, onClose }: ScenarioViewerProps) {
return (
<div>
<div className="flex justify-between items-center mb-6">
<h1 className="text-2xl font-bold">{scenario.name}</h1>
<div className="flex gap-2">
<button
onClick={onEdit}
className="p-2 rounded-full hover:bg-gray-100"
title="Edit"
>
<PencilIcon className="h-5 w-5 text-gray-600" />
</button>
<button
onClick={onClose}
className="p-2 rounded-full hover:bg-gray-100"
title="Close"
>
<XMarkIcon className="h-5 w-5 text-gray-600" />
</button>
</div>
</div>
<div className="flex flex-col gap-4">
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">NAME</div>
<div className="text-base">{scenario.name}</div>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">DESCRIPTION</div>
<div className="text-base whitespace-pre-wrap">{scenario.description}</div>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CRITERIA</div>
<div className="text-base whitespace-pre-wrap">{scenario.criteria}</div>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div className="flex flex-col">
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CONTEXT</div>
<div className="text-base whitespace-pre-wrap">{scenario.context}</div>
</div>
</div>
</div>
);
}
interface ScenarioEditorProps {
scenario: ScenarioType;
onSave: (scenario: ScenarioType) => void;
onCancel: () => void;
}
export function ScenarioEditor({ scenario, onSave, onCancel }: ScenarioEditorProps) {
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 (
<div>
<div className="flex justify-between items-center mb-6">
<h1 className="text-2xl font-bold">Edit Scenario</h1>
<div className="flex gap-2">
<button
onClick={() => handleSubmit({ preventDefault: () => {} } as React.FormEvent)}
className="p-2 rounded-full hover:bg-gray-100"
title="Save"
>
<DocumentDuplicateIcon className="h-5 w-5 text-gray-600" />
</button>
<button
onClick={onCancel}
className="p-2 rounded-full hover:bg-gray-100"
title="Close"
>
<XMarkIcon className="h-5 w-5 text-gray-600" />
</button>
</div>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">NAME</div>
<input
type="text"
value={name}
onChange={(e) => 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"
/>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">DESCRIPTION</div>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
rows={4}
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="Specify the user scenario that the simulator should simulate"
/>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CRITERIA</div>
<textarea
value={criteria}
onChange={(e) => setCriteria(e.target.value)}
rows={4}
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="Enter success criteria for this scenario"
/>
</div>
<div className="border-t border-gray-200 my-4"></div>
<div>
<div className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-4">CONTEXT</div>
<textarea
value={context}
onChange={(e) => setContext(e.target.value)}
rows={4}
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="Provide context about the user to the assistant at the start of chat"
/>
</div>
</form>
</div>
);
}