feat: use password input (#163)

* feat: use password input

* chore: address pull request feedback

* fix: typo in function name

* fix: deepsource issues

---------

Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
This commit is contained in:
Manuel
2024-03-02 17:46:03 +01:00
committed by GitHub
parent 990be660c5
commit 2a83df3485
5 changed files with 69 additions and 40 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
import { useCallback, useMemo, useState } from "react";
import { clientApi } from "@homarr/api/client";
import { useForm, zodResolver } from "@homarr/form";
@@ -25,10 +25,15 @@ export const UserCreateStepperComponent = () => {
const stepperMax = 4;
const [active, setActive] = useState(0);
const nextStep = () =>
setActive((current) => (current < stepperMax ? current + 1 : current));
const prevStep = () =>
setActive((current) => (current > 0 ? current - 1 : current));
const nextStep = useCallback(
() =>
setActive((current) => (current < stepperMax ? current + 1 : current)),
[setActive],
);
const prevStep = useCallback(
() => setActive((current) => (current > 0 ? current - 1 : current)),
[setActive],
);
const hasNext = active < stepperMax;
const hasPrevious = active > 0;
@@ -52,39 +57,51 @@ export const UserCreateStepperComponent = () => {
const securityForm = useForm({
initialValues: {
password: "",
confirmPassword: "",
},
validate: zodResolver(
z.object({
password: validation.user.password,
}),
z
.object({
password: validation.user.password,
confirmPassword: z.string(),
})
.refine((data) => data.password === data.confirmPassword, {
path: ["confirmPassword"],
message: "Passwords do not match",
}),
),
validateInputOnBlur: true,
validateInputOnChange: true,
});
const allForms = [generalForm, securityForm];
const allForms = useMemo(
() => [generalForm, securityForm],
[generalForm, securityForm],
);
const isCurrentFormValid = allForms[active]
? (allForms[active]!.isValid satisfies () => boolean)
: () => true;
const canNavigateToNextStep = isCurrentFormValid();
const controlledGoToNextStep = async () => {
const controlledGoToNextStep = useCallback(async () => {
if (active + 1 === stepperMax) {
await mutateAsync({
name: generalForm.values.username,
username: generalForm.values.username,
email: generalForm.values.email,
password: securityForm.values.password,
confirmPassword: securityForm.values.confirmPassword,
});
}
nextStep();
};
}, [active, generalForm, mutateAsync, securityForm, nextStep]);
const reset = () => {
const reset = useCallback(() => {
setActive(0);
allForms.forEach((form) => {
form.reset();
});
};
}, [allForms]);
return (
<>
@@ -134,6 +151,12 @@ export const UserCreateStepperComponent = () => {
withAsterisk
{...securityForm.getInputProps("password")}
/>
<PasswordInput
label={t("step.security.field.confirmPassword.label")}
variant="filled"
withAsterisk
{...securityForm.getInputProps("confirmPassword")}
/>
</Stack>
</Card>
</form>

View File

@@ -1,6 +1,6 @@
import { getScopedI18n } from "@homarr/translation/server";
import { UserCreateStepperComponent } from "./_components/stepper.component";
import { UserCreateStepperComponent } from "./_components/create-user-stepper";
export async function generateMetadata() {
const t = await getScopedI18n("management.page.user.create");