Add dark mode support for testing pages

This commit is contained in:
akhisud3195 2025-03-11 10:06:52 +05:30 committed by ramnique
parent d877486978
commit 9f2854a22c
5 changed files with 141 additions and 161 deletions

View file

@ -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} />}

View file

@ -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>

View file

@ -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`;
}
}

View file

@ -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>

View file

@ -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>