Skip to content

Commit

Permalink
Refactor changepassword and changeemail
Browse files Browse the repository at this point in the history
  • Loading branch information
nekiro committed Nov 28, 2024
1 parent a187398 commit 1b425bc
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 122 deletions.
74 changes: 50 additions & 24 deletions src/pages/account/changeemail.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,72 @@
import React, { useState } from "react";
import Panel from "../../components/Panel";
import FormWrapper, { FormButton, FormField } from "../../components/FormWrapper";
import { fetchApi, FetchResult } from "../../lib/request";
import { withSessionSsr } from "../../lib/session";
import { changeEmailSchema } from "../../schemas/ChangeEmail";

const fields: FormField[] = [
import React from "react";
import Panel from "@component/Panel";
import { withSessionSsr } from "@lib/session";
import { trpc } from "@util/trpc";
import { useForm, SubmitHandler } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useFormFeedback } from "@hook/useFormFeedback";
import { Container, VStack, Wrap } from "@chakra-ui/react";
import TextInput from "@component/TextInput";
import Button from "@component/Button";
import { FormField } from "@component/FormField";

const fields = [
{
type: "email",
name: "newEmail",
label: { text: "E-mail Address" },
label: "E-mail Address",
},
{
type: "password",
name: "password",
label: { text: "Password" },
label: "Password",
},
];

const buttons: FormButton[] = [
{ type: "submit", btnColorType: "primary", value: "Submit" },
{ href: "/account", value: "Back" },
];
const schema = z.object({
newEmail: z.string().email({ message: "Invalid email address" }),
password: z.string().min(6, { message: "Password must be at least 6 characters long" }),
});

