Password reset working

This commit is contained in:
2025-03-15 21:27:15 -04:00
parent 49243a71a1
commit d42f625540
6 changed files with 169 additions and 1 deletions

View File

@@ -1,5 +1,6 @@
import { createBrowserRouter, RouterProvider } from "react-router";
import NavBar from "./components/nav/NavBar";
import AccountPage from "./pages/protected/AccountPage";
import AdminPage from "./pages/protected/AdminPage";
import GamePage from "./pages/protected/GamePage";
import GamesPage from "./pages/protected/GamesPage";
@@ -38,6 +39,10 @@ const routes = createBrowserRouter([
{
element: <ProtectedRoute/>,
children: [
{
path: "/account",
element: <AccountPage/>
},
{
path: "/logout",
element: <LogoutPage/>

View File

@@ -1,5 +1,6 @@
import { useAuth } from "@/providers/AuthProvider";
import { isSiteAdmin } from "@/util/PermissionUtil";
import { BsFillPersonFill } from "react-icons/bs";
import { NavLink } from "react-router";
@@ -46,6 +47,16 @@ export default function ProtectedNavLinks(){
</NavLink>
))
}
{
jwt &&
<NavLink
to="/account"
>
<BsFillPersonFill
size={22}
/>
</NavLink>
}
</>
);
}

View File

@@ -3,6 +3,7 @@ import { AccountTutorialStatus } from "@/interface/AccountTutorialStatus";
import { RaidGroupPermissionType } from "@/interface/RaidGroup";
import { api } from "@/util/AxiosUtil";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
export function useGetAccounts(page: number, pageSize: number, searchTerm?: string){
@@ -160,6 +161,28 @@ export function useUpdateTutorialsStatus(){
});
}
export function useUpdatePassword(){
return useMutation({
mutationKey: ["updatePassword"],
mutationFn: async ({currentPassword, newPassword}:{currentPassword: string; newPassword: string;}) => {
try{
await api.post("/auth/resetPassword", {
currentPassword,
newPassword
});
}
catch(error){
if(error instanceof AxiosError && error.response?.data.errors){
throw new Error(error.response?.data.errors.join(", "));
}
else{
throw error;
}
}
}
});
}
export function useForcePasswordReset(accountId: string){

View File

@@ -0,0 +1,29 @@
import TabGroup, { Tab } from "@/components/tab/TabGroup";
import PasswordResetDisplay from "@/ui/account/PasswordResetDisplay";
export default function AccountPage(){
const tabs: Tab[] = [
{
tabId: "password",
tabHeader: "Password",
tabContent: <PasswordResetDisplay/>
}
];
return (
<main
className="flex flex-col items-center justify-center gap-y-8"
>
<h1
className="mt-8 text-4xl"
>
My Account
</h1>
<TabGroup
tabs={tabs}
/>
</main>
);
}

View File

@@ -22,7 +22,17 @@ export default function SignupPage(){
const signup = () => {
if(password !== secondPassword){
if(username === ""){
addErrorMessage("Username cannot be empty");
return;
}
else if(email === ""){
addErrorMessage("Email cannot be empty");
}
else if(password === ""){
addErrorMessage("Password cannot be empty");
}
else if(password !== secondPassword){
addErrorMessage("Passwords do not match");
return;
}

View File

@@ -0,0 +1,90 @@
import PrimaryButton from "@/components/button/PrimaryButton";
import PasswordInput from "@/components/input/PasswordInput";
import { useUpdatePassword } from "@/hooks/AccountHooks";
import { useTimedModal } from "@/providers/TimedModalProvider";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router";
export default function PasswordResetDisplay(){
const [ currentPassword, setCurrentPassword ] = useState("");
const [ newPassword, setNewPassword ] = useState("");
const [ confirmPassword, setConfirmPassword ] = useState("");
const navigate = useNavigate();
const { addErrorMessage, addSuccessMessage } = useTimedModal();
const {mutate: updatePasswordMutate, status: updatePasswordStatus, error: updatePasswordError, reset: updatePasswordReset} = useUpdatePassword();
const updatePassword = () => {
if(newPassword !== confirmPassword){
addErrorMessage("Passwords do not match");
return;
}
else if(newPassword === ""){
addErrorMessage("Password cannot be empty");
return;
}
else{
updatePasswordMutate({
currentPassword,
newPassword
});
}
}
useEffect(() => {
if(updatePasswordStatus === "success"){
addSuccessMessage("Password updated successfully");
updatePasswordReset();
setCurrentPassword("");
setNewPassword("");
setConfirmPassword("");
}
else if(updatePasswordStatus === "error"){
addErrorMessage("Failed to update password: " + updatePasswordError.message);
updatePasswordReset();
}
}, [ updatePasswordMutate, updatePasswordStatus, updatePasswordError, updatePasswordReset, addSuccessMessage, addErrorMessage, navigate ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div>
<PasswordInput
id="accountCurrentPassword"
placeholder="Current Password"
value={currentPassword}
onChange={(e) => setCurrentPassword(e.target.value)}
/>
</div>
<div>
<PasswordInput
id="accountNewPassword"
placeholder="New Password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
/>
</div>
<div>
<PasswordInput
id="accountConfirmPassword"
placeholder="Confirm Password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
</div>
<div>
<PrimaryButton
onClick={updatePassword}
>
Update Password
</PrimaryButton>
</div>
</div>
);
}