Added User List table
This commit is contained in:
193
src/components/form/admin-ban-user-form.tsx
Normal file
193
src/components/form/admin-ban-user-form.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
import { m } from '@/paraglide/messages';
|
||||
import { usersQueries } from '@/service/queries';
|
||||
import { banUser } from '@/service/user.api';
|
||||
import { userBanSchema } from '@/service/user.schema';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import { WarningIcon } from '@phosphor-icons/react';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { UserWithRole } from 'better-auth/plugins';
|
||||
import { toast } from 'sonner';
|
||||
import { Alert, AlertDescription, AlertTitle } from '../ui/alert';
|
||||
import { Button } from '../ui/button';
|
||||
import { DialogClose, DialogFooter } from '../ui/dialog';
|
||||
import { Field, FieldError, FieldGroup, FieldLabel } from '../ui/field';
|
||||
import { Input } from '../ui/input';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '../ui/select';
|
||||
import { Textarea } from '../ui/textarea';
|
||||
|
||||
type FormProps = {
|
||||
data: UserWithRole;
|
||||
onSubmit: (open: boolean) => void;
|
||||
};
|
||||
|
||||
const BanUserForm = ({ data, onSubmit }: FormProps) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const banUserMutation = useMutation({
|
||||
mutationFn: banUser,
|
||||
onSuccess: () => {
|
||||
queryClient.refetchQueries({
|
||||
queryKey: usersQueries.all,
|
||||
});
|
||||
onSubmit(false);
|
||||
toast.success(m.users_page_message_banned_success({ name: data.name }), {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
(m[`backend_${error.code}` as keyof typeof m] as () => string)(),
|
||||
{ richColors: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
id: data.id,
|
||||
banReason: '',
|
||||
banExp: 0,
|
||||
},
|
||||
validators: {
|
||||
onChange: userBanSchema,
|
||||
onSubmit: userBanSchema,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
banUserMutation.mutate({ data: value });
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
id="admin-ban-user-form"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<FieldGroup>
|
||||
<Alert variant="destructive">
|
||||
<WarningIcon />
|
||||
<AlertTitle>
|
||||
{m.profile_form_name()}: {data.name}
|
||||
</AlertTitle>
|
||||
<AlertDescription className="sr-only">adá</AlertDescription>
|
||||
</Alert>
|
||||
<form.Field
|
||||
name="id"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<Input
|
||||
type="hidden"
|
||||
name={field.name}
|
||||
id={field.name}
|
||||
value={field.state.value}
|
||||
aria-invalid={isInvalid}
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="banReason"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid} className="col-span-2">
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
{m.users_page_ui_form_ban_reason()}:
|
||||
</FieldLabel>
|
||||
<Textarea
|
||||
id={field.name}
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
aria-invalid={isInvalid}
|
||||
rows={4}
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="banExp"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
{m.users_page_ui_form_ban_exp()}
|
||||
</FieldLabel>
|
||||
<Select
|
||||
name={field.name}
|
||||
value={String(field.state.value)}
|
||||
onValueChange={(value) => field.handleChange(Number(value))}
|
||||
>
|
||||
<SelectTrigger aria-invalid={isInvalid}>
|
||||
<SelectValue
|
||||
placeholder={m.users_page_ui_select_placeholder_ban_exp()}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">
|
||||
{m.exp_time({ time: '1d' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="7">
|
||||
{m.exp_time({ time: '7d' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="15">
|
||||
{m.exp_time({ time: '15d' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="30">
|
||||
{m.exp_time({ time: '1m' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="180">
|
||||
{m.exp_time({ time: '6m' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="365">
|
||||
{m.exp_time({ time: '1y' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="99999">
|
||||
{m.exp_time({ time: '0' })}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Field>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="destructive" type="button">
|
||||
{m.ui_cancel_btn()}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit" variant="outline">
|
||||
{m.ui_ban_btn()}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default BanUserForm;
|
||||
124
src/components/form/admin-set-password-form.tsx
Normal file
124
src/components/form/admin-set-password-form.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import { m } from '@/paraglide/messages';
|
||||
import { usersQueries } from '@/service/queries';
|
||||
import { setUserPassword } from '@/service/user.api';
|
||||
import { userSetPasswordSchema } from '@/service/user.schema';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { UserWithRole } from 'better-auth/plugins';
|
||||
import { toast } from 'sonner';
|
||||
import { Button } from '../ui/button';
|
||||
import { DialogClose, DialogFooter } from '../ui/dialog';
|
||||
import { Field, FieldError, FieldGroup, FieldLabel } from '../ui/field';
|
||||
import { Input } from '../ui/input';
|
||||
|
||||
type FormProps = {
|
||||
data: UserWithRole;
|
||||
onSubmit: (open: boolean) => void;
|
||||
};
|
||||
|
||||
const AdminSetPasswordForm = ({ data, onSubmit }: FormProps) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const setUserPasswordMutation = useMutation({
|
||||
mutationFn: setUserPassword,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [...usersQueries.all, 'list'],
|
||||
});
|
||||
onSubmit(false);
|
||||
toast.success(m.users_page_message_set_password_success(), {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
(m[`backend_${error.code}` as keyof typeof m] as () => string)(),
|
||||
{ richColors: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
id: data.id,
|
||||
password: '',
|
||||
},
|
||||
validators: {
|
||||
onSubmit: userSetPasswordSchema,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setUserPasswordMutation.mutate({ data: value });
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
id="admin-set-password-form"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<FieldGroup>
|
||||
<form.Field
|
||||
name="id"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<Input
|
||||
type="hidden"
|
||||
name={field.name}
|
||||
id={field.name}
|
||||
value={field.state.value}
|
||||
aria-invalid={isInvalid}
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="password"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
{m.change_password_form_new_password()}
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id={field.name}
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
aria-invalid={isInvalid}
|
||||
type="password"
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Field>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
{m.ui_cancel_btn()}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit">{m.ui_save_btn()}</Button>
|
||||
</DialogFooter>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminSetPasswordForm;
|
||||
146
src/components/form/admin-set-user-role-form.tsx
Normal file
146
src/components/form/admin-set-user-role-form.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import { m } from '@/paraglide/messages';
|
||||
import { usersQueries } from '@/service/queries';
|
||||
import { setUserRole } from '@/service/user.api';
|
||||
import { RoleEnum, userUpdateRoleSchema } from '@/service/user.schema';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { UserWithRole } from 'better-auth/plugins';
|
||||
import { toast } from 'sonner';
|
||||
import { Button } from '../ui/button';
|
||||
import { DialogClose, DialogFooter } from '../ui/dialog';
|
||||
import { Field, FieldError, FieldGroup, FieldLabel } from '../ui/field';
|
||||
import { Input } from '../ui/input';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '../ui/select';
|
||||
|
||||
type SetRoleFormProps = {
|
||||
data: UserWithRole;
|
||||
onSubmit: (open: boolean) => void;
|
||||
};
|
||||
|
||||
const AdminSetUserRoleForm = ({ data, onSubmit }: SetRoleFormProps) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const defaultFormValues = {
|
||||
id: data.id,
|
||||
role: data.role,
|
||||
};
|
||||
|
||||
const updateRoleMutation = useMutation({
|
||||
mutationFn: setUserRole,
|
||||
onSuccess: () => {
|
||||
queryClient.refetchQueries({
|
||||
queryKey: usersQueries.all,
|
||||
});
|
||||
onSubmit(false);
|
||||
toast.success(m.users_page_message_set_role_success(), {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
(m[`backend_${error.code}` as keyof typeof m] as () => string)(),
|
||||
{ richColors: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: userUpdateRoleSchema.parse(defaultFormValues),
|
||||
validators: {
|
||||
onChange: userUpdateRoleSchema,
|
||||
onSubmit: userUpdateRoleSchema,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
updateRoleMutation.mutate({ data: value });
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
id="admin-set-user-role-form"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<FieldGroup>
|
||||
<form.Field
|
||||
name="id"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<Input
|
||||
type="hidden"
|
||||
name={field.name}
|
||||
id={field.name}
|
||||
value={field.state.value}
|
||||
aria-invalid={isInvalid}
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="role"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
{m.profile_form_role()}
|
||||
</FieldLabel>
|
||||
<Select
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onValueChange={(value) =>
|
||||
field.handleChange(RoleEnum.parse(value))
|
||||
}
|
||||
>
|
||||
<SelectTrigger aria-invalid={isInvalid}>
|
||||
<SelectValue
|
||||
placeholder={m.users_page_ui_select_placeholder_language()}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="admin">
|
||||
{m.role_tags({ role: 'admin' })}
|
||||
</SelectItem>
|
||||
<SelectItem value="user">
|
||||
{m.role_tags({ role: 'user' })}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Field>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
{m.ui_cancel_btn()}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit">{m.ui_save_btn()}</Button>
|
||||
</DialogFooter>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminSetUserRoleForm;
|
||||
123
src/components/form/admin-update-user-info-form.tsx
Normal file
123
src/components/form/admin-update-user-info-form.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import { m } from '@/paraglide/messages';
|
||||
import { usersQueries } from '@/service/queries';
|
||||
import { updateUserInformation } from '@/service/user.api';
|
||||
import { userUpdateInfoSchema } from '@/service/user.schema';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { UserWithRole } from 'better-auth/plugins';
|
||||
import { toast } from 'sonner';
|
||||
import { Button } from '../ui/button';
|
||||
import { DialogClose, DialogFooter } from '../ui/dialog';
|
||||
import { Field, FieldError, FieldGroup, FieldLabel } from '../ui/field';
|
||||
import { Input } from '../ui/input';
|
||||
|
||||
type UpdateUserFormProps = {
|
||||
data: UserWithRole;
|
||||
onSubmit: (open: boolean) => void;
|
||||
};
|
||||
|
||||
const AdminUpdateUserInfoForm = ({ data, onSubmit }: UpdateUserFormProps) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const updateUserMutation = useMutation({
|
||||
mutationFn: updateUserInformation,
|
||||
onSuccess: () => {
|
||||
queryClient.refetchQueries({
|
||||
queryKey: usersQueries.all,
|
||||
});
|
||||
onSubmit(false);
|
||||
toast.success(m.users_page_message_update_info_success(), {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
(m[`backend_${error.code}` as keyof typeof m] as () => string)(),
|
||||
{ richColors: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
},
|
||||
validators: {
|
||||
onChange: userUpdateInfoSchema,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
updateUserMutation.mutate({ data: value });
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
id="admin-update-user-info-form"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<FieldGroup>
|
||||
<form.Field
|
||||
name="id"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<Input
|
||||
type="hidden"
|
||||
name={field.name}
|
||||
id={field.name}
|
||||
value={field.state.value}
|
||||
aria-invalid={isInvalid}
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="name"
|
||||
children={(field) => {
|
||||
const isInvalid =
|
||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
||||
return (
|
||||
<Field data-invalid={isInvalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
{m.profile_form_name()}
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id={field.name}
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
aria-invalid={isInvalid}
|
||||
type="text"
|
||||
/>
|
||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
||||
</Field>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Field>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
{m.ui_cancel_btn()}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit">{m.ui_save_btn()}</Button>
|
||||
</DialogFooter>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminUpdateUserInfoForm;
|
||||
@@ -70,7 +70,7 @@ const ChangePasswordForm = () => {
|
||||
);
|
||||
},
|
||||
onError: (ctx) => {
|
||||
console.log(ctx.error.code);
|
||||
console.error(ctx.error.code);
|
||||
toast.error(
|
||||
(
|
||||
m[`backend_${ctx.error.code}` as keyof typeof m] as () => string
|
||||
|
||||
@@ -66,6 +66,7 @@ const ProfileForm = () => {
|
||||
});
|
||||
},
|
||||
onError: (ctx) => {
|
||||
console.error(ctx.error.code);
|
||||
toast.error(
|
||||
(
|
||||
m[
|
||||
@@ -79,7 +80,9 @@ const ProfileForm = () => {
|
||||
},
|
||||
},
|
||||
);
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
console.error('update load file', error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { m } from '@/paraglide/messages';
|
||||
import { settingQueries } from '@/service/queries';
|
||||
import { updateAdminSettings } from '@/service/setting.api';
|
||||
import { settingSchema, SettingsInput } from '@/service/setting.schema';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import { GearIcon } from '@phosphor-icons/react';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
@@ -32,6 +33,13 @@ const SettingsForm = () => {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
(m[`backend_${error.code}` as keyof typeof m] as () => string)(),
|
||||
{ richColors: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
|
||||
@@ -51,6 +51,7 @@ const SignInForm = () => {
|
||||
});
|
||||
},
|
||||
onError: (ctx) => {
|
||||
console.error(ctx.error.code);
|
||||
toast.error(
|
||||
(
|
||||
m[`backend_${ctx.error.code}` as keyof typeof m] as () => string
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Locale, setLocale } from '@/paraglide/runtime';
|
||||
import { settingQueries } from '@/service/queries';
|
||||
import { updateUserSettings } from '@/service/setting.api';
|
||||
import { UserSettingInput, userSettingSchema } from '@/service/setting.schema';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import { GearIcon } from '@phosphor-icons/react';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
@@ -40,6 +41,13 @@ const UserSettingsForm = () => {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
(m[`backend_${error.code}` as keyof typeof m] as () => string)(),
|
||||
{ richColors: true },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
|
||||
Reference in New Issue
Block a user