feat: setup drizzle (#594)
* chore: migration to SvelteKit 2 * stage 1: migrate to svelte 5 and fix rerendering issues * stage 2: fix more $: reactivity across dashboard * fix merge conflicts * chore: migrate code in main to svelte 5 * chore: update preventDefault * chore: simplify tsconfig and remove unused mobileMenuRef in MobileMenu.svelte * chore: enforce .ts across dashboard * rename from classroomio-com to website * stage-3: Replace carbon icon svelte with lucide icon * update lock file * chore: finish icon replacement * fix: settings and setup page multiple rerender * stage 3: More icon and rerendering fixes * feat: setup drizzle and better auth * fix: onboarding validation error showing translation key #586 (#593) * fix: onboarding validation error showing translation key #586 * fix: remove debug log for profile update errors * chore: add a clean command * fix: remove message from email verification response
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from '$lib/utils/functions/svelte';
|
||||
|
||||
import CodeSnippet from '$lib/components/CodeSnippet/index.svelte';
|
||||
import Checkbox from '$lib/components/Form/Checkbox.svelte';
|
||||
import HtmlRender from '$lib/components/HTMLRender/HTMLRender.svelte';
|
||||
@@ -9,31 +11,57 @@
|
||||
import QuestionTitle from '../QuestionTitle.svelte';
|
||||
import ReasonBox from '../ReasonBox.svelte';
|
||||
|
||||
export let title = '';
|
||||
export let index = 1;
|
||||
export let code;
|
||||
export let name = '';
|
||||
export let options: { value: string; label: string }[] = [];
|
||||
export let onSubmit = (a: string, b: string[]) => {};
|
||||
export let onPrevious = () => {};
|
||||
export let defaultValue: string[] = [];
|
||||
export let disablePreviousButton = false;
|
||||
export let isLast = false;
|
||||
export let disabled = false;
|
||||
export let isPreview = false;
|
||||
export let nextButtonProps = {
|
||||
isDisabled: false,
|
||||
isActive: false
|
||||
};
|
||||
export let grade: number | undefined;
|
||||
export let gradeMax = 0;
|
||||
export let disableGrading = false;
|
||||
export let isGradeWithAI = false;
|
||||
export let reason;
|
||||
export let isLoading = false;
|
||||
export let hideGrading = false;
|
||||
interface Props {
|
||||
key: string | number;
|
||||
title?: string;
|
||||
index?: number | string;
|
||||
code: any;
|
||||
name?: string;
|
||||
options?: { value: string; label: string }[];
|
||||
onSubmit?: any;
|
||||
onPrevious?: any;
|
||||
defaultValue?: string[];
|
||||
disablePreviousButton?: boolean;
|
||||
isLast?: boolean;
|
||||
disabled?: boolean;
|
||||
isPreview?: boolean;
|
||||
nextButtonProps?: any;
|
||||
grade?: number;
|
||||
gradeMax?: number;
|
||||
disableGrading?: boolean;
|
||||
isGradeWithAI?: boolean;
|
||||
reason?: string;
|
||||
isLoading?: boolean;
|
||||
hideGrading?: boolean;
|
||||
}
|
||||
|
||||
let gradeWithAI = false;
|
||||
let {
|
||||
title = '',
|
||||
index = 1,
|
||||
code,
|
||||
name = '',
|
||||
options = [],
|
||||
onSubmit = (_a: string, _b: string[]) => {},
|
||||
onPrevious = () => {},
|
||||
defaultValue = [],
|
||||
disablePreviousButton = false,
|
||||
isLast = false,
|
||||
disabled = false,
|
||||
isPreview = false,
|
||||
nextButtonProps = {
|
||||
isDisabled: false,
|
||||
isActive: false
|
||||
},
|
||||
grade = $bindable(),
|
||||
gradeMax = 0,
|
||||
disableGrading = false,
|
||||
isGradeWithAI = false,
|
||||
reason,
|
||||
isLoading = false,
|
||||
hideGrading = false
|
||||
}: Props = $props();
|
||||
|
||||
let gradeWithAI = $derived(isGradeWithAI);
|
||||
|
||||
function getVal(form, name) {
|
||||
let values: string[] = [];
|
||||
@@ -79,16 +107,12 @@
|
||||
gradeWithAI = false;
|
||||
grade = 0;
|
||||
}
|
||||
|
||||
$: gradeWithAI = isGradeWithAI;
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={handleFormSubmit}>
|
||||
<form onsubmit={preventDefault(handleFormSubmit)}>
|
||||
<div class="flex items-center justify-between">
|
||||
<HtmlRender className="mt-4 {typeof grade === 'number' && 'w-4/5'}" disableMaxWidth>
|
||||
<svelte:fragment slot="content">
|
||||
<QuestionTitle {index} {title} />
|
||||
</svelte:fragment>
|
||||
<QuestionTitle {index} {title} />
|
||||
</HtmlRender>
|
||||
{#if !hideGrading}
|
||||
<Grade {gradeMax} bind:grade {disableGrading} />
|
||||
|
||||
@@ -3,14 +3,20 @@
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { snackbar } from '../Snackbar/store';
|
||||
|
||||
export let gradeMax = 0;
|
||||
export let disableGrading = false;
|
||||
export let grade: number | undefined = 0;
|
||||
|
||||
$: if (grade && grade > gradeMax) {
|
||||
snackbar.error('grade cant be more than max value');
|
||||
grade = gradeMax;
|
||||
interface Props {
|
||||
gradeMax?: number;
|
||||
disableGrading?: boolean;
|
||||
grade?: number | undefined;
|
||||
}
|
||||
|
||||
let { gradeMax = 0, disableGrading = false, grade = $bindable(0) }: Props = $props();
|
||||
|
||||
$effect(() => {
|
||||
if (grade && grade > gradeMax) {
|
||||
snackbar.error('grade cant be more than max value');
|
||||
grade = gradeMax;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex items-center font-semibold">
|
||||
@@ -24,7 +30,7 @@
|
||||
isDisabled={disableGrading}
|
||||
/>
|
||||
|
||||
<p class="dark:text-white ml-2 text-base flex items-center font-semibold">
|
||||
<p class="ml-2 flex items-center text-base font-semibold dark:text-white">
|
||||
<span class="mr-1">/</span> <span>{gradeMax}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<script lang="ts">
|
||||
export let index: number;
|
||||
export let title: string;
|
||||
interface Props {
|
||||
index: number | string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
let { index, title }: Props = $props();
|
||||
</script>
|
||||
|
||||
<span class="flex gap-2">
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from '$lib/utils/functions/svelte';
|
||||
|
||||
import CodeSnippet from '$lib/components/CodeSnippet/index.svelte';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
@@ -9,32 +11,59 @@
|
||||
import ReasonBox from '../ReasonBox.svelte';
|
||||
import QuestionTitle from '../QuestionTitle.svelte';
|
||||
|
||||
export let title = '';
|
||||
export let index = 1;
|
||||
export let code = '';
|
||||
export let name = '';
|
||||
export let options: { value: string; label: string; is_correct: boolean }[] = [];
|
||||
export let onSubmit = (a: string, b: string[]) => {};
|
||||
export let onPrevious = () => {};
|
||||
export let defaultValue = '';
|
||||
export let disablePreviousButton = false;
|
||||
export let disabled = false;
|
||||
export let isPreview = false;
|
||||
export let nextButtonProps = {
|
||||
isDisabled: false,
|
||||
isActive: false
|
||||
};
|
||||
export let isLast = false;
|
||||
export let grade: number;
|
||||
export let gradeMax = 0;
|
||||
export let disableGrading = false;
|
||||
export let disableOptContainerMargin = false;
|
||||
export let isGradeWithAI = false;
|
||||
export let reason;
|
||||
export let isLoading = false;
|
||||
export let hideGrading = false;
|
||||
interface Props {
|
||||
key: string | number;
|
||||
title?: string;
|
||||
index?: number | string;
|
||||
code?: string;
|
||||
name?: string;
|
||||
options?: { value: string; label: string; is_correct: boolean }[];
|
||||
onSubmit?: any;
|
||||
onPrevious?: any;
|
||||
defaultValue?: string;
|
||||
disablePreviousButton?: boolean;
|
||||
disabled?: boolean;
|
||||
isPreview?: boolean;
|
||||
nextButtonProps?: any;
|
||||
isLast?: boolean;
|
||||
grade?: number;
|
||||
gradeMax?: number;
|
||||
disableGrading?: boolean;
|
||||
disableOptContainerMargin?: boolean;
|
||||
isGradeWithAI?: boolean;
|
||||
reason?: string;
|
||||
isLoading?: boolean;
|
||||
hideGrading?: boolean;
|
||||
}
|
||||
|
||||
let gradeWithAI = false;
|
||||
let {
|
||||
title = '',
|
||||
index = 1,
|
||||
code = '',
|
||||
name = '',
|
||||
options = [],
|
||||
onSubmit = (_a: string, _b: string[]) => {},
|
||||
onPrevious = () => {},
|
||||
defaultValue = '',
|
||||
disablePreviousButton = false,
|
||||
disabled = false,
|
||||
isPreview = false,
|
||||
nextButtonProps = {
|
||||
isDisabled: false,
|
||||
isActive: false
|
||||
},
|
||||
isLast = false,
|
||||
grade = $bindable(),
|
||||
gradeMax = 0,
|
||||
disableGrading = false,
|
||||
disableOptContainerMargin = false,
|
||||
isGradeWithAI = false,
|
||||
reason,
|
||||
isLoading = false,
|
||||
hideGrading = false
|
||||
}: Props = $props();
|
||||
|
||||
let gradeWithAI = $derived(isGradeWithAI);
|
||||
|
||||
function getRadioVal(form, name): string {
|
||||
let val;
|
||||
@@ -80,16 +109,12 @@
|
||||
gradeWithAI = false;
|
||||
grade = 0;
|
||||
}
|
||||
|
||||
$: gradeWithAI = isGradeWithAI;
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={handleFormSubmit}>
|
||||
<form onsubmit={preventDefault(handleFormSubmit)}>
|
||||
<div class="flex items-center justify-between">
|
||||
<HtmlRender className="mt-4 {typeof grade === 'number' && 'w-4/5'}" disableMaxWidth>
|
||||
<svelte:fragment slot="content">
|
||||
<QuestionTitle {index} {title} />
|
||||
</svelte:fragment>
|
||||
<QuestionTitle {index} {title} />
|
||||
</HtmlRender>
|
||||
{#if !hideGrading}
|
||||
<Grade {gradeMax} bind:grade {disableGrading} />
|
||||
@@ -103,7 +128,7 @@
|
||||
<div class={disableOptContainerMargin ? '' : 'ml-4'}>
|
||||
{#each options as option}
|
||||
<button
|
||||
class="cursor-pointer text-left my-2 border-2 border-gray-300 rounded-md hover:bg-gray-200 dark:hover:bg-neutral-800 w-full {getValidationClassName(
|
||||
class="my-2 w-full cursor-pointer rounded-md border-2 border-gray-300 text-left hover:bg-gray-200 dark:hover:bg-neutral-800 {getValidationClassName(
|
||||
option
|
||||
)}"
|
||||
type="button"
|
||||
@@ -124,7 +149,7 @@
|
||||
{/if}
|
||||
|
||||
{#if !isPreview}
|
||||
<div class="mt-3 flex items-center justify-between w-full">
|
||||
<div class="mt-3 flex w-full items-center justify-between">
|
||||
<PrimaryButton
|
||||
onClick={handlePrevious}
|
||||
label={$t('course.navItem.lessons.exercises.all_exercises.previous')}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { VARIANTS } from '../PrimaryButton/constants';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { SkeletonPlaceholder, SkeletonText } from 'carbon-components-svelte';
|
||||
|
||||
export let reason = '';
|
||||
export let isLoading = false;
|
||||
export let rejectGrade = () => {};
|
||||
export let acceptGrade = () => {};
|
||||
interface Props {
|
||||
reason?: string;
|
||||
isLoading?: boolean;
|
||||
rejectGrade?: any;
|
||||
acceptGrade?: any;
|
||||
}
|
||||
|
||||
let { reason = '', isLoading = false, rejectGrade = () => {}, acceptGrade = () => {} }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="border rounded-md">
|
||||
<div class="rounded-md border">
|
||||
{#if isLoading}
|
||||
<div class="flex w-full px-2 py-4">
|
||||
<div class="w-full flex flex-row items-start space-x-4">
|
||||
<div class="flex w-full flex-row items-start space-x-4">
|
||||
<img src="/ai.svg" alt="alt" class="animate-pulse" />
|
||||
<div class="w-full">
|
||||
<SkeletonText width="100%" paragraph lines={3} />
|
||||
@@ -28,7 +32,7 @@
|
||||
<div class="flex items-start justify-between px-2 py-4">
|
||||
<div class="flex items-center space-x-4">
|
||||
<img src="/ai.svg" alt="alt" />
|
||||
<p class="font-normal text-sm">
|
||||
<p class="text-sm font-normal">
|
||||
{reason}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from '$lib/utils/functions/svelte';
|
||||
|
||||
import CodeSnippet from '$lib/components/CodeSnippet/index.svelte';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
@@ -9,28 +11,52 @@
|
||||
import ReasonBox from '../ReasonBox.svelte';
|
||||
import QuestionTitle from '../QuestionTitle.svelte';
|
||||
|
||||
export let title = '';
|
||||
export let index = 1;
|
||||
export let code = '';
|
||||
export let name = '';
|
||||
export let onSubmit = (a: string, b: string) => {};
|
||||
export let onPrevious = () => {};
|
||||
export let defaultValue = '';
|
||||
export let disablePreviousButton = false;
|
||||
export let isLast = false;
|
||||
export let isPreview = false;
|
||||
export let disabled = false;
|
||||
export let grade: number | undefined;
|
||||
export let gradeMax = 0;
|
||||
export let disableGrading = false;
|
||||
export let isGradeWithAI = false;
|
||||
export let reason;
|
||||
export let isLoading = false;
|
||||
export let hideGrading = false;
|
||||
interface Props {
|
||||
key: string | number;
|
||||
title?: string;
|
||||
index?: number | string;
|
||||
code?: string;
|
||||
name?: string;
|
||||
onSubmit?: any;
|
||||
onPrevious?: any;
|
||||
defaultValue?: string;
|
||||
disablePreviousButton?: boolean;
|
||||
isLast?: boolean;
|
||||
isPreview?: boolean;
|
||||
disabled?: boolean;
|
||||
grade?: number;
|
||||
gradeMax?: number;
|
||||
disableGrading?: boolean;
|
||||
isGradeWithAI?: boolean;
|
||||
reason?: string;
|
||||
isLoading?: boolean;
|
||||
hideGrading?: boolean;
|
||||
}
|
||||
|
||||
let gradeWithAI = false;
|
||||
let {
|
||||
title = '',
|
||||
index = 1,
|
||||
code = '',
|
||||
name = '',
|
||||
onSubmit = (_a: string, _b: string) => {},
|
||||
onPrevious = () => {},
|
||||
defaultValue = $bindable(''),
|
||||
disablePreviousButton = false,
|
||||
isLast = false,
|
||||
isPreview = false,
|
||||
disabled = false,
|
||||
grade = $bindable(),
|
||||
gradeMax = 0,
|
||||
disableGrading = false,
|
||||
isGradeWithAI = false,
|
||||
reason,
|
||||
isLoading = false,
|
||||
hideGrading = false
|
||||
}: Props = $props();
|
||||
|
||||
function handleFormSubmit(event) {
|
||||
let gradeWithAI = $derived(isGradeWithAI);
|
||||
|
||||
function handleFormSubmit() {
|
||||
if (isPreview) return;
|
||||
|
||||
onSubmit(name, defaultValue);
|
||||
@@ -49,16 +75,12 @@
|
||||
gradeWithAI = false;
|
||||
grade = 0;
|
||||
}
|
||||
|
||||
$: gradeWithAI = isGradeWithAI;
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={handleFormSubmit}>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<form onsubmit={preventDefault(handleFormSubmit)}>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<HtmlRender className="mt-4 {typeof grade === 'number' && 'w-4/5'}" disableMaxWidth>
|
||||
<svelte:fragment slot="content">
|
||||
<QuestionTitle {index} {title} />
|
||||
</svelte:fragment>
|
||||
<QuestionTitle {index} {title} />
|
||||
</HtmlRender>
|
||||
{#if !hideGrading}
|
||||
<Grade {gradeMax} bind:grade {disableGrading} />
|
||||
@@ -71,10 +93,8 @@
|
||||
|
||||
<div class="ml-4">
|
||||
{#if disabled}
|
||||
<div class="bg-gray-200 dark:bg-gray-500 py-3 px-5 rounded-md mb-3">
|
||||
{defaultValue === ''
|
||||
? $t('course.navItem.lessons.exercises.all_exercises.no_answer')
|
||||
: defaultValue}
|
||||
<div class="mb-3 rounded-md bg-gray-200 px-5 py-3 dark:bg-gray-500">
|
||||
{defaultValue === '' ? $t('course.navItem.lessons.exercises.all_exercises.no_answer') : defaultValue}
|
||||
</div>
|
||||
{#if gradeWithAI}
|
||||
<ReasonBox {reason} {isLoading} {acceptGrade} {rejectGrade} />
|
||||
@@ -89,7 +109,7 @@
|
||||
</div>
|
||||
|
||||
{#if !isPreview}
|
||||
<div class="mt-3 flex items-center justify-between w-full">
|
||||
<div class="mt-3 flex w-full items-center justify-between">
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={handlePrevious}
|
||||
|
||||
Reference in New Issue
Block a user