Fix profile accordion error display
This commit is contained in:
@@ -13,7 +13,6 @@ 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"]>;
|
||||||
@@ -21,7 +20,7 @@ interface ProfileAccordionProps {
|
|||||||
|
|
||||||
export const ProfileAccordion = ({ user }: ProfileAccordionProps) => {
|
export const ProfileAccordion = ({ user }: ProfileAccordionProps) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const { mutate, isPending, isError, error } =
|
const { mutate, isPending } =
|
||||||
clientApi.user.editProfile.useMutation({
|
clientApi.user.editProfile.useMutation({
|
||||||
onError(error) {
|
onError(error) {
|
||||||
showErrorNotification({
|
showErrorNotification({
|
||||||
@@ -65,7 +64,6 @@ 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
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ import { useCallback, useMemo, useState } from "react";
|
|||||||
|
|
||||||
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 } from "@homarr/notifications";
|
||||||
import { useScopedI18n } from "@homarr/translation/client";
|
import { useScopedI18n } from "@homarr/translation/client";
|
||||||
import { validation, z } from "@homarr/validation";
|
import { validation, z } from "@homarr/validation";
|
||||||
|
|
||||||
import { ErrorDisplay } from "~/components/utils";
|
|
||||||
import { StepperNavigationComponent } from "./stepper-navigation.component";
|
import { StepperNavigationComponent } from "./stepper-navigation.component";
|
||||||
|
|
||||||
export const UserCreateStepperComponent = () => {
|
export const UserCreateStepperComponent = () => {
|
||||||
@@ -39,8 +39,16 @@ export const UserCreateStepperComponent = () => {
|
|||||||
const hasNext = active < stepperMax;
|
const hasNext = active < stepperMax;
|
||||||
const hasPrevious = active > 0;
|
const hasPrevious = active > 0;
|
||||||
|
|
||||||
const { mutateAsync, isPending, isError, error } =
|
const { mutateAsync, isPending } = clientApi.user.create.useMutation({
|
||||||
clientApi.user.create.useMutation();
|
onError(error) {
|
||||||
|
showErrorNotification({
|
||||||
|
autoClose: false,
|
||||||
|
id: "create-user-error",
|
||||||
|
title: t("step.error.title"),
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const generalForm = useForm({
|
const generalForm = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
@@ -109,7 +117,6 @@ export const UserCreateStepperComponent = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title mb="md">{t("title")}</Title>
|
<Title mb="md">{t("title")}</Title>
|
||||||
<ErrorDisplay hidden={!isError} message={error?.message} my="lg" />
|
|
||||||
<Stepper
|
<Stepper
|
||||||
active={active}
|
active={active}
|
||||||
onStepClick={setActive}
|
onStepClick={setActive}
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ export const userRouter = createTRPCRouter({
|
|||||||
.input(validation.user.create)
|
.input(validation.user.create)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const user = await ctx.db.query.users.findFirst({
|
const user = await ctx.db.query.users.findFirst({
|
||||||
where: eq(users.name, input.username),
|
where: eq(users.name, input.username.toLowerCase()),
|
||||||
});
|
});
|
||||||
if (user !== undefined) {
|
if (user !== undefined) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "FORBIDDEN",
|
code: "CONFLICT",
|
||||||
message: "User already exists",
|
message: "User already exists",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -91,12 +91,12 @@ export const userRouter = createTRPCRouter({
|
|||||||
.where(eq(users.id, input.userId))
|
.where(eq(users.id, input.userId))
|
||||||
.limit(1);
|
.limit(1);
|
||||||
const existingUser = await ctx.db.query.users.findFirst({
|
const existingUser = await ctx.db.query.users.findFirst({
|
||||||
where: eq(users.name, input.form.name),
|
where: eq(users.name, input.form.name.toLowerCase()),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (existingUser !== undefined) {
|
if (existingUser !== undefined) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "FORBIDDEN",
|
code: "CONFLICT",
|
||||||
message: `User ${input.form.name} already exists`,
|
message: `User ${input.form.name} already exists`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,14 @@ import type { NotificationData } from "@mantine/notifications";
|
|||||||
import { notifications } from "@mantine/notifications";
|
import { notifications } from "@mantine/notifications";
|
||||||
import { IconCheck, IconX } from "@tabler/icons-react";
|
import { IconCheck, IconX } from "@tabler/icons-react";
|
||||||
|
|
||||||
type CommonNotificationProps = Pick<NotificationData, "title" | "message">;
|
export const showSuccessNotification = (props: NotificationData) =>
|
||||||
|
|
||||||
export const showSuccessNotification = (props: CommonNotificationProps) =>
|
|
||||||
notifications.show({
|
notifications.show({
|
||||||
...props,
|
...props,
|
||||||
color: "teal",
|
color: "teal",
|
||||||
icon: <IconCheck size={20} />,
|
icon: <IconCheck size={20} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const showErrorNotification = (props: CommonNotificationProps) =>
|
export const showErrorNotification = (props: NotificationData) =>
|
||||||
notifications.show({
|
notifications.show({
|
||||||
...props,
|
...props,
|
||||||
color: "red",
|
color: "red",
|
||||||
|
|||||||
@@ -1108,6 +1108,9 @@ export default {
|
|||||||
completed: {
|
completed: {
|
||||||
title: "User created",
|
title: "User created",
|
||||||
},
|
},
|
||||||
|
error: {
|
||||||
|
title: "User creation failed",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
createAnother: "Create another user",
|
createAnother: "Create another user",
|
||||||
|
|||||||
Reference in New Issue
Block a user