jedmund-svelte/src/routes/labs/[slug]/+page.svelte

113 lines
2.5 KiB
Svelte

<script lang="ts">
import Page from '$components/Page.svelte'
import BackButton from '$components/BackButton.svelte'
import ProjectPasswordProtection from '$lib/components/ProjectPasswordProtection.svelte'
import ProjectHeaderContent from '$lib/components/ProjectHeaderContent.svelte'
import ProjectContent from '$lib/components/ProjectContent.svelte'
import type { PageData } from './$types'
import type { Project } from '$lib/types/project'
let { data } = $props<{ data: PageData }>()
const project = $derived(data.project as Project | null)
const error = $derived(data.error as string | undefined)
</script>
{#if error}
<div class="error-wrapper">
<Page>
<div class="error-content">
<p>{error}</p>
<BackButton href="/labs" label="Back to Labs" />
</div>
</Page>
</div>
{:else if !project}
<Page>
<div class="loading">Loading project...</div>
</Page>
{:else if project.status === 'list-only'}
<Page>
{#snippet header()}
<div class="error-header">
<h1>Project Not Available</h1>
</div>
{/snippet}
<div class="error-content">
<p>This project is not yet available for viewing. Please check back later.</p>
<BackButton href="/labs" label="Back to Labs" />
</div>
</Page>
{:else if project.status === 'password-protected' || project.status === 'published'}
<div class="project-wrapper">
<Page>
{#snippet header()}
<div class="project-header">
<ProjectHeaderContent {project} />
</div>
{/snippet}
{#if project.status === 'password-protected'}
<ProjectPasswordProtection
projectSlug={project.slug}
correctPassword={project.password || ''}
projectType="labs"
>
{#snippet children()}
<ProjectContent {project} />
{/snippet}
</ProjectPasswordProtection>
{:else}
<ProjectContent {project} />
{/if}
</Page>
</div>
{/if}
<style lang="scss">
/* Error and Loading States */
.error-wrapper {
width: 100%;
max-width: 700px;
margin: 0 auto;
padding: 0 $unit-2x;
box-sizing: border-box;
}
.error-header h1 {
color: $red-60;
font-size: 2rem;
margin: 0;
}
.error-content {
text-align: center;
p {
color: $grey-40;
margin-bottom: $unit-2x;
}
}
.loading {
text-align: center;
color: $grey-40;
padding: $unit-4x;
}
/* Project Wrapper */
.project-wrapper {
width: 100%;
max-width: 700px;
margin: 0 auto;
box-sizing: border-box;
@include breakpoint('phone') {
padding: 0 $unit-2x;
}
}
/* Project Header */
.project-header {
width: 100%;
}
</style>