Enhance audience management features with new components and API integrations

- Added `AssignCoursesModal`, `AudienceMemberRow`, `AudienceTable`, and related components for improved audience management UI.
- Implemented audience invite actions including resend and revoke functionality.
- Updated audience API to support importing members and assigning courses.
- Refactored audience data handling to include status and invite management.
- Improved overall user experience with pagination and selection features in the audience table.
This commit is contained in:
Rotimi Best
2026-03-22 18:42:23 +01:00
parent e9c4082f89
commit 3919ff6c2f
157 changed files with 13183 additions and 872 deletions
@@ -1,12 +1,9 @@
<script lang="ts">
import { getExerciseQuestionLabel, type ExerciseQuestionRendererProps } from '@cio/question-types';
import OptionImage from '../option-image.svelte';
import type { ExerciseQuestionRendererProps } from '@cio/question-types';
import { getOptionImageUrl, hasOptionImages } from '../option-image-utils';
import { cn } from '../../../../tools';
import McqPreviewOptionRow from '../shared/mcq-preview-option-row.svelte';
let { question, labels }: ExerciseQuestionRendererProps = $props();
const label = (key: Parameters<typeof getExerciseQuestionLabel>[1], fallback = '') =>
getExerciseQuestionLabel(labels, key, fallback);
const optionsHaveImages = $derived(hasOptionImages(question.options));
</script>
@@ -14,22 +11,7 @@
<div class="ui:space-y-2">
<ul class={optionsHaveImages ? 'ui:grid ui:grid-cols-2 ui:gap-3' : 'ui:space-y-1'}>
{#each question.options ?? [] as option, index}
{@const optionImageUrl = getOptionImageUrl(option)}
<li class={cn(optionsHaveImages && 'ui:space-y-2 ui:rounded-md ui:p-2', 'ui:text-sm')}>
<OptionImage
src={optionImageUrl}
alt={label('question.edit.image_alt')}
variant="preview"
hasAnyImageInOptions={optionsHaveImages}
/>
<div>
{option.label || option.value || [label('common.option_prefix'), String(index + 1)].filter(Boolean).join(' ')}
{#if option.isCorrect}
<span class="ui:ml-2 ui:text-xs ui:text-green-600">{label('common.correct_badge')}</span>
{/if}
</div>
</li>
<McqPreviewOptionRow {option} {index} optionImageUrl={getOptionImageUrl(option)} {optionsHaveImages} {labels} />
{/each}
</ul>
</div>