feat: multi language support (#254)
* feat: multitranslational support * - completion of settings page - completion of sidebar * sidebar rerendering bug fix * completion of the lesson navigation & materials page * completion of the course navigation * completion of requested languages * - Implementation of Language Picker - Rename Bug Fixes * checkpoint save * - addition of the language picker to the onboarding. - addition of the language switcher for the lesson notes. * merge completion * initialization of the new branch * add transition.svelte file * lesson note bug fix * feat: add translation migration * completion of translation * fix height issue of dropdown * refactoring * fix: improve code with LOCALE from db * finally get it fully functional * connect with AI * backward compatibility for lesson note * preserve old content, when generating AI content * undo translations in upgrade modal * fix duplicate key issue from codacy trigger --------- Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
co-authored by
Rotimi Best
parent
ff7d2cee35
commit
d75e2f258e
@@ -4,6 +4,7 @@
|
||||
import Modal from '$lib/components/Modal/index.svelte';
|
||||
import { deleteModal, quizesStore } from '$lib/utils/store/org';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
export let onDelete = () => {};
|
||||
|
||||
@@ -34,24 +35,26 @@
|
||||
onClose={closeModal}
|
||||
bind:open={$deleteModal.open}
|
||||
width="w-2/5"
|
||||
modalHeading={$deleteModal.isQuestion ? 'Delete Question' : 'Delete Quiz'}
|
||||
modalHeading={$deleteModal.isQuestion
|
||||
? $t('components.quiz.question_delete')
|
||||
: $t('components.quiz.quiz_delete')}
|
||||
size="sm"
|
||||
>
|
||||
<div class="w-full flex flex-col items-center my-10">
|
||||
<h1 class="dark:text-white text-lg text-center">
|
||||
{#if $deleteModal.isQuestion}
|
||||
Are you sure you want to delete this question?
|
||||
{$t('components.quiz.delete_question')}
|
||||
{:else}
|
||||
Are you sure you want to delete this quiz?
|
||||
{$t('components.quiz.delete_quiz')}
|
||||
{/if}
|
||||
You will lose your content and this action can’t be undone.
|
||||
{$t('components.quiz.lose_content')}
|
||||
</h1>
|
||||
|
||||
<div class="mt-5">
|
||||
<PrimaryButton
|
||||
className="px-6 py-3"
|
||||
variant={VARIANTS.CONTAINED}
|
||||
label="Delete"
|
||||
label={$t('components.quiz.delete')}
|
||||
onClick={() => {
|
||||
if ($deleteModal.isQuestion) {
|
||||
onDelete();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { currentOrg, createQuizModal, currentOrgPath, quizesStore } from '$lib/utils/store/org';
|
||||
import { createQuizValidation } from '$lib/utils/functions/validator';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
let open = false;
|
||||
let errors = {
|
||||
@@ -97,21 +98,23 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Quizzes - ClassroomIO</title>
|
||||
<title>{$t('components.quiz.title')} - ClassroomIO</title>
|
||||
</svelte:head>
|
||||
|
||||
<Modal
|
||||
onClose={handleClose}
|
||||
bind:open
|
||||
width="w-4/5 md:w-2/5"
|
||||
modalHeading="{$createQuizModal.openEdit ? 'Update' : 'Create'} a Quiz"
|
||||
modalHeading="{$createQuizModal.openEdit
|
||||
? $t('components.quiz.update')
|
||||
: $t('components.quiz.create')} {$t('components.quiz.a_quiz')}"
|
||||
>
|
||||
<form on:submit|preventDefault={createQuiz}>
|
||||
<TextField
|
||||
label="Quiz Title"
|
||||
label={$t('components.quiz.quiz_title')}
|
||||
bind:value={$createQuizModal.title}
|
||||
autofocus={true}
|
||||
placeholder="Your quiz title"
|
||||
placeholder={$t('components.quiz.placehoolder')}
|
||||
className="mb-4"
|
||||
isRequired={true}
|
||||
errorMessage={errors.title}
|
||||
@@ -121,7 +124,9 @@
|
||||
<div class="mt-5 flex items-center justify-end">
|
||||
<PrimaryButton
|
||||
className="px-6 py-3"
|
||||
label={$createQuizModal.openEdit ? 'Save Changes' : 'Continue'}
|
||||
label={$createQuizModal.openEdit
|
||||
? $t('components.quiz.save')
|
||||
: $t('components.quiz.continue')}
|
||||
type="submit"
|
||||
isDisabled={isLoading}
|
||||
{isLoading}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import { onRename, onDelete } from '$lib/utils/services/org/quiz';
|
||||
import { themeImages } from '$lib/utils/constants/quiz';
|
||||
import { calDateDiff } from '$lib/utils/functions/date';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
export let quiz;
|
||||
export let totalQuestions;
|
||||
@@ -28,7 +29,7 @@
|
||||
// onClick: onReport(quiz),
|
||||
// },
|
||||
{
|
||||
label: 'Rename',
|
||||
label: $t('components.quiz.rename'),
|
||||
onClick() {
|
||||
onRename(quiz);
|
||||
}
|
||||
@@ -40,7 +41,7 @@
|
||||
// },
|
||||
// },
|
||||
{
|
||||
label: 'Delete',
|
||||
label: $t('components.quiz.delete'),
|
||||
onClick() {
|
||||
onDelete(quiz);
|
||||
}
|
||||
@@ -77,13 +78,13 @@
|
||||
<div class="flex md:flex-row flex-col justify-between">
|
||||
<div>
|
||||
<p class="mb-2">{pluralize('question', totalQuestions, true)}</p>
|
||||
<p class="mb-2 md:mb-0">Updated {calDateDiff(quiz.updated_at)}</p>
|
||||
<p class="mb-2 md:mb-0">{$t('components.quiz.updated')} {calDateDiff(quiz.updated_at)}</p>
|
||||
</div>
|
||||
|
||||
<PrimaryButton
|
||||
className="px-6 py-3"
|
||||
variant={VARIANTS.OUTLINED}
|
||||
label="Start Quiz"
|
||||
label={$t('components.quiz.start')}
|
||||
onClick={startQuiz}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { optionImage } from '$lib/utils/constants/quiz';
|
||||
import TextField from '$lib/components/Form/TextField.svelte';
|
||||
import IconButton from '$lib/components/IconButton/index.svelte';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
export let currentQuestion = {
|
||||
label: ''
|
||||
@@ -17,10 +18,10 @@
|
||||
<h1 class="text-white mb-5 font-bold">{currentQuestion.label}</h1>
|
||||
{:else}
|
||||
<TextField
|
||||
placeholder="Start typing your question"
|
||||
placeholder={$t('components.quiz.start_typing')}
|
||||
bind:value={currentQuestion.label}
|
||||
className="w-full my-4"
|
||||
errorMessage={currentError.isLabelEmpty && 'This field is required'}
|
||||
errorMessage={currentError.isLabelEmpty && $t('components.quiz.required_field')}
|
||||
isRequired={true}
|
||||
bgColor="bg-white"
|
||||
/>
|
||||
@@ -37,11 +38,12 @@
|
||||
{:else}
|
||||
<TextField
|
||||
bind:value={option.label}
|
||||
placeholder="Type answer"
|
||||
placeholder={$t('components.quiz.type_answer')}
|
||||
bgColor="bg-white"
|
||||
className="mt-3"
|
||||
isDisabled={currentQuestion.type === 'boolean'}
|
||||
errorMessage={optionHasError(option.id, currentError.options) && 'Please enter a label'}
|
||||
errorMessage={optionHasError(option.id, currentError.options) &&
|
||||
$t('components.quiz.label')}
|
||||
/>
|
||||
<div class="flex justify-end absolute top-2 right-2">
|
||||
<IconButton
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { snackbar } from '$lib/components/Snackbar/store';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { currentOrg, quizesStore } from '$lib/utils/store/org';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
let isLoading = false;
|
||||
|
||||
@@ -43,9 +44,9 @@
|
||||
{:else}
|
||||
<Box>
|
||||
<CoursesEmptyIcon />
|
||||
<h3 class="dark:text-white text-2xl my-5">No Quiz Created</h3>
|
||||
<h3 class="dark:text-white text-2xl my-5">{$t('components.quiz.no_quizz')}</h3>
|
||||
<p class="dark:text-white w-1/3 text-center">
|
||||
Create interactive quizzes with scoreboard for your students.
|
||||
{$t('components.quiz.interactive')}
|
||||
</p>
|
||||
</Box>
|
||||
{/each}
|
||||
|
||||
Reference in New Issue
Block a user