Password reset working
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { createBrowserRouter, RouterProvider } from "react-router";
|
import { createBrowserRouter, RouterProvider } from "react-router";
|
||||||
import NavBar from "./components/nav/NavBar";
|
import NavBar from "./components/nav/NavBar";
|
||||||
|
import AccountPage from "./pages/protected/AccountPage";
|
||||||
import AdminPage from "./pages/protected/AdminPage";
|
import AdminPage from "./pages/protected/AdminPage";
|
||||||
import GamePage from "./pages/protected/GamePage";
|
import GamePage from "./pages/protected/GamePage";
|
||||||
import GamesPage from "./pages/protected/GamesPage";
|
import GamesPage from "./pages/protected/GamesPage";
|
||||||
@@ -38,6 +39,10 @@ const routes = createBrowserRouter([
|
|||||||
{
|
{
|
||||||
element: <ProtectedRoute/>,
|
element: <ProtectedRoute/>,
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: "/account",
|
||||||
|
element: <AccountPage/>
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/logout",
|
path: "/logout",
|
||||||
element: <LogoutPage/>
|
element: <LogoutPage/>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useAuth } from "@/providers/AuthProvider";
|
import { useAuth } from "@/providers/AuthProvider";
|
||||||
import { isSiteAdmin } from "@/util/PermissionUtil";
|
import { isSiteAdmin } from "@/util/PermissionUtil";
|
||||||
|
import { BsFillPersonFill } from "react-icons/bs";
|
||||||
import { NavLink } from "react-router";
|
import { NavLink } from "react-router";
|
||||||
|
|
||||||
|
|
||||||
@@ -46,6 +47,16 @@ export default function ProtectedNavLinks(){
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
jwt &&
|
||||||
|
<NavLink
|
||||||
|
to="/account"
|
||||||
|
>
|
||||||
|
<BsFillPersonFill
|
||||||
|
size={22}
|
||||||
|
/>
|
||||||
|
</NavLink>
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { AccountTutorialStatus } from "@/interface/AccountTutorialStatus";
|
|||||||
import { RaidGroupPermissionType } from "@/interface/RaidGroup";
|
import { RaidGroupPermissionType } from "@/interface/RaidGroup";
|
||||||
import { api } from "@/util/AxiosUtil";
|
import { api } from "@/util/AxiosUtil";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { AxiosError } from "axios";
|
||||||
|
|
||||||
|
|
||||||
export function useGetAccounts(page: number, pageSize: number, searchTerm?: string){
|
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){
|
export function useForcePasswordReset(accountId: string){
|
||||||
|
|||||||
29
src/pages/protected/AccountPage.tsx
Normal file
29
src/pages/protected/AccountPage.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -22,7 +22,17 @@ export default function SignupPage(){
|
|||||||
|
|
||||||
|
|
||||||
const signup = () => {
|
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");
|
addErrorMessage("Passwords do not match");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/ui/account/PasswordResetDisplay.tsx
Normal file
90
src/ui/account/PasswordResetDisplay.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user