Fix error handle

fix pagination issue
change logic for change passsword and profile update
This commit is contained in:
2026-02-10 13:25:50 +07:00
parent 1d3e79c546
commit 5ffdd7454a
26 changed files with 339 additions and 213 deletions

View File

@@ -1,8 +1,9 @@
import { useAppForm } from '@hooks/use-app-form';
import { authClient } from '@lib/auth-client';
import { m } from '@paraglide/messages';
import { KeyIcon } from '@phosphor-icons/react';
import { ChangePassword, ChangePasswordFormSchema } from '@service/user.schema';
import { changePassword } from '@service/profile.api';
import { ChangePassword, changePasswordFormSchema } from '@service/user.schema';
import { useMutation } from '@tanstack/react-query';
import { Card, CardContent, CardHeader, CardTitle } from '@ui/card';
import { Field, FieldGroup } from '@ui/field';
import { toast } from 'sonner';
@@ -14,37 +15,33 @@ const defaultValues: ChangePassword = {
};
const ChangePasswordForm = () => {
const { mutate: changePasswordMutation, isPending } = useMutation({
mutationFn: changePassword,
onSuccess: () => {
form.reset();
toast.success(m.change_password_messages_change_password_success(), {
richColors: true,
});
},
onError: (error: ReturnError) => {
console.error(error);
const code = error.code as Parameters<
typeof m.backend_message
>[0]['code'];
toast.error(m.backend_message({ code }), {
richColors: true,
});
},
});
const form = useAppForm({
defaultValues,
validators: {
onSubmit: ChangePasswordFormSchema,
onChange: ChangePasswordFormSchema,
onSubmit: changePasswordFormSchema,
onChange: changePasswordFormSchema,
},
onSubmit: async ({ value }) => {
await authClient.changePassword(
{
newPassword: value.newPassword,
currentPassword: value.currentPassword,
revokeOtherSessions: true,
},
{
onSuccess: () => {
form.reset();
toast.success(
m.change_password_messages_change_password_success(),
{
richColors: true,
},
);
},
onError: (ctx) => {
console.error(ctx.error.code);
toast.error(m.backend_message({ code: ctx.error.code }), {
richColors: true,
});
},
},
);
changePasswordMutation({ data: value });
},
});
@@ -70,6 +67,7 @@ const ChangePasswordForm = () => {
{(field) => (
<field.TextField
label={m.change_password_form_current_password()}
type="password"
/>
)}
</form.AppField>
@@ -91,7 +89,10 @@ const ChangePasswordForm = () => {
</form.AppField>
<Field>
<form.AppForm>
<form.SubscribeButton label={m.ui_change_password_btn()} />
<form.SubscribeButton
label={m.ui_change_password_btn()}
disabled={isPending}
/>
</form.AppForm>
</Field>
</FieldGroup>

View File

@@ -1,13 +1,13 @@
import { Skeleton } from '@/components/ui/skeleton';
import { updateProfile } from '@/service/profile.api';
import { useAuth } from '@components/auth/auth-provider';
import AvatarUser from '@components/avatar/avatar-user';
import RoleBadge from '@components/avatar/role-badge';
import { useAppForm } from '@hooks/use-app-form';
import { authClient } from '@lib/auth-client';
import { m } from '@paraglide/messages';
import { UserCircleIcon } from '@phosphor-icons/react';
import { uploadProfileImage } from '@service/profile.api';
import { ProfileInput, profileUpdateSchema } from '@service/profile.schema';
import { useQueryClient } from '@tanstack/react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Card, CardContent, CardHeader, CardTitle } from '@ui/card';
import { Field, FieldGroup, FieldLabel } from '@ui/field';
import { Input } from '@ui/input';
@@ -24,6 +24,31 @@ const ProfileForm = () => {
const { data: session, isPending } = useAuth();
const queryClient = useQueryClient();
const { mutate: updateProfileMutation, isPending: isRunning } = useMutation({
mutationFn: updateProfile,
onSuccess: () => {
form.reset();
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
queryClient.refetchQueries({
queryKey: ['auth', 'session'],
});
toast.success(m.profile_messages_update_success(), {
richColors: true,
});
},
onError: (error: ReturnError) => {
console.error(error);
const code = error.code as Parameters<
typeof m.backend_message
>[0]['code'];
toast.error(m.backend_message({ code }), {
richColors: true,
});
},
});
const form = useAppForm({
defaultValues: {
...defaultValues,
@@ -34,55 +59,19 @@ const ProfileForm = () => {
onChange: profileUpdateSchema,
},
onSubmit: async ({ value }) => {
try {
let imageKey;
if (value.image) {
// upload image
const formData = new FormData();
formData.set('file', value.image);
const { imageKey: uploadedKey } = await uploadProfileImage({
data: formData,
});
imageKey = uploadedKey;
}
await authClient.updateUser(
{
name: value.name,
image: imageKey,
},
{
onSuccess: () => {
form.reset();
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
queryClient.refetchQueries({
queryKey: ['auth', 'session'],
});
toast.success(m.profile_messages_update_success(), {
richColors: true,
});
},
onError: (ctx) => {
console.error(ctx.error.code);
toast.error(m.backend_message({ code: ctx.error.code }), {
richColors: true,
});
},
},
);
} catch (error) {
console.error('update load file', error);
toast.error(JSON.stringify(error), {
richColors: true,
});
const formData = new FormData();
formData.set('name', value.name);
if (value.image) {
formData.set('file', value.image);
}
updateProfileMutation({ data: formData });
},
});
if (isPending) return null;
if (!session?.user?.name) return null;
if (isPending || !session?.user?.name) {
return <Skeleton className="h-100 col-span-1" />;
}
return (
<Card className="@container/card col-span-1">
@@ -136,7 +125,10 @@ const ProfileForm = () => {
</Field>
<Field>
<form.AppForm>
<form.SubscribeButton label={m.ui_update_btn()} />
<form.SubscribeButton
label={m.ui_update_btn()}
disabled={isRunning}
/>
</form.AppForm>
</Field>
</FieldGroup>

View File

@@ -13,7 +13,7 @@ import { slugify } from '@utils/helper';
import { toast } from 'sonner';
type EditHouseFormProps = {
data: OrganizationWithMembers;
data: HouseWithMembers;
onSubmit: (open: boolean) => void;
mutateKey: string;
};