📦 chore(authContext.tsx): add AuthContext component and its initial value to provide authentication-related data throughout the app
📦 chore(authContext.tsx): add login, logout, and refreshAccessToken functions to handle authentication logic 📦 chore(authContext.tsx): add userData state and setUserData function to store user data 📦 chore(baseModal/index.tsx): add "x-small" size option to BaseModal component to make it smaller 📦 chore(deleteAccountPage/index.tsx): create DeleteAccountPage component to handle account deletion logic 📦 chore(routes.tsx): add route for DeleteAccountPage component under /account/delete path 📦 chore(types/auth.ts): create AuthContextType and userData types to define the shape of authentication-related data
This commit is contained in:
commit
a88bf657a7
5 changed files with 164 additions and 1 deletions
77
src/frontend/src/contexts/authContext.tsx
Normal file
77
src/frontend/src/contexts/authContext.tsx
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { createContext, useEffect, useState } from "react";
|
||||||
|
import { AuthContextType, userData } from "../types/contexts/auth";
|
||||||
|
|
||||||
|
const initialValue: AuthContextType = {
|
||||||
|
isAuthenticated: false,
|
||||||
|
accessToken: null,
|
||||||
|
login: () => {},
|
||||||
|
logout: () => {},
|
||||||
|
refreshAccessToken: () => Promise.resolve(),
|
||||||
|
userData: null,
|
||||||
|
setUserData: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const AuthContext = createContext<AuthContextType>(initialValue);
|
||||||
|
|
||||||
|
export function AuthProvider({ children }): React.ReactElement {
|
||||||
|
const [accessToken, setAccessToken] = useState<string | null>(null);
|
||||||
|
const [userData, setUserData] = useState<userData>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const storedAccessToken = localStorage.getItem("access_token");
|
||||||
|
if (storedAccessToken) {
|
||||||
|
setAccessToken(storedAccessToken);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function login(newAccessToken: string, refreshToken: string) {
|
||||||
|
localStorage.setItem("access_token", newAccessToken);
|
||||||
|
setAccessToken(newAccessToken);
|
||||||
|
// Store refreshToken if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
localStorage.removeItem("access_token");
|
||||||
|
// Clear refreshToken if used
|
||||||
|
setAccessToken(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshAccessToken(refreshToken: string) {
|
||||||
|
try {
|
||||||
|
// Call your API to refresh the access token using the refresh token
|
||||||
|
const response = await fetch("/api/refresh-token", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ refreshToken }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
login(data.accessToken, refreshToken);
|
||||||
|
} else {
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
// !! to convert string to boolean
|
||||||
|
<AuthContext.Provider
|
||||||
|
value={{
|
||||||
|
isAuthenticated: !!accessToken,
|
||||||
|
accessToken,
|
||||||
|
login,
|
||||||
|
logout,
|
||||||
|
refreshAccessToken,
|
||||||
|
setUserData,
|
||||||
|
userData,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</AuthContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ interface BaseModalProps {
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
setOpen?: (open: boolean) => void;
|
setOpen?: (open: boolean) => void;
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
size?: "smaller" | "small" | "medium" | "large" | "large-h-full";
|
size?: "x-small" | "smaller" | "small" | "medium" | "large" | "large-h-full";
|
||||||
}
|
}
|
||||||
function BaseModal({
|
function BaseModal({
|
||||||
open,
|
open,
|
||||||
|
|
@ -73,6 +73,10 @@ function BaseModal({
|
||||||
let height: string;
|
let height: string;
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
case "x-small":
|
||||||
|
minWidth = "min-w-[20vw]";
|
||||||
|
height = "h-[10vh]";
|
||||||
|
break;
|
||||||
case "smaller":
|
case "smaller":
|
||||||
minWidth = "min-w-[40vw]";
|
minWidth = "min-w-[40vw]";
|
||||||
height = "h-[27vh]";
|
height = "h-[27vh]";
|
||||||
|
|
|
||||||
59
src/frontend/src/pages/deleteAccountPage/index.tsx
Normal file
59
src/frontend/src/pages/deleteAccountPage/index.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button } from "../../components/ui/button";
|
||||||
|
import { Input } from "../../components/ui/input";
|
||||||
|
import BaseModal from "../../modals/baseModal";
|
||||||
|
|
||||||
|
export default function DeleteAccountPage() {
|
||||||
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
||||||
|
|
||||||
|
const handleDeleteAccount = () => {
|
||||||
|
// Implement your account deletion logic here
|
||||||
|
// For example, make an API call to delete the account
|
||||||
|
// Upon successful deletion, you can redirect the user to another page
|
||||||
|
console.log("Account deleted!");
|
||||||
|
// Implement the logic to redirect the user after account deletion.
|
||||||
|
// For example, use react-router-dom's useHistory hook.
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
|
||||||
|
<div className="flex w-72 flex-col items-center justify-center gap-2">
|
||||||
|
<span className="mb-4 text-5xl">⛓️</span>
|
||||||
|
<span className="mb-4 text-center text-2xl font-semibold text-primary">
|
||||||
|
Delete your account
|
||||||
|
</span>
|
||||||
|
<Input className="bg-background" placeholder="Confirm password" />
|
||||||
|
|
||||||
|
<BaseModal
|
||||||
|
open={showConfirmation}
|
||||||
|
setOpen={setShowConfirmation}
|
||||||
|
size="x-small"
|
||||||
|
>
|
||||||
|
<BaseModal.Header description="This action is irreversible and will permanently erase all your data and information associated with the account. ">
|
||||||
|
<h3>Are you sure ?</h3>
|
||||||
|
</BaseModal.Header>
|
||||||
|
<BaseModal.Trigger>
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
className="w-full hover:bg-status-red"
|
||||||
|
onClick={() => setShowConfirmation(true)}
|
||||||
|
>
|
||||||
|
Delete account
|
||||||
|
</Button>
|
||||||
|
</BaseModal.Trigger>
|
||||||
|
<BaseModal.Content>
|
||||||
|
<div className="flex h-full w-full flex-col justify-end">
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
className="w-full hover:bg-status-red"
|
||||||
|
onClick={() => handleDeleteAccount()}
|
||||||
|
>
|
||||||
|
Delete account
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</BaseModal.Content>
|
||||||
|
</BaseModal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import { Route, Routes } from "react-router-dom";
|
||||||
import CommunityPage from "./pages/CommunityPage";
|
import CommunityPage from "./pages/CommunityPage";
|
||||||
import FlowPage from "./pages/FlowPage";
|
import FlowPage from "./pages/FlowPage";
|
||||||
import HomePage from "./pages/MainPage";
|
import HomePage from "./pages/MainPage";
|
||||||
|
import DeleteAccountPage from "./pages/deleteAccountPage";
|
||||||
import LoginPage from "./pages/loginPage";
|
import LoginPage from "./pages/loginPage";
|
||||||
import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
||||||
import AdminPage from "./pages/AdminPage";
|
import AdminPage from "./pages/AdminPage";
|
||||||
|
|
@ -15,9 +16,15 @@ const Router = () => {
|
||||||
<Route path="" element={<FlowPage />} />
|
<Route path="" element={<FlowPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="*" element={<HomePage />} />
|
<Route path="*" element={<HomePage />} />
|
||||||
|
|
||||||
<Route path="/login" element={<LoginPage />} />
|
<Route path="/login" element={<LoginPage />} />
|
||||||
<Route path="/login/admin" element={<LoginAdminPage />} />
|
<Route path="/login/admin" element={<LoginAdminPage />} />
|
||||||
|
|
||||||
<Route path="/admin" element={<AdminPage />} />
|
<Route path="/admin" element={<AdminPage />} />
|
||||||
|
|
||||||
|
<Route path="/account">
|
||||||
|
<Route path="delete" element={<DeleteAccountPage />}></Route>
|
||||||
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
16
src/frontend/src/types/contexts/auth.ts
Normal file
16
src/frontend/src/types/contexts/auth.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
export type AuthContextType = {
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
accessToken: string | null;
|
||||||
|
login: (accessToken: string, refreshToken: string) => void;
|
||||||
|
logout: () => void;
|
||||||
|
refreshAccessToken: (refreshToken: string) => Promise<void>;
|
||||||
|
userData: userData | null;
|
||||||
|
setUserData: (userData: userData | null) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type userData = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
role: string;
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue