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:
@@ -12,12 +12,10 @@
|
||||
import { blockedSubdomain } from '$lib/utils/constants/app';
|
||||
import { getOrganizations } from '$lib/utils/services/org';
|
||||
import { generateSitename } from '$lib/utils/functions/org';
|
||||
import {
|
||||
triggerSendEmail,
|
||||
NOTIFICATION_NAME
|
||||
} from '$lib/utils/services/notification/notification';
|
||||
import { triggerSendEmail, NOTIFICATION_NAME } from '$lib/utils/services/notification/notification';
|
||||
import { handleLocaleChange, t } from '$lib/utils/functions/translations';
|
||||
import { LOCALE } from '$lib/utils/types';
|
||||
import { untrack } from 'svelte';
|
||||
|
||||
interface OnboardingField {
|
||||
fullname?: string;
|
||||
@@ -35,17 +33,16 @@
|
||||
}
|
||||
|
||||
const maxSteps = 2;
|
||||
let fields: OnboardingField = {
|
||||
let fields: OnboardingField = $state({
|
||||
fullname: '',
|
||||
orgName: '',
|
||||
siteName: '',
|
||||
locale: LOCALE.EN
|
||||
};
|
||||
let errors: OnboardingField = {};
|
||||
let progress = 50;
|
||||
let step = 1;
|
||||
let loading = false;
|
||||
let isSiteNameTouched = false;
|
||||
});
|
||||
let errors: OnboardingField = $state({});
|
||||
let step = $state(1);
|
||||
let loading = $state(false);
|
||||
let isSiteNameTouched = $state(false);
|
||||
let selectedId = 'en';
|
||||
|
||||
let dropdownItems = [
|
||||
@@ -61,6 +58,8 @@
|
||||
{ id: 'da', text: 'Danish' }
|
||||
];
|
||||
|
||||
const progress = $derived(Math.round((step / maxSteps) * 100));
|
||||
|
||||
const educatorGoals: Goal[] = [
|
||||
{
|
||||
label: $t('onboarding.sell'),
|
||||
@@ -116,15 +115,6 @@
|
||||
fields.metadata = payload;
|
||||
}
|
||||
|
||||
function setOrgSiteName(orgName: string | undefined, isTouched: boolean) {
|
||||
if (!orgName || isTouched) return;
|
||||
|
||||
fields.siteName = orgName
|
||||
?.toLowerCase()
|
||||
?.replace(/\s+/g, '-')
|
||||
?.replace(/[^a-zA-Z0-9-]/g, '');
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
loading = true;
|
||||
// Run validation
|
||||
@@ -233,9 +223,30 @@
|
||||
loading = false;
|
||||
};
|
||||
|
||||
$: progress = Math.round((step / maxSteps) * 100);
|
||||
$: fields.siteName = generateSitename(fields.siteName || '');
|
||||
$: setOrgSiteName(fields.orgName, isSiteNameTouched);
|
||||
function updateSiteName(sname?: string) {
|
||||
if (!sname) return;
|
||||
|
||||
untrack(() => {
|
||||
fields.siteName = generateSitename(sname);
|
||||
});
|
||||
}
|
||||
$effect(() => {
|
||||
updateSiteName(fields.siteName);
|
||||
});
|
||||
|
||||
function setOrgSiteName(orgName: string | undefined, isTouched: boolean) {
|
||||
if (!orgName || isTouched) return;
|
||||
|
||||
untrack(() => {
|
||||
fields.siteName = orgName
|
||||
?.toLowerCase()
|
||||
?.replace(/\s+/g, '-')
|
||||
?.replace(/[^a-zA-Z0-9-]/g, '');
|
||||
});
|
||||
}
|
||||
$effect(() => {
|
||||
setOrgSiteName(fields.orgName, isSiteNameTouched);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $profile.id}
|
||||
@@ -252,7 +263,7 @@
|
||||
<div
|
||||
class="mb-6 flex w-64 items-center justify-center rounded-2xl border border-gray-300 bg-gray-100 py-6 dark:bg-neutral-800"
|
||||
>
|
||||
<UserProfileIcon />
|
||||
<UserProfileIcon size={16} />
|
||||
<p class="ml-2 text-sm dark:text-white">{$profile.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -317,13 +328,7 @@
|
||||
<!-- Loop through Goals -->
|
||||
{#each educatorGoals as goal}
|
||||
<label class="mb-1 inline-flex w-full items-center font-light dark:text-white">
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={fields.goal}
|
||||
name="goal"
|
||||
value={goal.value}
|
||||
class="mr-2"
|
||||
/>
|
||||
<input type="radio" bind:group={fields.goal} name="goal" value={goal.value} class="mr-2" />
|
||||
{goal.label}
|
||||
</label>
|
||||
{/each}
|
||||
@@ -344,13 +349,7 @@
|
||||
<!-- Loop through Goals -->
|
||||
{#each sources as source}
|
||||
<label class="mb-1 inline-flex w-full items-center font-light dark:text-white">
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={fields.source}
|
||||
name="source"
|
||||
value={source.value}
|
||||
class="mr-2"
|
||||
/>
|
||||
<input type="radio" bind:group={fields.source} name="source" value={source.value} class="mr-2" />
|
||||
{source.label}
|
||||
</label>
|
||||
{/each}
|
||||
@@ -365,12 +364,7 @@
|
||||
<!-- Language Picker -->
|
||||
<div class="mt-10">
|
||||
<span>{$t('content.toggle_label')}: </span>
|
||||
<Dropdown
|
||||
items={dropdownItems}
|
||||
{selectedId}
|
||||
on:select={handleSelect}
|
||||
class="w-full"
|
||||
/>
|
||||
<Dropdown items={dropdownItems} {selectedId} on:select={handleSelect} class="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -380,10 +374,7 @@
|
||||
<!-- Footer -->
|
||||
<div class="mt-8 flex w-full items-center justify-between">
|
||||
<div class="relative h-2 w-24 bg-gray-300">
|
||||
<span
|
||||
class="progress bg-primary-700 absolute left-0 top-0 h-full"
|
||||
style="width: {progress}%;"
|
||||
/>
|
||||
<span class="progress bg-primary-700 absolute left-0 top-0 h-full" style="width: {progress}%;"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
|
||||
Reference in New Issue
Block a user