feat: Add admin experiment management pages and components

- Implemented ExperimentPage for viewing and editing individual experiments.
- Created ExperimentsAdminPage for managing all experiments with a list and a modal for creating new experiments.
- Developed AnnotatePage for annotating experiments with different views based on annotation tools.
- Added CreateExperimentModal for creating new experiments with dataset selection.
- Introduced DeleteExperimentButton for confirming and executing experiment deletions.
- Built EditableExperimentHeader for editing experiment details.
- Created ExperimentsList component to display a list of experiments with links to their details.
This commit is contained in:
averel10
2026-03-20 07:26:02 +01:00
parent 4b35e2392e
commit dd5d99ec24
16 changed files with 1593 additions and 60 deletions

View File

@@ -0,0 +1,74 @@
import { redirect, notFound } from 'next/navigation';
import { headers } from 'next/headers';
import Link from 'next/link';
import { auth } from '@/lib/auth';
import { getAnnotationEntries } from '@/app/actions/annotations';
import SingleChoiceView from '@/components/AnnotationViews/SingleChoiceView';
import { getExperimentById } from '@/app/actions/experiment';
interface Props {
params: Promise<{ experimentId: string}>;
}
export default async function AnnotatePage({ params }: Props) {
const session = await auth.api.getSession({ headers: await headers() });
if (!session) redirect('/user/sign-in');
const { experimentId: experimentIdStr } = await params;
const experimentId = parseInt(experimentIdStr, 10);
const prototype = await getExperimentById(experimentId).then(exp => exp?.annotationTool || null);
if (isNaN(experimentId)) {
return (
<div className="max-w-xl mx-auto py-16 text-center">
<p className="text-gray-600">Ungültige Experiment-ID.</p>
<Link href="/" className="text-blue-600 hover:underline mt-4 inline-block">
Startseite
</Link>
</div>
);
}
const entries = await getAnnotationEntries(experimentId);
if (entries.length === 0) {
return (
<div className="max-w-xl mx-auto py-20 text-center">
<div className="text-5xl mb-4"></div>
<h1 className="text-2xl font-bold text-green-600 mb-3">
Alle Samples bewertet!
</h1>
<p className="text-gray-600 mb-8">
Sie haben alle Samples in diesem Experiment bereits bewertet. Danke für Ihre Mitarbeit!
</p>
<Link
href="/"
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg transition-colors"
>
Zurück zur Startseite
</Link>
</div>
);
}
// Render based on prototype type
const renderAnnotationView = () => {
switch (prototype) {
case 'single-choice':
return <SingleChoiceView entries={entries} experimentId={experimentId} />;
// Add more prototypes here as needed
default:
return (
<div className="max-w-xl mx-auto py-16 text-center">
<p className="text-gray-600">Unbekannter Annotation-Typ: {prototype}</p>
<Link href="/" className="text-blue-600 hover:underline mt-4 inline-block">
Startseite
</Link>
</div>
);
}
};
return renderAnnotationView();
}