feat: widgets and ai chat

This commit is contained in:
Rotimi Best
2026-04-27 11:40:38 +01:00
parent ae1801f85f
commit 5717dd8004
391 changed files with 28177 additions and 22467 deletions
@@ -8,11 +8,40 @@
import { currentOrg } from '$lib/utils/store/org';
import { classroomio } from '$lib/utils/services/api';
import * as Page from '@cio/ui/base/page';
import { coursesApi } from '$features/course/api';
import type { PendingOrgInvite } from '$features/lms/utils/types';
let pendingInvite = $state<PendingOrgInvite | null>(null);
let showInviteModal = $state(false);
const todayLabel = new Intl.DateTimeFormat('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric'
}).format(new Date());
const firstName = $derived($profile.fullname?.trim().split(/\s+/)[0] || $t('dashboard.learner'));
let totalCompleted = $derived(
coursesApi.enrolledCourses.reduce((acc, course) => {
const exercisesCompleted =
'exercisesCompleted' in course && typeof course.exercisesCompleted === 'number' ? course.exercisesCompleted : 0;
return acc + (course.progressRate || 0) + exercisesCompleted;
}, 0)
);
let totalLessons = $derived(
coursesApi.enrolledCourses.reduce((acc, course) => {
const exercises =
'exerciseCount' in course && typeof course.exerciseCount === 'number' ? course.exerciseCount : 0;
return acc + (course.lessonCount || 0) + exercises;
}, 0)
);
let progressPercentage = $derived(totalLessons > 0 ? Math.round((totalCompleted / totalLessons) * 100) : 0);
onMount(async () => {
if (!$profile.id || !$currentOrg.id) return;
@@ -38,15 +67,24 @@
<title>Student Dashboard - ClassroomIO</title>
</svelte:head>
<Page.Root class="w-full">
<Page.Root class="mx-auto w-full max-w-4xl">
<Page.Header>
<Page.HeaderContent>
<Page.Subtitle>{todayLabel}</Page.Subtitle>
<Page.Title>
{$t(getGreeting())}
{$profile.fullname}!
{$t(getGreeting())},
<span class="ui:text-primary italic">{firstName}.</span>
</Page.Title>
<Page.Subtitle>
{#if totalLessons > 0}
{$t('dashboard.lms_today_progress', { progress: progressPercentage })}
{:else}
{$t('dashboard.lms_today_empty')}
{/if}
</Page.Subtitle>
</Page.HeaderContent>
</Page.Header>
<Page.Body>
{#snippet child()}
<DashboardPage />
@@ -1,6 +1,5 @@
<script lang="ts">
import { ProfilePage } from '$features/settings/pages';
import { VisitOrgSiteButton } from '$features/ui';
import { t } from '$lib/utils/functions/translations';
import { Button } from '@cio/ui/base/button';
import * as Page from '@cio/ui/base/page';
@@ -30,8 +29,6 @@
<Button variant="secondary" loading={isLoading} onclick={handleUpdate}>
{$t('settings.profile.update_profile')}
</Button>
<VisitOrgSiteButton />
</Page.Action>
</Page.Header>
<Page.Body>