2025-12-22 02:36:48 +01:00
|
|
|
<script lang="ts">
|
|
|
|
|
import { Separator } from '@cio/ui/base/separator';
|
|
|
|
|
import * as Sidebar from '@cio/ui/base/sidebar';
|
|
|
|
|
import BellIcon from '@lucide/svelte/icons/bell';
|
|
|
|
|
import { Button } from '@cio/ui/base/button';
|
2026-03-18 23:39:12 +01:00
|
|
|
import { IconButton } from '@cio/ui/custom/icon-button';
|
2025-12-22 02:36:48 +01:00
|
|
|
import * as Popover from '@cio/ui/base/popover';
|
2026-03-18 23:39:12 +01:00
|
|
|
import { HoverableItem, PreviewIcon } from '@cio/ui/custom/moving-icons';
|
2025-12-22 02:36:48 +01:00
|
|
|
import RefreshCcwIcon from '@lucide/svelte/icons/refresh-ccw';
|
|
|
|
|
import * as Empty from '@cio/ui/base/empty';
|
2026-05-18 03:47:22 +01:00
|
|
|
import { page } from '$app/state';
|
2026-03-18 23:39:12 +01:00
|
|
|
import { currentOrg, currentOrgDomain } from '$lib/utils/store/org';
|
|
|
|
|
import { isStudentExperience } from '$lib/utils/store/app';
|
2026-04-27 11:40:38 +01:00
|
|
|
import SparklesIcon from '@lucide/svelte/icons/sparkles';
|
2025-12-22 02:36:48 +01:00
|
|
|
import { setupProgressApi } from '$features/setup/api/setup-progress.svelte';
|
2026-03-09 11:18:22 +01:00
|
|
|
import { courseApi } from '$features/course/api';
|
2026-03-18 23:39:12 +01:00
|
|
|
import { openCoursePreview } from '$features/course/utils/course-preview';
|
2026-05-18 03:47:22 +01:00
|
|
|
import { getActiveCourseNavKey } from '$features/course/utils/functions';
|
2026-04-27 11:40:38 +01:00
|
|
|
import { toggleAiAssistant } from '$features/ai-assistant/utils/store';
|
2026-03-18 23:39:12 +01:00
|
|
|
import { t } from '$lib/utils/functions/translations';
|
|
|
|
|
import CoursePublishBadge from './course-publish-badge.svelte';
|
2026-05-09 06:05:03 +01:00
|
|
|
import CoursePublicBadge from './course-public-badge.svelte';
|
2025-12-22 02:36:48 +01:00
|
|
|
|
|
|
|
|
const siteName = $derived($currentOrg.siteName);
|
2026-03-18 23:39:12 +01:00
|
|
|
const showCoursePublishBadge = $derived(!$isStudentExperience);
|
2026-05-09 06:05:03 +01:00
|
|
|
const isPublicCourse = $derived(courseApi.course?.type === 'PUBLIC');
|
2026-05-18 03:47:22 +01:00
|
|
|
const activeNavKey = $derived(getActiveCourseNavKey(page.url.pathname, courseApi.course?.id ?? ''));
|
2025-12-22 02:36:48 +01:00
|
|
|
|
|
|
|
|
$effect(() => {
|
|
|
|
|
if (!siteName) return;
|
|
|
|
|
|
|
|
|
|
setupProgressApi.fetchSetupProgress(siteName);
|
|
|
|
|
});
|
2026-03-18 23:39:12 +01:00
|
|
|
|
|
|
|
|
function handlePreview() {
|
|
|
|
|
openCoursePreview({
|
|
|
|
|
courseId: courseApi.course?.id ?? '',
|
|
|
|
|
courseSlug: courseApi.course?.slug,
|
|
|
|
|
currentOrgDomain: $currentOrgDomain
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-12-22 02:36:48 +01:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<header
|
2026-05-18 03:47:22 +01:00
|
|
|
class="border-border ui:bg-background sticky top-0 z-100 flex h-12 w-full shrink-0 items-center gap-2 border-b backdrop-blur transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-8"
|
2025-12-22 02:36:48 +01:00
|
|
|
>
|
|
|
|
|
<div class="flex w-full items-center gap-2 px-4">
|
|
|
|
|
<Sidebar.Trigger />
|
|
|
|
|
|
|
|
|
|
<div class="h-4 w-2">
|
|
|
|
|
<Separator orientation="vertical" />
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-05-09 06:05:03 +01:00
|
|
|
<div class="flex w-[60%] min-w-0 flex-1 flex-col justify-center gap-0.5">
|
|
|
|
|
<div class="flex min-w-0 items-center gap-2">
|
|
|
|
|
<p class="max-w-xs truncate text-sm font-medium">
|
2026-05-18 03:47:22 +01:00
|
|
|
{activeNavKey ? $t(activeNavKey) : ''}
|
2026-05-09 06:05:03 +01:00
|
|
|
</p>
|
2026-03-18 23:39:12 +01:00
|
|
|
|
2026-05-09 06:05:03 +01:00
|
|
|
{#if isPublicCourse}
|
|
|
|
|
<CoursePublicBadge class="shrink-0" />
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
{#if showCoursePublishBadge}
|
|
|
|
|
<CoursePublishBadge isPublished={courseApi.course?.isPublished ?? false} />
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
2026-03-18 23:39:12 +01:00
|
|
|
</div>
|
2025-12-22 02:36:48 +01:00
|
|
|
|
|
|
|
|
<span class="grow"></span>
|
|
|
|
|
|
2026-05-09 06:05:03 +01:00
|
|
|
<Button variant="outline" size="sm" onclick={toggleAiAssistant}>
|
|
|
|
|
<SparklesIcon size={14} />
|
|
|
|
|
{$t('course.navItems.nav_ai_assistant')}
|
|
|
|
|
</Button>
|
2026-04-27 11:40:38 +01:00
|
|
|
|
2025-12-22 02:36:48 +01:00
|
|
|
<Popover.Root>
|
|
|
|
|
<Popover.Trigger>
|
|
|
|
|
<Button variant="outline" size="icon">
|
|
|
|
|
<BellIcon class="custom rounded-full" />
|
|
|
|
|
</Button>
|
|
|
|
|
</Popover.Trigger>
|
|
|
|
|
<Popover.Content>
|
|
|
|
|
<Empty.Root class="ui:from-muted/50 ui:to-background ui:h-full ui:bg-gradient-to-b ui:from-30%">
|
|
|
|
|
<Empty.Header>
|
|
|
|
|
<Empty.Media variant="icon">
|
|
|
|
|
<BellIcon />
|
|
|
|
|
</Empty.Media>
|
|
|
|
|
<Empty.Title>No Notifications</Empty.Title>
|
|
|
|
|
<Empty.Description>You're all caught up. New notifications will appear here.</Empty.Description>
|
|
|
|
|
</Empty.Header>
|
|
|
|
|
<Empty.Content>
|
|
|
|
|
<Button variant="outline" size="sm">
|
|
|
|
|
<RefreshCcwIcon />
|
2026-03-18 23:39:12 +01:00
|
|
|
{$t('common.refresh')}
|
2025-12-22 02:36:48 +01:00
|
|
|
</Button>
|
|
|
|
|
</Empty.Content>
|
|
|
|
|
</Empty.Root>
|
|
|
|
|
</Popover.Content>
|
|
|
|
|
</Popover.Root>
|
2026-03-18 23:39:12 +01:00
|
|
|
|
|
|
|
|
<HoverableItem>
|
|
|
|
|
{#snippet children(isHovered)}
|
|
|
|
|
<IconButton
|
|
|
|
|
onclick={handlePreview}
|
|
|
|
|
disabled={!courseApi.course?.id}
|
|
|
|
|
tooltip={$t('course.header.preview')}
|
|
|
|
|
aria-label={$t('course.header.preview')}
|
|
|
|
|
>
|
|
|
|
|
<PreviewIcon {isHovered} size={16} />
|
|
|
|
|
</IconButton>
|
|
|
|
|
{/snippet}
|
|
|
|
|
</HoverableItem>
|
2025-12-22 02:36:48 +01:00
|
|
|
</div>
|
|
|
|
|
</header>
|