feat: add AI quiz generation frontend modal and sidebar button
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2026 LobotomyLabs
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
-->
|
||||
<script lang="ts">
|
||||
import BrownButton from '$lib/components/buttons/brown.svelte';
|
||||
let { data = $bindable() } = $props();
|
||||
let open = $state(false);
|
||||
let topic = $state('');
|
||||
let loading = $state(false);
|
||||
|
||||
async function generate() {
|
||||
if (!topic) return;
|
||||
loading = true;
|
||||
try {
|
||||
const res = await fetch('/api/v1/ai/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ topic, num_questions: 5 })
|
||||
});
|
||||
if (res.ok) {
|
||||
const quiz = await res.json();
|
||||
data.title = quiz.title;
|
||||
data.description = quiz.description;
|
||||
data.questions = quiz.questions;
|
||||
open = false;
|
||||
} else {
|
||||
alert('Generation failed');
|
||||
}
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="my-2 px-6">
|
||||
<BrownButton onclick={() => (open = true)}>✨ Generate with AI</BrownButton>
|
||||
</div>
|
||||
|
||||
{#if open}
|
||||
<div class="fixed z-50 inset-0 flex items-center justify-center bg-black/50">
|
||||
<div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-xl w-96">
|
||||
<h3 class="text-lg font-bold mb-4 dark:text-white">Generate Quiz with AI</h3>
|
||||
<input type="text" bind:value={topic} placeholder="Enter topic (e.g. World History)" class="w-full p-2 border rounded mb-4 dark:bg-gray-700 dark:text-white" />
|
||||
<div class="flex justify-end gap-2">
|
||||
<button class="px-4 py-2 bg-gray-300 rounded" onclick={() => (open = false)}>Cancel</button>
|
||||
<button class="px-4 py-2 bg-indigo-600 text-white rounded" onclick={generate} disabled={loading}>{loading ? 'Generating...' : 'Generate'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -13,6 +13,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
import { getLocalization } from '$lib/i18n';
|
||||
import AddNewQuestionPopup from '$lib/editor/AddNewQuestionPopup.svelte';
|
||||
import BrownButton from '$lib/components/buttons/brown.svelte';
|
||||
import AIModal from '$lib/editor/AIModal.svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
const { t } = getLocalization();
|
||||
@@ -74,7 +75,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
</script>
|
||||
|
||||
<div class="h-screen relative">
|
||||
<div class="h-10 flex justify-center w-full p-1 absolute z-20">
|
||||
<div class="h-10 flex justify-center w-full p-1 absolute z-20 gap-2">
|
||||
<div>
|
||||
<BrownButton onclick={() => (reorder_mode = !reorder_mode)}
|
||||
>{#if reorder_mode}{$t('editor.disable_reorder')}{:else}{$t(
|
||||
@@ -82,6 +83,9 @@ SPDX-License-Identifier: MPL-2.0
|
||||
)}{/if}</BrownButton
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<AIModal bind:data />
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-r-2 pt-6 px-6 overflow-scroll h-full">
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user