mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-09 19:45:17 +02:00
Add dark mode support for testing pages
This commit is contained in:
parent
d877486978
commit
9f2854a22c
5 changed files with 141 additions and 161 deletions
|
|
@ -48,13 +48,17 @@ export function App({
|
|||
{menuItems.map((item) => (
|
||||
<li key={item.label}>
|
||||
<Link
|
||||
className={`block p-2 rounded-md text-sm ${pathname.startsWith(item.href) ? "bg-gray-100" : "hover:bg-gray-100"}`}
|
||||
className={`block p-2 rounded-md text-sm ${
|
||||
pathname.startsWith(item.href)
|
||||
? "bg-gray-100 dark:bg-neutral-800"
|
||||
: "hover:bg-gray-100 dark:hover:bg-neutral-800"
|
||||
}`}
|
||||
href={item.href}>{item.label}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="grow border-l border-gray-200 p-2">
|
||||
<div className="grow border-l border-gray-200 dark:border-neutral-800 p-2">
|
||||
{selection === "scenarios" && <ScenariosApp projectId={projectId} slug={innerSlug} />}
|
||||
{selection === "profiles" && <ProfilesApp projectId={projectId} slug={innerSlug} />}
|
||||
{selection === "simulations" && <SimulationsApp projectId={projectId} slug={innerSlug} />}
|
||||
|
|
|
|||
|
|
@ -60,12 +60,12 @@ function EditProfile({
|
|||
}
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">Edit Profile</h1>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">Edit Profile</h1>
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{error && <div className="bg-red-100 p-2 rounded-md text-red-800 flex items-center gap-2 text-sm">
|
||||
{error && <div className="bg-red-100 dark:bg-red-900/20 p-2 rounded-md text-red-800 dark:text-red-400 flex items-center gap-2 text-sm">
|
||||
{error}
|
||||
<Button size="sm" color="danger" onPress={() => formRef.current?.requestSubmit()}>Retry</Button>
|
||||
</div>}
|
||||
|
|
@ -157,7 +157,7 @@ function ViewProfile({
|
|||
}
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">View Profile</h1>
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">View Profile</h1>
|
||||
<Button
|
||||
size="sm"
|
||||
className="self-start"
|
||||
|
|
@ -167,39 +167,39 @@ function ViewProfile({
|
|||
>
|
||||
All Profiles
|
||||
</Button>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{!loading && !profile && <div className="text-gray-600 text-center">Profile not found</div>}
|
||||
{!loading && !profile && <div className="text-gray-600 dark:text-neutral-400 text-center">Profile not found</div>}
|
||||
{!loading && profile && (
|
||||
<>
|
||||
<div className="flex flex-col gap-1 text-sm">
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Name</div>
|
||||
<div className="flex-[2]">
|
||||
<div className="flex-[2] whitespace-pre-wrap">{profile.name}</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Name</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{profile.name}</div>
|
||||
</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Context</div>
|
||||
<div className="flex-[2] whitespace-pre-wrap dark:text-neutral-200">{profile.context}</div>
|
||||
</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Mock Tools</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{profile.mockTools ? "Yes" : "No"}</div>
|
||||
</div>
|
||||
{profile.mockPrompt && (
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Mock Prompt</div>
|
||||
<div className="flex-[2] whitespace-pre-wrap dark:text-neutral-200">{profile.mockPrompt}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Created</div>
|
||||
<div className="flex-[2] dark:text-neutral-300"><RelativeTime date={new Date(profile.createdAt)} /></div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Context</div>
|
||||
<div className="flex-[2] whitespace-pre-wrap">{profile.context}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Mock Tools</div>
|
||||
<div className="flex-[2]">{profile.mockTools ? "Yes" : "No"}</div>
|
||||
</div>
|
||||
{profile.mockPrompt && <div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Mock Prompt</div>
|
||||
<div className="flex-[2] whitespace-pre-wrap">{profile.mockPrompt}</div>
|
||||
</div>}
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Created</div>
|
||||
<div className="flex-[2]"><RelativeTime date={new Date(profile.createdAt)} /></div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Last Updated</div>
|
||||
<div className="flex-[2]"><RelativeTime date={new Date(profile.lastUpdatedAt)} /></div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Last Updated</div>
|
||||
<div className="flex-[2] dark:text-neutral-300"><RelativeTime date={new Date(profile.lastUpdatedAt)} /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2 mt-4">
|
||||
|
|
@ -413,7 +413,7 @@ function ProfileList({
|
|||
}, [page, pageSize, error, projectId]);
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">Profiles</h1>
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">Profiles</h1>
|
||||
<Button
|
||||
size="sm"
|
||||
onPress={() => router.push(`/projects/${projectId}/test/profiles/new`)}
|
||||
|
|
@ -422,43 +422,43 @@ function ProfileList({
|
|||
>
|
||||
New Profile
|
||||
</Button>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{error && <div className="bg-red-100 p-2 rounded-md text-red-800 flex items-center gap-2 text-sm">
|
||||
{error && <div className="bg-red-100 dark:bg-red-900/20 p-2 rounded-md text-red-800 dark:text-red-400 flex items-center gap-2 text-sm">
|
||||
{error}
|
||||
<Button size="sm" color="danger" onPress={() => setError(null)}>Retry</Button>
|
||||
</div>}
|
||||
{!loading && !error && <>
|
||||
{profiles.length === 0 && <div className="text-gray-600 text-center">No profiles found</div>}
|
||||
{profiles.length === 0 && <div className="text-gray-600 dark:text-neutral-400 text-center">No profiles found</div>}
|
||||
{profiles.length > 0 && <div className="flex flex-col w-full">
|
||||
{/* Header */}
|
||||
<div className="grid grid-cols-8 py-2 bg-gray-100 font-semibold text-sm">
|
||||
<div className="col-span-2 px-4">Name</div>
|
||||
<div className="col-span-3 px-4">Context</div>
|
||||
<div className="col-span-1 px-4">Mock Tools</div>
|
||||
<div className="col-span-1 px-4">Created</div>
|
||||
<div className="col-span-1 px-4">Updated</div>
|
||||
<div className="grid grid-cols-8 py-2 bg-gray-100 dark:bg-neutral-800 font-semibold text-sm">
|
||||
<div className="col-span-2 px-4 dark:text-neutral-300">Name</div>
|
||||
<div className="col-span-3 px-4 dark:text-neutral-300">Context</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Mock Tools</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Created</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Updated</div>
|
||||
</div>
|
||||
|
||||
{/* Rows */}
|
||||
{profiles.map((profile) => (
|
||||
<div key={profile._id} className="grid grid-cols-8 py-2 border-b hover:bg-gray-50 text-sm">
|
||||
<div key={profile._id} className="grid grid-cols-8 py-2 border-b border-gray-200 dark:border-neutral-800 hover:bg-gray-50 dark:hover:bg-neutral-800 text-sm">
|
||||
<div className="col-span-2 px-4 truncate">
|
||||
<Link
|
||||
href={`/projects/${projectId}/test/profiles/${profile._id}`}
|
||||
className="text-blue-600 hover:underline"
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline"
|
||||
>
|
||||
{profile.name}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="col-span-3 px-4 truncate">{profile.context}</div>
|
||||
<div className="col-span-1 px-4">{profile.mockTools ? "Yes" : "No"}</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 truncate">
|
||||
<div className="col-span-3 px-4 truncate dark:text-neutral-300">{profile.context}</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">{profile.mockTools ? "Yes" : "No"}</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 dark:text-neutral-400 truncate">
|
||||
<RelativeTime date={new Date(profile.createdAt)} />
|
||||
</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 truncate">
|
||||
<div className="col-span-1 px-4 text-gray-600 dark:text-neutral-400 truncate">
|
||||
<RelativeTime date={new Date(profile.lastUpdatedAt)} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ function RunList({
|
|||
<Button size="sm" color="danger" onPress={() => setError(null)}>Retry</Button>
|
||||
</div>}
|
||||
{!loading && !error && <>
|
||||
{runs.length === 0 && <div className="text-gray-600 text-center">No test runs found</div>}
|
||||
{runs.length === 0 && <div className="text-gray-600 dark:text-neutral-400 text-center">No test runs found</div>}
|
||||
{runs.length > 0 && <div className="space-y-4">
|
||||
{runs.map((run) => (
|
||||
<div key={run._id} className="border dark:border-neutral-800 rounded-lg shadow-sm">
|
||||
|
|
@ -362,7 +362,7 @@ function RunList({
|
|||
<div className="flex items-center space-x-4">
|
||||
<Link
|
||||
href={`/projects/${projectId}/test/runs/${run._id}`}
|
||||
className="text-blue-600 hover:underline"
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline"
|
||||
>
|
||||
{run.name}
|
||||
</Link>
|
||||
|
|
@ -417,16 +417,16 @@ function getStatusClass(status: string) {
|
|||
const baseClass = "px-2 py-1 rounded text-xs uppercase font-medium";
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return `${baseClass} bg-green-100 text-green-800`;
|
||||
return `${baseClass} bg-green-100 dark:bg-green-900/20 text-green-800 dark:text-green-400`;
|
||||
case 'failed':
|
||||
case 'error':
|
||||
return `${baseClass} bg-red-100 text-red-800`;
|
||||
return `${baseClass} bg-red-100 dark:bg-red-900/20 text-red-800 dark:text-red-400`;
|
||||
case 'cancelled':
|
||||
return `${baseClass} bg-gray-100 text-gray-800`;
|
||||
return `${baseClass} bg-gray-100 dark:bg-neutral-800 text-gray-800 dark:text-neutral-400`;
|
||||
case 'running':
|
||||
case 'pending':
|
||||
default:
|
||||
return `${baseClass} bg-yellow-100 text-yellow-800`;
|
||||
return `${baseClass} bg-yellow-100 dark:bg-yellow-900/20 text-yellow-800 dark:text-yellow-400`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,22 +51,14 @@ function EditScenario({
|
|||
}
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">Edit Scenario</h1>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">Edit Scenario</h1>
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{error && <div className="bg-red-100 p-2 rounded-md text-red-800 flex items-center gap-2 text-sm">
|
||||
{error && <div className="bg-red-100 dark:bg-red-900/20 p-2 rounded-md text-red-800 dark:text-red-400 flex items-center gap-2 text-sm">
|
||||
{error}
|
||||
<Button
|
||||
size="sm"
|
||||
color="danger"
|
||||
onPress={() => {
|
||||
formRef.current?.requestSubmit();
|
||||
}}
|
||||
>
|
||||
Retry
|
||||
</Button>
|
||||
<Button size="sm" color="danger" onPress={() => formRef.current?.requestSubmit()}>Retry</Button>
|
||||
</div>}
|
||||
{!loading && scenario && (
|
||||
<form ref={formRef} action={handleSubmit} className="flex flex-col gap-2">
|
||||
|
|
@ -140,7 +132,7 @@ function ViewScenario({
|
|||
}
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">View Scenario</h1>
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">View Scenario</h1>
|
||||
<Button
|
||||
size="sm"
|
||||
className="self-start"
|
||||
|
|
@ -150,29 +142,29 @@ function ViewScenario({
|
|||
>
|
||||
All Scenarios
|
||||
</Button>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{!loading && !scenario && <div className="text-gray-600 text-center">Scenario not found</div>}
|
||||
{!loading && !scenario && <div className="text-gray-600 dark:text-neutral-400 text-center">Scenario not found</div>}
|
||||
{!loading && scenario && (
|
||||
<>
|
||||
<div className="flex flex-col gap-1 text-sm">
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Name</div>
|
||||
<div className="flex-[2]">{scenario.name}</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Name</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{scenario.name}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Description</div>
|
||||
<div className="flex-[2]">{scenario.description}</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Description</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{scenario.description}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Created</div>
|
||||
<div className="flex-[2]"><RelativeTime date={new Date(scenario.createdAt)} /></div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Created</div>
|
||||
<div className="flex-[2] dark:text-neutral-300"><RelativeTime date={new Date(scenario.createdAt)} /></div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Last Updated</div>
|
||||
<div className="flex-[2]"><RelativeTime date={new Date(scenario.lastUpdatedAt)} /></div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Last Updated</div>
|
||||
<div className="flex-[2] dark:text-neutral-300"><RelativeTime date={new Date(scenario.lastUpdatedAt)} /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2 mt-4">
|
||||
|
|
@ -372,7 +364,7 @@ function ScenarioList({
|
|||
}, [page, pageSize, error, projectId]);
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">Scenarios</h1>
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">Scenarios</h1>
|
||||
<Button
|
||||
size="sm"
|
||||
onPress={() => router.push(`/projects/${projectId}/test/scenarios/new`)}
|
||||
|
|
@ -381,41 +373,41 @@ function ScenarioList({
|
|||
>
|
||||
New Scenario
|
||||
</Button>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{error && <div className="bg-red-100 p-2 rounded-md text-red-800 flex items-center gap-2 text-sm">
|
||||
{error && <div className="bg-red-100 dark:bg-red-900/20 p-2 rounded-md text-red-800 dark:text-red-400 flex items-center gap-2 text-sm">
|
||||
{error}
|
||||
<Button size="sm" color="danger" onPress={() => setError(null)}>Retry</Button>
|
||||
</div>}
|
||||
{!loading && !error && <>
|
||||
{scenarios.length === 0 && <div className="text-gray-600 text-center">No scenarios found</div>}
|
||||
{scenarios.length === 0 && <div className="text-gray-600 dark:text-neutral-400 text-center">No scenarios found</div>}
|
||||
{scenarios.length > 0 && <div className="flex flex-col w-full">
|
||||
{/* Header */}
|
||||
<div className="grid grid-cols-7 py-2 bg-gray-100 font-semibold text-sm">
|
||||
<div className="col-span-2 px-4">Name</div>
|
||||
<div className="col-span-3 px-4">Description</div>
|
||||
<div className="col-span-1 px-4">Created</div>
|
||||
<div className="col-span-1 px-4">Updated</div>
|
||||
<div className="grid grid-cols-7 py-2 bg-gray-100 dark:bg-neutral-800 font-semibold text-sm">
|
||||
<div className="col-span-2 px-4 dark:text-neutral-300">Name</div>
|
||||
<div className="col-span-3 px-4 dark:text-neutral-300">Description</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Created</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Updated</div>
|
||||
</div>
|
||||
|
||||
{/* Rows */}
|
||||
{scenarios.map((scenario) => (
|
||||
<div key={scenario._id} className="grid grid-cols-7 py-2 border-b hover:bg-gray-50 text-sm">
|
||||
<div key={scenario._id} className="grid grid-cols-7 py-2 border-b border-gray-200 dark:border-neutral-800 hover:bg-gray-50 dark:hover:bg-neutral-800 text-sm">
|
||||
<div className="col-span-2 px-4 truncate">
|
||||
<Link
|
||||
href={`/projects/${projectId}/test/scenarios/${scenario._id}`}
|
||||
className="text-blue-600 hover:underline"
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline"
|
||||
>
|
||||
{scenario.name}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="col-span-3 px-4 truncate">{scenario.description}</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 truncate">
|
||||
<div className="col-span-3 px-4 truncate dark:text-neutral-300">{scenario.description}</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 dark:text-neutral-400 truncate">
|
||||
<RelativeTime date={new Date(scenario.createdAt)} />
|
||||
</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 truncate">
|
||||
<div className="col-span-1 px-4 text-gray-600 dark:text-neutral-400 truncate">
|
||||
<RelativeTime date={new Date(scenario.lastUpdatedAt)} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -79,12 +79,12 @@ function EditSimulation({
|
|||
}
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">Edit Simulation</h1>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">Edit Simulation</h1>
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{error && <div className="bg-red-100 p-2 rounded-md text-red-800 flex items-center gap-2 text-sm">
|
||||
{error && <div className="bg-red-100 dark:bg-red-900/20 p-2 rounded-md text-red-800 dark:text-red-400 flex items-center gap-2 text-sm">
|
||||
{error}
|
||||
<Button size="sm" color="danger" onPress={() => formRef.current?.requestSubmit()}>Retry</Button>
|
||||
</div>}
|
||||
|
|
@ -107,12 +107,12 @@ function EditSimulation({
|
|||
required
|
||||
/>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-sm font-medium">Scenario</label>
|
||||
<label className="text-sm font-medium text-gray-700 dark:text-neutral-300">Scenario</label>
|
||||
<div className="flex items-center gap-2">
|
||||
{scenario ? (
|
||||
<div className="text-sm text-blue-600">{scenario.name}</div>
|
||||
<div className="text-sm text-blue-600 dark:text-blue-400">{scenario.name}</div>
|
||||
) : (
|
||||
<div className="text-sm text-gray-500">No scenario selected</div>
|
||||
<div className="text-sm text-gray-500 dark:text-neutral-500">No scenario selected</div>
|
||||
)}
|
||||
<Button
|
||||
size="sm"
|
||||
|
|
@ -124,12 +124,12 @@ function EditSimulation({
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-sm font-medium">Profile (optional)</label>
|
||||
<label className="text-sm font-medium text-gray-700 dark:text-neutral-300">Profile (optional)</label>
|
||||
<div className="flex items-center gap-2">
|
||||
{profile ? (
|
||||
<div className="text-sm text-blue-600">{profile.name}</div>
|
||||
<div className="text-sm text-blue-600 dark:text-blue-400">{profile.name}</div>
|
||||
) : (
|
||||
<div className="text-sm text-gray-500">No profile selected</div>
|
||||
<div className="text-sm text-gray-500 dark:text-neutral-500">No profile selected</div>
|
||||
)}
|
||||
{profile && <Button size="sm" variant="bordered" onClick={() => setProfile(null)}>Remove</Button>}
|
||||
<Button
|
||||
|
|
@ -220,7 +220,7 @@ function ViewSimulation({
|
|||
}
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">View Simulation</h1>
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">View Simulation</h1>
|
||||
<Button
|
||||
size="sm"
|
||||
className="self-start"
|
||||
|
|
@ -230,53 +230,37 @@ function ViewSimulation({
|
|||
>
|
||||
All Simulations
|
||||
</Button>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{!loading && !simulation && <div className="text-gray-600 text-center">Simulation not found</div>}
|
||||
{!loading && !simulation && <div className="text-gray-600 dark:text-neutral-400 text-center">Simulation not found</div>}
|
||||
{!loading && simulation && (
|
||||
<>
|
||||
<div className="flex flex-col gap-1 text-sm">
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Name</div>
|
||||
<div className="flex-[2]">{simulation.name}</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Name</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{simulation.name}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Scenario</div>
|
||||
<div className="flex-[2]">
|
||||
{scenario ? (
|
||||
<Link href={`/projects/${projectId}/test/scenarios/${scenario._id}`} className="text-blue-600 hover:underline">
|
||||
{scenario.name}
|
||||
</Link>
|
||||
) : (
|
||||
<div className="text-sm text-gray-500">No scenario selected</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Scenario</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{scenario?.name || 'Loading...'}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Profile</div>
|
||||
<div className="flex-[2]">
|
||||
{profile ? (
|
||||
<Link href={`/projects/${projectId}/test/profiles/${profile._id}`} className="text-blue-600 hover:underline">
|
||||
{profile.name}
|
||||
</Link>
|
||||
) : (
|
||||
<div className="text-sm text-gray-500">No profile selected</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Profile</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{profile?.name || 'None'}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Pass Criteria</div>
|
||||
<div className="flex-[2]">{simulation.passCriteria}</div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Pass Criteria</div>
|
||||
<div className="flex-[2] dark:text-neutral-200">{simulation.passCriteria}</div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Created</div>
|
||||
<div className="flex-[2]"><RelativeTime date={new Date(simulation.createdAt)} /></div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Created</div>
|
||||
<div className="flex-[2] dark:text-neutral-300"><RelativeTime date={new Date(simulation.createdAt)} /></div>
|
||||
</div>
|
||||
<div className="flex border-b py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600">Last Updated</div>
|
||||
<div className="flex-[2]"><RelativeTime date={new Date(simulation.lastUpdatedAt)} /></div>
|
||||
<div className="flex border-b border-gray-200 dark:border-neutral-800 py-2">
|
||||
<div className="flex-[1] font-medium text-gray-600 dark:text-neutral-400">Last Updated</div>
|
||||
<div className="flex-[2] dark:text-neutral-300"><RelativeTime date={new Date(simulation.lastUpdatedAt)} /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2 mt-4">
|
||||
|
|
@ -584,7 +568,7 @@ function SimulationList({
|
|||
}, [simulationList, error, projectId]);
|
||||
|
||||
return <div className="h-full flex flex-col gap-2">
|
||||
<h1 className="text-medium font-bold text-gray-800 pb-2 border-b border-gray-200">Simulations</h1>
|
||||
<h1 className="text-medium font-bold text-gray-800 dark:text-neutral-200 pb-2 border-b border-gray-200 dark:border-neutral-800">Simulations</h1>
|
||||
<Button
|
||||
size="sm"
|
||||
onPress={() => router.push(`/projects/${projectId}/test/simulations/new`)}
|
||||
|
|
@ -593,59 +577,59 @@ function SimulationList({
|
|||
>
|
||||
New Simulation
|
||||
</Button>
|
||||
{loading && <div className="flex gap-2 items-center">
|
||||
{loading && <div className="flex gap-2 items-center text-gray-600 dark:text-neutral-400">
|
||||
<Spinner size="sm" />
|
||||
Loading...
|
||||
</div>}
|
||||
{error && <div className="bg-red-100 p-2 rounded-md text-red-800 flex items-center gap-2 text-sm">
|
||||
{error && <div className="bg-red-100 dark:bg-red-900/20 p-2 rounded-md text-red-800 dark:text-red-400 flex items-center gap-2 text-sm">
|
||||
{error}
|
||||
<Button size="sm" color="danger" onPress={() => setError(null)}>Retry</Button>
|
||||
</div>}
|
||||
{!loading && !error && <>
|
||||
{simulationList.length === 0 && <div className="text-gray-600 text-center">No simulation found</div>}
|
||||
{simulationList.length === 0 && <div className="text-gray-600 dark:text-neutral-400 text-center">No simulations found</div>}
|
||||
{simulationList.length > 0 && <div className="flex flex-col w-full">
|
||||
{/* Header */}
|
||||
<div className="grid grid-cols-9 py-2 bg-gray-100 font-semibold text-sm">
|
||||
<div className="col-span-2 px-4">Name</div>
|
||||
<div className="col-span-3 px-4">Scenario</div>
|
||||
<div className="col-span-1 px-4">Profile</div>
|
||||
<div className="col-span-1 px-4">Criteria</div>
|
||||
<div className="col-span-1 px-4">Created</div>
|
||||
<div className="col-span-1 px-4">Updated</div>
|
||||
<div className="grid grid-cols-9 py-2 bg-gray-100 dark:bg-neutral-800 font-semibold text-sm">
|
||||
<div className="col-span-2 px-4 dark:text-neutral-300">Name</div>
|
||||
<div className="col-span-3 px-4 dark:text-neutral-300">Scenario</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Profile</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Criteria</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Created</div>
|
||||
<div className="col-span-1 px-4 dark:text-neutral-300">Updated</div>
|
||||
</div>
|
||||
|
||||
{/* Rows */}
|
||||
{simulationList.map((simulation) => (
|
||||
<div key={simulation._id} className="grid grid-cols-9 py-2 border-b hover:bg-gray-50 text-sm">
|
||||
<div key={simulation._id} className="grid grid-cols-9 py-2 border-b border-gray-200 dark:border-neutral-800 hover:bg-gray-50 dark:hover:bg-neutral-800 text-sm">
|
||||
<div className="col-span-2 px-4 truncate">
|
||||
<Link
|
||||
href={`/projects/${projectId}/test/simulations/${simulation._id}`}
|
||||
className="text-blue-600 hover:underline"
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline"
|
||||
>
|
||||
{simulation.name}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="col-span-3 px-4 truncate">
|
||||
<div className="col-span-3 px-4 truncate dark:text-neutral-300">
|
||||
{scenarioMap[simulation.scenarioId]?.name || (
|
||||
<span className="text-gray-500 font-mono text-xs">{simulation.scenarioId}</span>
|
||||
<span className="text-gray-500 dark:text-neutral-500 font-mono text-xs">{simulation.scenarioId}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-1 px-4 truncate">
|
||||
<div className="col-span-1 px-4 truncate dark:text-neutral-300">
|
||||
{simulation.profileId ? (
|
||||
profileMap[simulation.profileId]?.name || (
|
||||
<span className="text-gray-500 font-mono text-xs">{simulation.profileId}</span>
|
||||
<span className="text-gray-500 dark:text-neutral-500 font-mono text-xs">{simulation.profileId}</span>
|
||||
)
|
||||
) : (
|
||||
<span className="text-gray-500 font-mono text-xs">None</span>
|
||||
<span className="text-gray-500 dark:text-neutral-500 font-mono text-xs">None</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-1 px-4 truncate">
|
||||
<div className="col-span-1 px-4 truncate dark:text-neutral-300">
|
||||
{simulation.passCriteria}
|
||||
</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 truncate">
|
||||
<div className="col-span-1 px-4 text-gray-600 dark:text-neutral-400 truncate">
|
||||
<RelativeTime date={new Date(simulation.createdAt)} />
|
||||
</div>
|
||||
<div className="col-span-1 px-4 text-gray-600 truncate">
|
||||
<div className="col-span-1 px-4 text-gray-600 dark:text-neutral-400 truncate">
|
||||
<RelativeTime date={new Date(simulation.lastUpdatedAt)} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue