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
This commit is contained in:
Rotimi Best
2025-11-01 09:54:19 +01:00
committed by GitHub
parent 97fb446df5
commit 86adad9358
4 changed files with 150 additions and 159 deletions
@@ -1,11 +1,11 @@
<script> <script lang="ts">
import { Dropdown } from 'carbon-components-svelte'; import { Dropdown } from 'carbon-components-svelte';
import { t, initialized } from '$lib/utils/functions/translations'; import { t, initialized } from '$lib/utils/functions/translations';
import { LANGUAGES } from '$lib/utils/constants/translation'; import { LANGUAGES } from '$lib/utils/constants/translation';
import { LOCALE } from '$lib/utils/types'; import { LOCALE } from '$lib/utils/types';
export let className = ''; export let className = '';
export let value = LOCALE.EN; export let value: LOCALE = LOCALE.EN;
export let hasLangChanged = false; export let hasLangChanged = false;
const dropdownItems = [{ id: '', text: 'Pick a Language' }, ...LANGUAGES]; const dropdownItems = [{ id: '', text: 'Pick a Language' }, ...LANGUAGES];
@@ -1,4 +1,4 @@
<script> <script lang="ts">
import TextField from '$lib/components/Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
@@ -13,14 +13,15 @@
import { Column, Grid, Row } from 'carbon-components-svelte'; import { Column, Grid, Row } from 'carbon-components-svelte';
import SectionTitle from '../SectionTitle.svelte'; import SectionTitle from '../SectionTitle.svelte';
import LanguagePicker from './LanguagePicker.svelte'; import LanguagePicker from './LanguagePicker.svelte';
import { LOCALE } from '$lib/utils/types';
let avatar = ''; let avatar = '';
let loading = false; let loading = false;
let hasLangChanged = false; let hasLangChanged = false;
let locale = ''; let locale: LOCALE;
let hasUnsavedChanges = false; let hasUnsavedChanges = false;
let errors = {}; let errors: Record<string, string> = {};
async function handleUpdate() { async function handleUpdate() {
errors = updateProfileValidation($profile); errors = updateProfileValidation($profile);
@@ -33,7 +34,7 @@
console.log({ hasLangChanged }); console.log({ hasLangChanged });
loading = true; loading = true;
const updates = { const updates: Partial<typeof $profile> = {
fullname: $profile.fullname, fullname: $profile.fullname,
username: $profile.username, username: $profile.username,
email: $profile.email, email: $profile.email,
@@ -54,7 +55,8 @@
updates.avatar_url = response.publicUrl; updates.avatar_url = response.publicUrl;
$profile.avatar_url = response.publicUrl; $profile.avatar_url = response.publicUrl;
} }
avatar = undefined;
avatar = '';
} }
let { error } = await supabase.from('profile').update(updates).match({ id: $profile.id }); let { error } = await supabase.from('profile').update(updates).match({ id: $profile.id });
@@ -127,12 +129,7 @@
errorMessage={$t(errors.email)} errorMessage={$t(errors.email)}
onChange={() => (hasUnsavedChanges = true)} onChange={() => (hasUnsavedChanges = true)}
/> />
<LanguagePicker <LanguagePicker bind:hasLangChanged bind:value={locale} className="w-full lg:w-60 mb-4" />
onChange={() => (hasUnsavedChanges = true)}
bind:hasLangChanged
bind:value={locale}
className="w-full lg:w-60 mb-4"
/>
</Column> </Column>
</Row> </Row>
+23 -19
View File
@@ -1,30 +1,34 @@
export const blockedSubdomain = [ export const blockedSubdomain = [
'academy',
'app', 'app',
'apps', 'apps',
'play', 'blog',
'support',
'demo',
'help',
'teachers',
'church',
'tech',
'build', 'build',
'campaign',
'church',
'cloud',
'community', 'community',
'conference', 'conference',
'campaign', 'course',
'blog', 'courses',
'forum', 'demo',
'mobile',
'dev', 'dev',
'stage', 'forum',
'prod',
'group', 'group',
'groups', 'groups',
'academy', 'help',
'schools', 'launch',
'training',
'cloud',
'launchweek', 'launchweek',
'course', 'mobile',
'launch' 'play',
'prod',
'production',
'schools',
'stage',
'staging',
'support',
'teacher',
'teachers',
'tech',
'training'
]; ];
@@ -2,141 +2,40 @@ import z from 'zod';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import isNumber from 'lodash/isNumber'; import isNumber from 'lodash/isNumber';
import { validateEmail } from './validateEmail'; import { validateEmail } from './validateEmail';
import { t as _t, initialized } from '$lib/utils/functions/translations'; import { t, initialized } from '$lib/utils/functions/translations';
const t = { function getOrgNameValidation() {
get: (key: string) => { return z
const isInitialized = get(initialized);
if (!isInitialized) return key;
return _t.get(key);
}
};
const getOrgNameValidation = () =>
z
.string() .string()
.min(5, { message: `${t.get('validations.organization_name.min_char')}` }) .min(5, { message: `${t.get('validations.organization_name.min_char')}` })
.refine((val) => !/^[-]|[-]$/.test(val), { .refine((val) => !/^[-]|[-]$/.test(val), {
message: `${t.get('validations.organization_name.hyphen_rule')}` message: `${t.get('validations.organization_name.hyphen_rule')}`
}); });
}
const getSiteNameValidation = () => function getSiteNameValidation() {
z return z
.string() .string()
.min(5, { message: `${t.get('validations.site_name.min_char')}` }) .min(5, { message: `${t.get('validations.site_name.min_char')}` })
.refine((val) => !/^[-]|[-]$/.test(val), { .refine((val) => !/^[-]|[-]$/.test(val), {
message: `${t.get('validations.site_name.hyphen_rule')}` message: `${t.get('validations.site_name.hyphen_rule')}`
}); });
}
function getNewsfeedValidation() {
return z.string().min(5, { message: `${t.get('validations.news_feed.min_char')}` });
}
const getNewsfeedValidation = () => export const saveCertificateValidation = (fields = {}) => {
z.string().min(5, { message: `${t.get('validations.news_feed.min_char')}` }); const schema = z.object({
const lessonSchema = z.object({
title: z.string().nonempty({ message: `${t.get('validations.lesson_schema.empty_title')}` }),
lesson_at: z.string().optional(),
call_url: z.string().nullable().optional(),
is_unlocked: z.boolean().optional()
});
const createQuizValidationSchema = z.object({
title: z.string().min(6, {
message: `${t.get('validations.course_payment.full_name.min_char')}`
})
});
const askCommunityValidationSchema = z.object({
title: z.string().min(6, {
message: `${t.get('validations.ask_community.title.min_char')}`
}),
body: z.string().min(20, {
message: `${t.get('validations.ask_community.body.min_char')}`
}),
courseId: z.string().min(36, {
message: `${t.get('validations.ask_community.course_id.select_course')}`
})
});
const commentInCommunityValidationSchema = z.object({
comment: z.string().min(6, {
message: `${t.get('validations.comment_in_community.min_char')}`
})
});
const orgLandingpageValidationSchema = z.object({
name: z.string().min(6, {
message: `${t.get('validations.org_landing_page.name.min_char')}`
}),
email: z.string().email({
message: `${t.get('validations.org_landing_page.email.invalid_email')}`
}),
phone: z.string().min(6, {
message: `${t.get('validations.org_landing_page.phone.min_char')}`
}),
message: z.string().min(20, {
message: `${t.get('validations.org_landing_page.message.min_char')}`
})
});
const forgotValidationSchema = z.object({
email: z.string().email({
message: `${t.get('validations.forgot.invalid_email')}`
})
});
const authValidationSchema = z.object({
email: z.string().email({
message: 'validations.auth.email.invalid_email'
}),
password: z.string().min(6, {
message: 'validations.auth.password.min_char'
})
});
const resetValidationSchema = z.object({
password: z.string().min(6, {
message: `${t.get('validations.reset.password.min_char')}`
})
});
const onboardingValidationSchema = {
stepOne: z.object({
fullname: z
.string()
.min(5, { message: `${t.get('validations.onboarding.step_one.full_name.min_char')}` }),
orgName: getOrgNameValidation(),
siteName: getSiteNameValidation()
}),
stepTwo: z.object({
goal: z
.string({
required_error: `${t.get('validations.onboarding.step_two.goal.required')}`
})
.min(1),
source: z
.string({
required_error: `${t.get('validations.onboarding.step_two.source.required')}`
})
.min(1)
})
};
const saveCertificateSchema = z.object({
description: z.string().max(200, 'course.navItem.certificates.description_error'), description: z.string().max(200, 'course.navItem.certificates.description_error'),
is_certificate_downloadable: z.boolean(), is_certificate_downloadable: z.boolean(),
certificate_theme: z.string() certificate_theme: z.string()
}); });
export const saveCertificateValidation = (fields = {}) => { const { error } = schema.safeParse(fields);
const { error } = saveCertificateSchema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
const updateProfileValidationSchema = z.object({
email: z.string().email({ message: 'validations.user_profile.email' }),
username: z.string().nonempty({ message: 'validations.user_profile.username' }),
fullname: z.string().min(5, { message: 'validations.user_profile.fullname' })
});
export const getConfirmPasswordError = ({ password, confirmPassword }) => { export const getConfirmPasswordError = ({ password, confirmPassword }) => {
return password > 6 && confirmPassword > 6 && password !== confirmPassword return password > 6 && confirmPassword > 6 && password !== confirmPassword
? `${t.get('validations.confirm_password.not_match')}` ? `${t.get('validations.confirm_password.not_match')}`
@@ -173,12 +72,30 @@ export const processErrors = (error, mapToId?: boolean) => {
}; };
export const authValidation = (fields = {}) => { export const authValidation = (fields = {}) => {
const { error } = authValidationSchema.safeParse(fields); const schema = z.object({
email: z.string().email({
message: 'validations.auth.email.invalid_email'
}),
password: z.string().min(6, {
message: 'validations.auth.password.min_char'
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
export const lessonValidation = (lesson = {}) => { export const lessonValidation = (lesson = {}) => {
const { error } = lessonSchema.safeParse(lesson); const schema = z.object({
title: z.string().nonempty({ message: `${t.get('validations.lesson_schema.empty_title')}` }),
lesson_at: z.string().optional(),
call_url: z.string().nullable().optional(),
is_unlocked: z.boolean().optional()
});
const { error } = schema.safeParse(lesson);
return processErrors(error); return processErrors(error);
}; };
@@ -197,24 +114,70 @@ export const coursePaymentValidation = (fields = {}) => {
}; };
export const resetValidation = (fields = {}) => { export const resetValidation = (fields = {}) => {
const { error } = resetValidationSchema.safeParse(fields); const schema = z.object({
password: z.string().min(6, {
message: `${t.get('validations.reset.password.min_char')}`
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
export const forgotValidation = (fields = {}) => { export const forgotValidation = (fields = {}) => {
const { error } = forgotValidationSchema.safeParse(fields); const schema = z.object({
email: z.string().email({
message: `${t.get('validations.forgot.invalid_email')}`
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
export const orgLandingpageValidation = (fields = {}) => { export const orgLandingpageValidation = (fields = {}) => {
const { error } = orgLandingpageValidationSchema.safeParse(fields); const schema = z.object({
name: z.string().min(6, {
message: `${t.get('validations.org_landing_page.name.min_char')}`
}),
email: z.string().email({
message: `${t.get('validations.org_landing_page.email.invalid_email')}`
}),
phone: z.string().min(6, {
message: `${t.get('validations.org_landing_page.phone.min_char')}`
}),
message: z.string().min(20, {
message: `${t.get('validations.org_landing_page.message.min_char')}`
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
export const onboardingValidation = (fields = {}, step) => { export const onboardingValidation = (fields = {}, step) => {
const onboardingValidationSchema = {
stepOne: z.object({
fullname: z
.string()
.min(5, { message: `${t.get('validations.onboarding.step_one.full_name.min_char')}` }),
orgName: getOrgNameValidation(),
siteName: getSiteNameValidation()
}),
stepTwo: z.object({
goal: z
.string({
required_error: `${t.get('validations.onboarding.step_two.goal.required')}`
})
.min(1),
source: z
.string({
required_error: `${t.get('validations.onboarding.step_two.source.required')}`
})
.min(1)
})
};
const schema = const schema =
step === 1 ? onboardingValidationSchema.stepOne : onboardingValidationSchema.stepTwo; step === 1 ? onboardingValidationSchema.stepOne : onboardingValidationSchema.stepTwo;
const { error } = schema.safeParse(fields); const { error } = schema.safeParse(fields);
@@ -223,7 +186,11 @@ export const onboardingValidation = (fields = {}, step) => {
}; };
export const updateProfileValidation = (fields = {}) => { export const updateProfileValidation = (fields = {}) => {
const schema = updateProfileValidationSchema; const schema = z.object({
email: z.string().email({ message: 'validations.user_profile.email' }),
username: z.string().nonempty({ message: 'validations.user_profile.username' }),
fullname: z.string().min(5, { message: 'validations.user_profile.fullname' })
});
const { error } = schema.safeParse(fields); const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
@@ -297,19 +264,42 @@ export const updateProfileEmailValidation = (email) => {
}; };
export const createQuizValidation = (fields = {}) => { export const createQuizValidation = (fields = {}) => {
const { error } = createQuizValidationSchema.safeParse(fields); const schema = z.object({
title: z.string().min(6, {
message: `${t.get('validations.course_payment.full_name.min_char')}`
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
export const askCommunityValidation = (fields = {}) => { export const askCommunityValidation = (fields = {}) => {
const { error } = askCommunityValidationSchema.safeParse(fields); const schema = z.object({
title: z.string().min(6, {
message: `${t.get('validations.ask_community.title.min_char')}`
}),
body: z.string().min(20, {
message: `${t.get('validations.ask_community.body.min_char')}`
}),
courseId: z.string().min(36, {
message: `${t.get('validations.ask_community.course_id.select_course')}`
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };
export const commentInCommunityValidation = (fields = {}) => { export const commentInCommunityValidation = (fields = {}) => {
const { error } = commentInCommunityValidationSchema.safeParse(fields); const schema = z.object({
comment: z.string().min(6, {
message: `${t.get('validations.comment_in_community.min_char')}`
})
});
const { error } = schema.safeParse(fields);
return processErrors(error); return processErrors(error);
}; };