feat: add change password form (#199)

This commit is contained in:
Manuel
2024-03-06 21:20:41 +01:00
committed by GitHub
parent c0401702f0
commit beb7defd32
6 changed files with 117 additions and 8 deletions

View File

@@ -1,15 +1,13 @@
"use client";
import React from "react";
import { useRouter } from "next/router";
import { useRouter } from "next/navigation";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useScopedI18n } from "@homarr/translation/client";
import { Button, Divider, Group, Stack, Text } from "@homarr/ui";
import { revalidatePathAction } from "~/app/revalidatePathAction";
interface DangerZoneAccordionProps {
user: NonNullable<RouterOutputs["user"]["getById"]>;
}
@@ -19,9 +17,8 @@ export const DangerZoneAccordion = ({ user }: DangerZoneAccordionProps) => {
const router = useRouter();
const { mutateAsync: mutateUserDeletionAsync } =
clientApi.user.delete.useMutation({
onSettled: async () => {
await router.push("/manage/users");
await revalidatePathAction("/manage/users");
onSettled: () => {
router.push("/manage/users");
},
});

View File

@@ -0,0 +1,80 @@
"use client";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useForm, zodResolver } from "@homarr/form";
import { showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { Button, PasswordInput, Stack, Title } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { revalidatePathAction } from "~/app/revalidatePathAction";
interface SecurityAccordionComponentProps {
user: NonNullable<RouterOutputs["user"]["getById"]>;
}
export const SecurityAccordionComponent = ({
user,
}: SecurityAccordionComponentProps) => {
return (
<Stack>
<ChangePasswordForm user={user} />
</Stack>
);
};
const ChangePasswordForm = ({
user,
}: {
user: NonNullable<RouterOutputs["user"]["getById"]>;
}) => {
const t = useI18n();
const { mutate, isPending } = clientApi.user.changePassword.useMutation({
onSettled: async () => {
await revalidatePathAction(`/manage/users/${user.id}`);
showSuccessNotification({
title: t(
"management.page.user.edit.section.security.changePassword.message.passwordUpdated",
),
message: "",
});
},
});
const form = useForm({
initialValues: {
userId: user.id,
password: "",
},
validate: zodResolver(validation.user.changePassword),
validateInputOnBlur: true,
validateInputOnChange: true,
});
const handleSubmit = () => {
mutate(form.values);
};
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack>
<Stack gap={0}>
<Title order={5}>
{t(
"management.page.user.edit.section.security.changePassword.title",
)}
</Title>
<PasswordInput
label={t(
"management.page.user.edit.section.security.changePassword.form.password.label",
)}
{...form.getInputProps("password")}
/>
</Stack>
<Button loading={isPending} type="submit" disabled={!form.isValid()}>
{t("common.action.confirm")}
</Button>
</Stack>
</form>
);
};

View File

@@ -20,6 +20,7 @@ import {
import { api } from "~/trpc/server";
import { DangerZoneAccordion } from "./_components/dangerZone.accordion";
import { ProfileAccordion } from "./_components/profile.accordion";
import { SecurityAccordionComponent } from "./_components/security.accordion";
interface Props {
params: {
@@ -80,12 +81,14 @@ export default async function EditUserPage({ params }: Props) {
{t("section.security.title")}
</Text>
</AccordionControl>
<AccordionPanel></AccordionPanel>
<AccordionPanel>
<SecurityAccordionComponent user={user} />
</AccordionPanel>
</AccordionItem>
<AccordionItem
styles={{
item: {
"--__item-border-color": "rgba(248,81,73,0.4)",
borderColor: "rgba(248,81,73,0.4)",
borderWidth: 4,
},
}}