update account form for email login
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { ExternalLink } from '@/public/assets/external-link';
|
import { ExternalLink } from '@/public/assets/external-link';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
@@ -21,9 +24,10 @@ import { Trans } from '@kit/ui/trans';
|
|||||||
|
|
||||||
import { UpdateAccountSchemaClient } from '../_lib/schemas/update-account.schema';
|
import { UpdateAccountSchemaClient } from '../_lib/schemas/update-account.schema';
|
||||||
import { onUpdateAccount } from '../_lib/server/update-account';
|
import { onUpdateAccount } from '../_lib/server/update-account';
|
||||||
import { z } from 'zod';
|
import { toast } from '@kit/ui/sonner';
|
||||||
|
import { pathsConfig } from '@/packages/shared/src/config';
|
||||||
|
|
||||||
type UpdateAccountFormValues = z.infer<typeof UpdateAccountSchemaClient>;
|
type UpdateAccountFormValues = z.infer<ReturnType<typeof UpdateAccountSchemaClient>>;
|
||||||
|
|
||||||
export function UpdateAccountForm({
|
export function UpdateAccountForm({
|
||||||
defaultValues,
|
defaultValues,
|
||||||
@@ -32,33 +36,56 @@ export function UpdateAccountForm({
|
|||||||
defaultValues: UpdateAccountFormValues,
|
defaultValues: UpdateAccountFormValues,
|
||||||
isEmailUser: boolean,
|
isEmailUser: boolean,
|
||||||
}) {
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useTranslation('account');
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
resolver: zodResolver(UpdateAccountSchemaClient),
|
resolver: zodResolver(UpdateAccountSchemaClient({ isEmailUser })),
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
defaultValues,
|
defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { firstName, lastName, personalCode, email, weight, height, userConsent } = defaultValues;
|
const { firstName, lastName, personalCode, email, userConsent } = defaultValues;
|
||||||
|
|
||||||
|
const defaultValues_weight = "weight" in defaultValues ? defaultValues.weight : null;
|
||||||
|
const defaultValues_height = "height" in defaultValues ? defaultValues.height : null;
|
||||||
|
|
||||||
const hasFirstName = !!firstName;
|
const hasFirstName = !!firstName;
|
||||||
const hasLastName = !!lastName;
|
const hasLastName = !!lastName;
|
||||||
const hasPersonalCode = !!personalCode;
|
const hasPersonalCode = !!personalCode;
|
||||||
const hasEmail = !!email;
|
const hasEmail = !!email;
|
||||||
const hasWeight = !!weight;
|
|
||||||
const hasHeight = !!height;
|
|
||||||
|
|
||||||
const onUpdateAccountOptions = async (values: UpdateAccountFormValues) =>
|
const onUpdateAccountOptions = async (values: UpdateAccountFormValues) => {
|
||||||
onUpdateAccount({
|
const loading = toast.loading(t('updateAccount.updateAccountLoading'));
|
||||||
firstName: hasFirstName ? firstName : values.firstName,
|
try {
|
||||||
lastName: hasLastName ? lastName : values.lastName,
|
const response = await onUpdateAccount({
|
||||||
personalCode: hasPersonalCode ? personalCode : values.personalCode,
|
firstName: hasFirstName ? firstName : values.firstName,
|
||||||
email: hasEmail ? email : values.email,
|
lastName: hasLastName ? lastName : values.lastName,
|
||||||
phone: values.phone,
|
personalCode: hasPersonalCode ? personalCode : values.personalCode,
|
||||||
weight: (hasWeight ? weight : values.weight) as number,
|
email: hasEmail ? email : values.email,
|
||||||
height: (hasHeight ? height : values.height) as number,
|
phone: values.phone,
|
||||||
userConsent: values.userConsent ?? userConsent,
|
weight: ((("weight" in values && values.weight) ?? defaultValues_weight) || null) as number,
|
||||||
city: values.city,
|
height: ((("height" in values && values.height) ?? defaultValues_height) || null) as number,
|
||||||
});
|
userConsent: values.userConsent ?? userConsent,
|
||||||
|
city: values.city,
|
||||||
|
});
|
||||||
|
if (!response) {
|
||||||
|
throw new Error('Failed to update account');
|
||||||
|
}
|
||||||
|
toast.dismiss(loading);
|
||||||
|
toast.success(t('updateAccount.updateAccountSuccess'));
|
||||||
|
|
||||||
|
if (response.hasUnseenMembershipConfirmation) {
|
||||||
|
router.push(pathsConfig.auth.membershipConfirmation);
|
||||||
|
} else {
|
||||||
|
router.push(pathsConfig.app.selectPackage);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.info("promiseresult error", error);
|
||||||
|
toast.error(t('updateAccount.updateAccountError'));
|
||||||
|
toast.dismiss(loading);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ const updateAccountSchema = {
|
|||||||
.string({
|
.string({
|
||||||
error: 'Last name is required',
|
error: 'Last name is required',
|
||||||
})
|
})
|
||||||
.nonempty(),
|
.nonempty({
|
||||||
|
error: 'common:formFieldError.stringNonEmpty',
|
||||||
|
}),
|
||||||
personalCode: z.string().refine(
|
personalCode: z.string().refine(
|
||||||
(val) => {
|
(val) => {
|
||||||
try {
|
try {
|
||||||
@@ -30,7 +32,7 @@ const updateAccountSchema = {
|
|||||||
}),
|
}),
|
||||||
phone: z
|
phone: z
|
||||||
.string({
|
.string({
|
||||||
error: 'Phone number is required',
|
error: 'error:invalidPhone',
|
||||||
})
|
})
|
||||||
.nonempty()
|
.nonempty()
|
||||||
.refine(
|
.refine(
|
||||||
@@ -75,18 +77,26 @@ export const UpdateAccountSchemaServer = z.object({
|
|||||||
email: updateAccountSchema.email,
|
email: updateAccountSchema.email,
|
||||||
phone: updateAccountSchema.phone,
|
phone: updateAccountSchema.phone,
|
||||||
city: updateAccountSchema.city,
|
city: updateAccountSchema.city,
|
||||||
weight: updateAccountSchema.weight,
|
weight: updateAccountSchema.weight.nullable(),
|
||||||
height: updateAccountSchema.height,
|
height: updateAccountSchema.height.nullable(),
|
||||||
userConsent: updateAccountSchema.userConsent,
|
userConsent: updateAccountSchema.userConsent,
|
||||||
});
|
});
|
||||||
export const UpdateAccountSchemaClient = z.object({
|
export const UpdateAccountSchemaClient = ({ isEmailUser }: { isEmailUser: boolean }) => z.object({
|
||||||
firstName: updateAccountSchema.firstName,
|
firstName: updateAccountSchema.firstName,
|
||||||
lastName: updateAccountSchema.lastName,
|
lastName: updateAccountSchema.lastName,
|
||||||
personalCode: updateAccountSchema.personalCode,
|
personalCode: updateAccountSchema.personalCode,
|
||||||
email: updateAccountSchema.email,
|
email: updateAccountSchema.email,
|
||||||
phone: updateAccountSchema.phone,
|
phone: updateAccountSchema.phone,
|
||||||
city: updateAccountSchema.city,
|
...(isEmailUser
|
||||||
weight: updateAccountSchema.weight.gt(-1).gte(0).nullable(),
|
? {
|
||||||
height: updateAccountSchema.height.gt(-1).gte(0).nullable(),
|
city: z.string().optional(),
|
||||||
|
weight: z.number().optional(),
|
||||||
|
height: z.number().optional(),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
city: updateAccountSchema.city,
|
||||||
|
weight: updateAccountSchema.weight,
|
||||||
|
height: updateAccountSchema.height,
|
||||||
|
}),
|
||||||
userConsent: updateAccountSchema.userConsent,
|
userConsent: updateAccountSchema.userConsent,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
import { updateCustomer } from '@lib/data/customer';
|
import { updateCustomer } from '@lib/data/customer';
|
||||||
|
|
||||||
import { AccountSubmitData, createAuthApi } from '@kit/auth/api';
|
import { AccountSubmitData, createAuthApi } from '@kit/auth/api';
|
||||||
@@ -39,11 +37,8 @@ export const onUpdateAccount = enhanceAction(
|
|||||||
|
|
||||||
const hasUnseenMembershipConfirmation =
|
const hasUnseenMembershipConfirmation =
|
||||||
await api.hasUnseenMembershipConfirmation();
|
await api.hasUnseenMembershipConfirmation();
|
||||||
|
return {
|
||||||
if (hasUnseenMembershipConfirmation) {
|
hasUnseenMembershipConfirmation,
|
||||||
redirect(pathsConfig.auth.membershipConfirmation);
|
|
||||||
} else {
|
|
||||||
redirect(pathsConfig.app.selectPackage);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { Trans } from 'react-i18next';
|
|||||||
import { AccountWithParams } from '@kit/accounts/api';
|
import { AccountWithParams } from '@kit/accounts/api';
|
||||||
import { useRevalidatePersonalAccountDataQuery } from '@kit/accounts/hooks/use-personal-account-data';
|
import { useRevalidatePersonalAccountDataQuery } from '@kit/accounts/hooks/use-personal-account-data';
|
||||||
import { Button } from '@kit/ui/button';
|
import { Button } from '@kit/ui/button';
|
||||||
import { Card, CardTitle } from '@kit/ui/card';
|
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@@ -25,7 +24,6 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@kit/ui/select';
|
} from '@kit/ui/select';
|
||||||
import { toast } from '@kit/ui/sonner';
|
import { toast } from '@kit/ui/sonner';
|
||||||
import { Switch } from '@kit/ui/switch';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AccountSettings,
|
AccountSettings,
|
||||||
@@ -131,7 +129,11 @@ export default function AccountSettingsForm({
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input
|
||||||
|
placeholder="cm"
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -150,7 +152,11 @@ export default function AccountSettingsForm({
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input
|
||||||
|
placeholder="kg"
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export const accountSettingsSchema = z.object({
|
|||||||
email: z.email({ error: 'error:invalidEmail' }).nullable(),
|
email: z.email({ error: 'error:invalidEmail' }).nullable(),
|
||||||
phone: z.e164({ error: 'error:invalidPhone' }),
|
phone: z.e164({ error: 'error:invalidPhone' }),
|
||||||
accountParams: z.object({
|
accountParams: z.object({
|
||||||
height: z.coerce.number({ error: 'error:invalidNumber' }),
|
height: z.coerce.number({ error: 'error:invalidNumber' }).gt(0),
|
||||||
weight: z.coerce.number({ error: 'error:invalidNumber' }),
|
weight: z.coerce.number({ error: 'error:invalidNumber' }).gt(0),
|
||||||
isSmoker: z.boolean().optional().nullable(),
|
isSmoker: z.boolean().optional().nullable(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const personalCodeSchema = z.string().refine(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: 'Invalid personal code',
|
message: 'common:formFieldError.invalidPersonalCode',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import Isikukood, { Gender } from 'isikukood';
|
import Isikukood from 'isikukood';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the code is running in a browser environment.
|
* Check if the code is running in a browser environment.
|
||||||
|
|||||||
@@ -130,7 +130,10 @@
|
|||||||
"description": "Please enter your personal details to continue",
|
"description": "Please enter your personal details to continue",
|
||||||
"button": "Continue",
|
"button": "Continue",
|
||||||
"userConsentLabel": "I agree to the use of personal data on the platform",
|
"userConsentLabel": "I agree to the use of personal data on the platform",
|
||||||
"userConsentUrlTitle": "View privacy policy"
|
"userConsentUrlTitle": "View privacy policy",
|
||||||
|
"updateAccountLoading": "Updating account details...",
|
||||||
|
"updateAccountSuccess": "Account details updated",
|
||||||
|
"updateAccountError": "Updating account details error"
|
||||||
},
|
},
|
||||||
"consentModal": {
|
"consentModal": {
|
||||||
"title": "Before we start",
|
"title": "Before we start",
|
||||||
|
|||||||
@@ -129,7 +129,9 @@
|
|||||||
"selectDate": "Select date"
|
"selectDate": "Select date"
|
||||||
},
|
},
|
||||||
"formFieldError": {
|
"formFieldError": {
|
||||||
"invalidPhoneNumber": "Please enter a valid Estonian phone number (must include country code +372)"
|
"invalidPhoneNumber": "Please enter a valid Estonian phone number (must include country code +372)",
|
||||||
|
"invalidPersonalCode": "Please enter a valid Estonian personal code",
|
||||||
|
"stringNonEmpty": "This field is required"
|
||||||
},
|
},
|
||||||
"wallet": {
|
"wallet": {
|
||||||
"balance": "Your MedReport account balance",
|
"balance": "Your MedReport account balance",
|
||||||
|
|||||||
@@ -130,7 +130,10 @@
|
|||||||
"description": "Jätkamiseks palun sisestage enda isikuandmed",
|
"description": "Jätkamiseks palun sisestage enda isikuandmed",
|
||||||
"button": "Jätka",
|
"button": "Jätka",
|
||||||
"userConsentLabel": "Nõustun isikuandmete kasutamisega platvormil",
|
"userConsentLabel": "Nõustun isikuandmete kasutamisega platvormil",
|
||||||
"userConsentUrlTitle": "Vaata isikuandmete töötlemise põhimõtteid"
|
"userConsentUrlTitle": "Vaata isikuandmete töötlemise põhimõtteid",
|
||||||
|
"updateAccountLoading": "Konto andmed uuendatakse...",
|
||||||
|
"updateAccountSuccess": "Konto andmed uuendatud",
|
||||||
|
"updateAccountError": "Konto andmete uuendamine ebaõnnestus"
|
||||||
},
|
},
|
||||||
"consentModal": {
|
"consentModal": {
|
||||||
"title": "Enne alustamist",
|
"title": "Enne alustamist",
|
||||||
|
|||||||
@@ -129,7 +129,9 @@
|
|||||||
"selectDate": "Vali kuupäev"
|
"selectDate": "Vali kuupäev"
|
||||||
},
|
},
|
||||||
"formFieldError": {
|
"formFieldError": {
|
||||||
"invalidPhoneNumber": "Palun sisesta Eesti telefoninumber (peab sisaldama riigikoodi +372)"
|
"invalidPhoneNumber": "Palun sisesta Eesti telefoninumber (peab sisaldama riigikoodi +372)",
|
||||||
|
"invalidPersonalCode": "Palun sisesta Eesti isikukood",
|
||||||
|
"stringNonEmpty": "See väli on kohustuslik"
|
||||||
},
|
},
|
||||||
"wallet": {
|
"wallet": {
|
||||||
"balance": "Sinu MedReporti konto saldo",
|
"balance": "Sinu MedReporti konto saldo",
|
||||||
|
|||||||
@@ -130,7 +130,10 @@
|
|||||||
"description": "Пожалуйста, введите личные данные для продолжения",
|
"description": "Пожалуйста, введите личные данные для продолжения",
|
||||||
"button": "Продолжить",
|
"button": "Продолжить",
|
||||||
"userConsentLabel": "Я согласен на использование персональных данных на платформе",
|
"userConsentLabel": "Я согласен на использование персональных данных на платформе",
|
||||||
"userConsentUrlTitle": "Посмотреть политику конфиденциальности"
|
"userConsentUrlTitle": "Посмотреть политику конфиденциальности",
|
||||||
|
"updateAccountLoading": "Обновление данных аккаунта...",
|
||||||
|
"updateAccountSuccess": "Данные аккаунта обновлены",
|
||||||
|
"updateAccountError": "Не удалось обновить данные аккаунта"
|
||||||
},
|
},
|
||||||
"consentModal": {
|
"consentModal": {
|
||||||
"title": "Перед началом",
|
"title": "Перед началом",
|
||||||
|
|||||||
@@ -128,6 +128,11 @@
|
|||||||
"amount": "Сумма",
|
"amount": "Сумма",
|
||||||
"selectDate": "Выберите дату"
|
"selectDate": "Выберите дату"
|
||||||
},
|
},
|
||||||
|
"formFieldError": {
|
||||||
|
"invalidPhoneNumber": "Пожалуйста, введите действительный номер телефона (должен включать код страны +372)",
|
||||||
|
"invalidPersonalCode": "Пожалуйста, введите действительный персональный код",
|
||||||
|
"stringNonEmpty": "Это поле обязательно"
|
||||||
|
},
|
||||||
"wallet": {
|
"wallet": {
|
||||||
"balance": "Баланс вашего счета MedReport",
|
"balance": "Баланс вашего счета MedReport",
|
||||||
"expiredAt": "Действительно до {{expiredAt}}"
|
"expiredAt": "Действительно до {{expiredAt}}"
|
||||||
|
|||||||
Reference in New Issue
Block a user