146 lines
5.3 KiB
Svelte
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} |