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:
Rotimi Best
2025-11-01 15:49:29 +01:00
committed by GitHub
parent 97fb446df5
commit b96d91cd7c
801 changed files with 22279 additions and 10834 deletions
@@ -1,8 +1,8 @@
<script>
<script lang="ts">
import Chip from '$lib/components/Chip/Text.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import CheckmarkOutline from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
import CircleCheckIcon from '$lib/components/Icons/CircleCheckIcon.svelte';
import { currentOrg } from '$lib/utils/store/org';
import { goto } from '$app/navigation';
@@ -10,9 +10,17 @@
import { profile } from '$lib/utils/store/user';
import { t } from '$lib/utils/functions/translations';
export let data;
let setupList = data.setup || [];
let completed = 0;
let { data } = $props();
const setupList = $derived(
(data.setup || []).map((item) => {
if (item.id === 'profile') {
item.is_completed = !$profile.avatar_url.includes('avatars/avatar.png');
}
return item;
})
);
const completed = $derived(setupList.filter((list) => list.is_completed).length);
const StepsEnum = {
UPDATE_PROFILE: 'profile',
@@ -70,21 +78,12 @@
break;
}
};
$: setupList = setupList.map((item) => {
if (item.id === 'profile') {
item.is_completed = !$profile.avatar_url.includes('avatars/avatar.png');
}
return item;
});
$: completed = setupList.filter((list) => list.is_completed).length;
</script>
<section class="w-full md:max-w-4xl mx-auto">
<div class="py-2 md:py-10 px-2 md:px-5">
<section class="mx-auto w-full md:max-w-4xl">
<div class="px-2 py-2 md:px-5 md:py-10">
<div class="flex items-center gap-2">
<h1 class="dark:text-white text-2xl md:text-3xl font-bold">{$t('setup.get_started')}</h1>
<h1 class="text-2xl font-bold md:text-3xl dark:text-white">{$t('setup.get_started')}</h1>
<Chip
value={`${completed}/${setupList.length}`}
className="text-[10px] font-semibold px-3 !py-1"
@@ -95,18 +94,14 @@
<section class="px-4">
{#each setupList as list, i}
<div
class="flex flex-col lg:flex-row lg:items-center justify-between gap-2 w-full py-8 border-b border-gray-300"
class="flex w-full flex-col justify-between gap-2 border-b border-gray-300 py-8 lg:flex-row lg:items-center"
>
<div class={`space-y-1 flex-1 ${list.is_completed ? 'opacity-50' : ''} lg:max-w-[50%]`}>
<div class={`flex-1 space-y-1 ${list.is_completed ? 'opacity-50' : ''} lg:max-w-[50%]`}>
<div class="flex items-center gap-3">
<Chip
value={i + 1}
className={`text-[10px] font-semibold !py-1 `}
shape="rounded-full"
/>
<p class="font-medium text-lg">{$t(list.title)}</p>
<Chip value={i + 1} className={`text-[10px] font-semibold !py-1 `} shape="rounded-full" />
<p class="text-lg font-medium">{$t(list.title)}</p>
</div>
<p class={`text-sm`}>
<p class="text-sm">
{$t(list.desc)}
</p>
</div>
@@ -118,7 +113,7 @@
isDisabled={list.is_completed}
>
{#if list.is_completed}
<CheckmarkOutline />
<CircleCheckIcon size={16} />
{/if}
{$t(list.button_label)}
</PrimaryButton>
@@ -1,5 +1,5 @@
import { getSupabase } from '$lib/utils/functions/supabase';
import get from 'lodash/get';
import { getSupabase } from '$lib/utils/functions/supabase';
const supabase = getSupabase();
@@ -53,9 +53,7 @@ async function getGenericData(orgSlug: string): Promise<{
};
}
async function getIsLessonCreated(
orgSlug: string
): Promise<{ isLessonCreated: boolean; lessonData: any }> {
async function getIsLessonCreated(orgSlug: string): Promise<{ isLessonCreated: boolean; lessonData: any }> {
const { data } = await supabase
.from('lesson')
.select(
@@ -104,9 +102,7 @@ async function getIsExerciseCreated(orgSlug: string): Promise<boolean> {
}
export const load = async ({ params = { slug: '' } }) => {
const { isCourseCreated, isCoursePublished, orgHasAvatarUrl, courseData } = await getGenericData(
params.slug
);
const { isCourseCreated, isCoursePublished, orgHasAvatarUrl, courseData } = await getGenericData(params.slug);
const { isLessonCreated, lessonData } = await getIsLessonCreated(params.slug);
const isExerciseCreated = await getIsExerciseCreated(params.slug);