export default function ChangeEmail() {
const [response, setResponse] = useState<FetchResult | undefined>(undefined);
const {
register,
handleSubmit,
reset,
formState: { errors, isValid, isSubmitting },
} = useForm<z.infer<typeof schema>>({
resolver: zodResolver(schema),
});
const { handleResponse, showResponse } = useFormFeedback();
const changeEmail = trpc.account.changeEmail.useMutation();

const onSubmit = async (values: any, { resetForm }: any) => {
const response = await fetchApi("POST", "/api/account/changeemail", {
data: {
email: values.newEmail,
password: values.password,
},
const onSubmit: SubmitHandler<z.infer<typeof schema>> = async ({ newEmail, password }) => {
handleResponse(async () => {
await changeEmail.mutateAsync({ newEmail, password });
showResponse("Email changed.", "success");
});

setResponse(response);
resetForm();
reset();
};

return (
<Panel header="Change Email">
<FormWrapper validationSchema={changeEmailSchema} onSubmit={onSubmit} fields={fields} buttons={buttons} response={response} />
<form onSubmit={handleSubmit(onSubmit)}>
<Container alignContent={"center"} padding={2}>
<VStack spacing={5}>
{fields.map((field) => (
<FormField key={field.name} error={(errors as any)[field.name]?.message} name={field.name} label={field.label}>
<TextInput type={field.type} {...register(field.name as any)} />
</FormField>
))}
<Wrap spacing={2} padding="10px">
<Button isLoading={isSubmitting} isActive={!isValid} loadingText="Submitting" type="submit" value="Submit" btnColorType="primary" />
<Button value="Back" btnColorType="danger" href="/account" />
</Wrap>
</VStack>
</Container>
</form>
</Panel>
);
}
Expand Down
85 changes: 60 additions & 25 deletions src/pages/account/changepassword.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,69 @@
import React, { useState } from "react";
import Panel from "../../components/Panel";
import FormWrapper, { FormButton, FormField } from "../../components/FormWrapper";
import { fetchApi, FetchResult } from "../../lib/request";
import { withSessionSsr } from "../../lib/session";
import { changePasswordSchema } from "../../schemas/ChangePassword";
import { Text } from "@chakra-ui/react";
import React from "react";
import Panel from "@component/Panel";
import { withSessionSsr } from "@lib/session";
import { trpc } from "@util/trpc";
import { SubmitHandler, useForm } from "react-hook-form";
import { z } from "zod";
import { Text, Container, VStack, Wrap } from "@chakra-ui/react";
import TextInput from "@component/TextInput";
import Button from "@component/Button";
import { zodResolver } from "@hookform/resolvers/zod";
import { FormField } from "@component/FormField";
import { useFormFeedback } from "@hook/useFormFeedback";

const fields: FormField[] = [
const fields = [
{
type: "password",
name: "newPassword",
placeholder: "6 to 30 characters",
label: { text: "New Password" },
label: "New Password",
},
{
type: "password",
name: "repeatNewPassword",
label: { text: "Repeat New Password" },
label: "Repeat New Password",
},
{
type: "password",
name: "password",
label: { text: "Password" },
label: "Password",
},
];

const buttons: FormButton[] = [
{ type: "submit", btnColorType: "primary", value: "Submit" },
{ href: "/account", btnColorType: "danger", value: "Back" },
];
const schema = z
.object({
newPassword: z.string().min(6, { message: "Password must be at least 6 characters long" }),
repeatNewPassword: z.string().min(6, { message: "Password must be at least 6 characters long" }),
password: z.string().min(6, { message: "Password must be at least 6 characters long" }),
})
.refine((data) => data.newPassword === data.repeatNewPassword, {
message: "New passwords don't match",
path: ["repeatNewPassword"],
});

export default function ChangePassword() {
const [response, setResponse] = useState<FetchResult | undefined>(undefined);
const {
register,
handleSubmit,
reset,
formState: { errors, isValid, isSubmitting },
} = useForm<z.infer<typeof schema>>({
resolver: zodResolver(schema),
});
const { handleResponse, showResponse } = useFormFeedback();
const changePassword = trpc.account.changePassword.useMutation();

const onSubmit = async (values: any, { resetForm }: any) => {
const response = await fetchApi("POST", "/api/account/changepassword", {
data: {
newPassword: values.newPassword,
password: values.password,
},
const onSubmit: SubmitHandler<z.infer<typeof schema>> = async ({ newPassword, password }) => {
handleResponse(async () => {
await changePassword.mutateAsync({
newPassword,
password,
});

showResponse("Password changed.", "success");
});

setResponse(response);
resetForm();
reset();
};

return (
Expand All @@ -51,7 +72,21 @@ export default function ChangePassword() {
Please enter your current password and a new password. For your security, please enter the new password twice.
</Text>

<FormWrapper validationSchema={changePasswordSchema} onSubmit={onSubmit} fields={fields} buttons={buttons} response={response} />
<form onSubmit={handleSubmit(onSubmit)}>
<Container alignContent={"center"} padding={2}>
<VStack spacing={5}>
{fields.map((field) => (
<FormField key={field.name} error={(errors as any)[field.name]?.message} name={field.name} label={field.label}>
<TextInput type={field.type} {...register(field.name as any)} />
</FormField>
))}
<Wrap spacing={2} padding="10px">
<Button isLoading={isSubmitting} isActive={!isValid} loadingText="Submitting" type="submit" value="Submit" btnColorType="primary" />
<Button value="Back" btnColorType="danger" href="/account" />
</Wrap>
</VStack>
</Container>
</form>
</Panel>
);
}
Expand Down
27 changes: 0 additions & 27 deletions src/pages/api/account/[id].ts

This file was deleted.

46 changes: 0 additions & 46 deletions src/pages/api/account/changepassword.ts

This file was deleted.

62 changes: 62 additions & 0 deletions src/server/routers/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,66 @@ export const accountRouter = router({

return player;
}),
changePassword: authProcedure
.input(
z.object({
newPassword: z.string(),
password: z.string(),
}),
)
.mutation(async ({ input, ctx }) => {
const { newPassword, password } = input;
const { session } = ctx;

const account = await prisma.accounts.findFirst({
where: {
id: session.user!.id,
password: await sha1Encrypt(password),
},
});

if (!account) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Password doesn't match." });
}

await prisma.accounts.update({
where: {
id: account.id,
},
data: {
password: await sha1Encrypt(newPassword),
},
});
}),
changeEmail: authProcedure
.input(
z.object({
newEmail: z.string().email(),
password: z.string(),
}),
)
.mutation(async ({ input, ctx }) => {
const { newEmail, password } = input;
const { session } = ctx;

const account = await prisma.accounts.findFirst({
where: {
id: session.user!.id,
password: await sha1Encrypt(password),
},
});

if (!account) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Password doesn't match." });
}

await prisma.accounts.update({
where: {
id: account.id,
},
data: {
email: newEmail,
},
});
}),
});

0 comments on commit 1b425bc

Please sign in to comment.