fix: Handle existing user when editing profile
This commit is contained in:
@@ -5,10 +5,15 @@ import { Button, Stack, TextInput } from "@mantine/core";
|
|||||||
import type { RouterOutputs } from "@homarr/api";
|
import type { RouterOutputs } from "@homarr/api";
|
||||||
import { clientApi } from "@homarr/api/client";
|
import { clientApi } from "@homarr/api/client";
|
||||||
import { useForm, zodResolver } from "@homarr/form";
|
import { useForm, zodResolver } from "@homarr/form";
|
||||||
|
import {
|
||||||
|
showErrorNotification,
|
||||||
|
showSuccessNotification,
|
||||||
|
} from "@homarr/notifications";
|
||||||
import { useI18n } from "@homarr/translation/client";
|
import { useI18n } from "@homarr/translation/client";
|
||||||
import { validation } from "@homarr/validation";
|
import { validation } from "@homarr/validation";
|
||||||
|
|
||||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||||
|
import { ErrorDisplay } from "~/components/utils";
|
||||||
|
|
||||||
interface ProfileAccordionProps {
|
interface ProfileAccordionProps {
|
||||||
user: NonNullable<RouterOutputs["user"]["getById"]>;
|
user: NonNullable<RouterOutputs["user"]["getById"]>;
|
||||||
@@ -16,11 +21,30 @@ interface ProfileAccordionProps {
|
|||||||
|
|
||||||
export const ProfileAccordion = ({ user }: ProfileAccordionProps) => {
|
export const ProfileAccordion = ({ user }: ProfileAccordionProps) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const { mutate, isPending } = clientApi.user.editProfile.useMutation({
|
const { mutate, isPending, isError, error } =
|
||||||
onSettled: async () => {
|
clientApi.user.editProfile.useMutation({
|
||||||
await revalidatePathAction("/manage/users");
|
onError(error) {
|
||||||
},
|
showErrorNotification({
|
||||||
});
|
title: t(
|
||||||
|
"management.page.user.edit.section.profile.editProfile.title",
|
||||||
|
),
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
showSuccessNotification({
|
||||||
|
title: t(
|
||||||
|
"management.page.user.edit.section.profile.editProfile.title",
|
||||||
|
),
|
||||||
|
message: t(
|
||||||
|
"management.page.user.edit.section.profile.editProfile.message.profileUpdated",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSettled: async () => {
|
||||||
|
await revalidatePathAction("/manage/users");
|
||||||
|
},
|
||||||
|
});
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
name: user.name ?? "",
|
name: user.name ?? "",
|
||||||
@@ -41,6 +65,7 @@ export const ProfileAccordion = ({ user }: ProfileAccordionProps) => {
|
|||||||
return (
|
return (
|
||||||
<form onSubmit={form.onSubmit(handleSubmit)}>
|
<form onSubmit={form.onSubmit(handleSubmit)}>
|
||||||
<Stack>
|
<Stack>
|
||||||
|
<ErrorDisplay hidden={!isError} message={error?.message} />
|
||||||
<TextInput
|
<TextInput
|
||||||
label={t("user.field.username.label")}
|
label={t("user.field.username.label")}
|
||||||
withAsterisk
|
withAsterisk
|
||||||
|
|||||||
@@ -90,7 +90,16 @@ export const userRouter = createTRPCRouter({
|
|||||||
.from(users)
|
.from(users)
|
||||||
.where(eq(users.id, input.userId))
|
.where(eq(users.id, input.userId))
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
const existingUser = await ctx.db.query.users.findFirst({
|
||||||
|
where: eq(users.name, input.form.name),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingUser !== undefined) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "FORBIDDEN",
|
||||||
|
message: `User ${input.form.name} already exists`,
|
||||||
|
});
|
||||||
|
}
|
||||||
const emailDirty =
|
const emailDirty =
|
||||||
input.form.email && user[0]?.email !== input.form.email;
|
input.form.email && user[0]?.email !== input.form.email;
|
||||||
await ctx.db
|
await ctx.db
|
||||||
|
|||||||
Reference in New Issue
Block a user