show less update-account fields on email login

This commit is contained in:
2025-09-10 06:33:56 +03:00
parent 312027b9ed
commit e3cdba6a7c
4 changed files with 127 additions and 90 deletions

View File

@@ -19,19 +19,21 @@ import {
import { Input } from '@kit/ui/input'; import { Input } from '@kit/ui/input';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import { UpdateAccountSchema } 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 { z } from 'zod';
type UpdateAccountFormValues = z.infer<typeof UpdateAccountSchema>; type UpdateAccountFormValues = z.infer<typeof UpdateAccountSchemaClient>;
export function UpdateAccountForm({ export function UpdateAccountForm({
defaultValues, defaultValues,
isEmailUser,
}: { }: {
defaultValues: UpdateAccountFormValues, defaultValues: UpdateAccountFormValues,
isEmailUser: boolean,
}) { }) {
const form = useForm({ const form = useForm({
resolver: zodResolver(UpdateAccountSchema), resolver: zodResolver(UpdateAccountSchemaClient),
mode: 'onChange', mode: 'onChange',
defaultValues, defaultValues,
}); });
@@ -44,18 +46,18 @@ export function UpdateAccountForm({
const hasEmail = !!email; const hasEmail = !!email;
const hasWeight = !!weight; const hasWeight = !!weight;
const hasHeight = !!height; const hasHeight = !!height;
const hasUserConsent = !!userConsent;
const onUpdateAccountOptions = async (values: UpdateAccountFormValues) => const onUpdateAccountOptions = async (values: UpdateAccountFormValues) =>
onUpdateAccount({ onUpdateAccount({
...values, firstName: hasFirstName ? firstName : values.firstName,
...(hasFirstName && { firstName }), lastName: hasLastName ? lastName : values.lastName,
...(hasLastName && { lastName }), personalCode: hasPersonalCode ? personalCode : values.personalCode,
...(hasPersonalCode && { personalCode }), email: hasEmail ? email : values.email,
...(hasEmail && { email }), phone: values.phone,
...(hasWeight && { weight: values.weight ?? weight }), weight: (hasWeight ? weight : values.weight) as number,
...(hasHeight && { height: values.height ?? height }), height: (hasHeight ? height : values.height) as number,
...(hasUserConsent && { userConsent: values.userConsent ?? userConsent }), userConsent: values.userConsent ?? userConsent,
city: values.city,
}); });
return ( return (
@@ -66,14 +68,14 @@ export function UpdateAccountForm({
> >
<FormField <FormField
name="firstName" name="firstName"
disabled={hasFirstName} disabled={hasFirstName && !isEmailUser}
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
<Trans i18nKey={'common:formField:firstName'} /> <Trans i18nKey={'common:formField:firstName'} />
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<Input {...field} /> <Input {...field} autoFocus={!hasFirstName} />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
@@ -82,14 +84,14 @@ export function UpdateAccountForm({
<FormField <FormField
name="lastName" name="lastName"
disabled={hasLastName} disabled={hasLastName && !isEmailUser}
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
<Trans i18nKey={'common:formField:lastName'} /> <Trans i18nKey={'common:formField:lastName'} />
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<Input {...field} /> <Input {...field} autoFocus={hasFirstName && !hasLastName} />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
@@ -98,7 +100,7 @@ export function UpdateAccountForm({
<FormField <FormField
name="personalCode" name="personalCode"
disabled={hasPersonalCode} disabled={hasPersonalCode && !isEmailUser}
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
@@ -143,72 +145,76 @@ export function UpdateAccountForm({
)} )}
/> />
<FormField {!isEmailUser && (
name="city" <>
render={({ field }) => ( <FormField
<FormItem> name="city"
<FormLabel> render={({ field }) => (
<Trans i18nKey={'common:formField:city'} /> <FormItem>
</FormLabel> <FormLabel>
<FormControl> <Trans i18nKey={'common:formField:city'} />
<Input {...field} /> </FormLabel>
</FormControl> <FormControl>
<FormMessage /> <Input {...field} />
</FormItem> </FormControl>
)} <FormMessage />
/> </FormItem>
)}
/>
<div className="flex flex-row justify-between gap-4"> <div className="flex flex-row justify-between gap-4">
<FormField <FormField
name="weight" name="weight"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
<Trans i18nKey={'common:formField:weight'} /> <Trans i18nKey={'common:formField:weight'} />
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<Input <Input
type="number" type="number"
placeholder="kg" placeholder="kg"
{...field} {...field}
value={field.value ?? ''} value={field.value ?? ''}
onChange={(e) => onChange={(e) =>
field.onChange( field.onChange(
e.target.value === '' ? null : Number(e.target.value), e.target.value === '' ? null : Number(e.target.value),
) )
} }
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
/> />
<FormField <FormField
name="height" name="height"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
<Trans i18nKey={'common:formField:height'} /> <Trans i18nKey={'common:formField:height'} />
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<Input <Input
placeholder="cm" placeholder="cm"
type="number" type="number"
{...field} {...field}
value={field.value ?? ''} value={field.value ?? ''}
onChange={(e) => onChange={(e) =>
field.onChange( field.onChange(
e.target.value === '' ? null : Number(e.target.value), e.target.value === '' ? null : Number(e.target.value),
) )
} }
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
/> />
</div> </div>
</>
)}
<FormField <FormField
name="userConsent" name="userConsent"

View File

@@ -1,7 +1,8 @@
import { z } from 'zod'; import { z } from 'zod';
import Isikukood from 'isikukood';
import parsePhoneNumber from 'libphonenumber-js/min'; import parsePhoneNumber from 'libphonenumber-js/min';
export const UpdateAccountSchema = z.object({ const updateAccountSchema = {
firstName: z firstName: z
.string({ .string({
error: 'First name is required', error: 'First name is required',
@@ -12,11 +13,18 @@ export const UpdateAccountSchema = z.object({
error: 'Last name is required', error: 'Last name is required',
}) })
.nonempty(), .nonempty(),
personalCode: z personalCode: z.string().refine(
.string({ (val) => {
error: 'Personal code is required', try {
}) return new Isikukood(val).validate();
.nonempty(), } catch {
return false;
}
},
{
message: 'common:formFieldError.invalidPersonalCode',
},
),
email: z.string().email({ email: z.string().email({
message: 'Email is required', message: 'Email is required',
}), }),
@@ -59,4 +67,26 @@ export const UpdateAccountSchema = z.object({
userConsent: z.boolean().refine((val) => val === true, { userConsent: z.boolean().refine((val) => val === true, {
message: 'Must be true', message: 'Must be true',
}), }),
} as const;
export const UpdateAccountSchemaServer = z.object({
firstName: updateAccountSchema.firstName,
lastName: updateAccountSchema.lastName,
personalCode: updateAccountSchema.personalCode,
email: updateAccountSchema.email,
phone: updateAccountSchema.phone,
city: updateAccountSchema.city,
weight: updateAccountSchema.weight,
height: updateAccountSchema.height,
userConsent: updateAccountSchema.userConsent,
});
export const UpdateAccountSchemaClient = z.object({
firstName: updateAccountSchema.firstName,
lastName: updateAccountSchema.lastName,
personalCode: updateAccountSchema.personalCode,
email: updateAccountSchema.email,
phone: updateAccountSchema.phone,
city: updateAccountSchema.city,
weight: updateAccountSchema.weight.gt(-1).gte(0).nullable(),
height: updateAccountSchema.height.gt(-1).gte(0).nullable(),
userConsent: updateAccountSchema.userConsent,
}); });

View File

@@ -10,7 +10,7 @@ import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { pathsConfig } from '@kit/shared/config'; import { pathsConfig } from '@kit/shared/config';
import { UpdateAccountSchema } from '../schemas/update-account.schema'; import { UpdateAccountSchemaServer } from '../schemas/update-account.schema';
export const onUpdateAccount = enhanceAction( export const onUpdateAccount = enhanceAction(
async (params: AccountSubmitData) => { async (params: AccountSubmitData) => {
@@ -47,6 +47,6 @@ export const onUpdateAccount = enhanceAction(
} }
}, },
{ {
schema: UpdateAccountSchema, schema: UpdateAccountSchemaServer,
}, },
); );

View File

@@ -17,6 +17,7 @@ async function UpdateAccount() {
const { account, user } = await loadCurrentUserAccount(); const { account, user } = await loadCurrentUserAccount();
const isKeycloakUser = user?.app_metadata?.provider === 'keycloak'; const isKeycloakUser = user?.app_metadata?.provider === 'keycloak';
const isEmailUser = user?.app_metadata?.provider === 'email';
if (!user) { if (!user) {
redirect(pathsConfig.auth.signIn); redirect(pathsConfig.auth.signIn);
@@ -50,7 +51,7 @@ async function UpdateAccount() {
<p className="text-muted-foreground pt-1 text-sm"> <p className="text-muted-foreground pt-1 text-sm">
<Trans i18nKey={'account:updateAccount:description'} /> <Trans i18nKey={'account:updateAccount:description'} />
</p> </p>
<UpdateAccountForm defaultValues={defaultValues} /> <UpdateAccountForm defaultValues={defaultValues} isEmailUser={isEmailUser} />
</div> </div>
<div className="hidden w-1/2 min-w-[460px] bg-[url(/assets/med-report-logo-big.png)] bg-cover bg-center bg-no-repeat md:block"></div> <div className="hidden w-1/2 min-w-[460px] bg-[url(/assets/med-report-logo-big.png)] bg-cover bg-center bg-no-repeat md:block"></div>
</div> </div>