Files
cog-socket/src/routes/experiment/[id]/+page.svelte
2025-07-16 16:46:27 +02:00

146 lines
5.3 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card';
import { goto } from '$app/navigation';
import { get } from 'svelte/store';
import FileManager from './FileManager.svelte';
import ExperimentSessions from './ExperimentSessions.svelte';
let experimentId = '';
let experiment: any = null;
let name = '';
let description = '';
let error = '';
let success = '';
let copied = false;
let origin = '';
let activeTab = 'info';
$: publicLink = experiment
? `${origin}/public/${experiment.multiplayer ? 'multiplayer/run' : 'run'}/${experiment.id}`
: '';
function copyLink() {
navigator.clipboard.writeText(publicLink);
copied = true;
setTimeout(() => (copied = false), 2000);
}
onMount(async () => {
origin = window.location.origin;
const params = get(page).params;
experimentId = params.id;
const res = await fetch(`/api/experiment?id=${experimentId}`);
if (res.ok) {
const data = await res.json();
experiment = data.experiment;
console.log(experiment)
name = experiment.name;
description = experiment.description;
} else {
error = 'Failed to load experiment.';
}
});
async function handleSave() {
error = '';
success = '';
const res = await fetch(`/api/experiment?id=${experimentId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, description })
});
if (res.ok) {
success = 'Experiment updated!';
} else {
error = 'Failed to update experiment.';
}
}
</script>
{#if experiment}
<div class="flex flex-col min-h-screen bg-background py-8">
<div class="w-full max-w-xl mx-auto mb-8">
<div class="flex border-b mb-4">
<button class="px-4 py-2 -mb-px border-b-2 font-medium focus:outline-none transition-colors duration-200" class:!border-primary={activeTab === 'info'} class:border-transparent={activeTab !== 'info'} on:click={() => activeTab = 'info'}>Info</button>
<button class="px-4 py-2 -mb-px border-b-2 font-medium focus:outline-none transition-colors duration-200" class:!border-primary={activeTab === 'files'} class:border-transparent={activeTab !== 'files'} on:click={() => activeTab = 'files'}>Files</button>
<button class="px-4 py-2 -mb-px border-b-2 font-medium focus:outline-none transition-colors duration-200" class:!border-primary={activeTab === 'sessions'} class:border-transparent={activeTab !== 'sessions'} on:click={() => activeTab = 'sessions'}>Sessions</button>
</div>
{#if activeTab === 'info'}
<Card class="w-full">
<CardHeader>
<CardTitle>Experiment Details</CardTitle>
</CardHeader>
<CardContent>
<div class="mb-4">
<Label>ID</Label>
<div class="text-sm text-muted-foreground mb-2">{experiment.id}</div>
</div>
<div class="mb-4">
<Label>Type</Label>
<div class="text-sm text-muted-foreground mb-2">{experiment.type}</div>
</div>
<div class="mb-4">
<Label>Multiplayer</Label>
<div class="text-sm text-muted-foreground mb-2">{experiment.multiplayer ? 'Yes' : 'No'}</div>
</div>
<form on:submit|preventDefault={handleSave} class="space-y-4">
<div>
<Label for="name">Name</Label>
<Input id="name" type="text" bind:value={name} required />
</div>
<div>
<Label for="description">Description</Label>
<Input id="description" type="text" bind:value={description} />
</div>
<div>
<Label>Created At</Label>
<div class="text-sm text-muted-foreground mb-2">{new Date(experiment.createdAt).toLocaleString()}</div>
</div>
{#if error}
<div class="text-red-500 text-sm">{error}</div>
{/if}
{#if success}
<div class="text-green-600 text-sm">{success}</div>
{/if}
<Button type="submit">Save Changes</Button>
</form>
<div class="mt-8">
<Label>Public Link</Label>
<div class="flex items-center space-x-2 mt-2">
<Input id="public-link" type="text" readonly value={publicLink} />
<Button on:click={copyLink}>Copy</Button>
</div>
{#if copied}
<p class="text-green-600 text-sm mt-2">Copied to clipboard!</p>
{/if}
</div>
</CardContent>
</Card>
{:else if activeTab === 'files'}
<FileManager {experimentId} />
{:else if activeTab === 'sessions'}
<ExperimentSessions {experimentId} />
{/if}
</div>
</div>
{:else if error}
<div class="flex justify-center items-center min-h-screen bg-background">
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Error</CardTitle>
</CardHeader>
<CardContent>
<div class="text-red-500">{error}</div>
</CardContent>
</Card>
</div>
{:else}
<div class="flex justify-center items-center min-h-screen bg-background">
<div>Loading...</div>
</div>
{/if}