Skip to content

Commit fdde9ba

Browse files
add error pages and start of admin pages to view suggestions
1 parent ebf4254 commit fdde9ba

8 files changed

+77
-26
lines changed

src/App.tsx

+14-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
33
import { Toaster } from '@/components/Toaster';
44

55
import LandingPage from './pages/LandingPage';
6-
import DeveloperPage from './pages/DeveloperPage';
6+
import AdminPage from './pages/admin/AdminPage';
77
import LoginPage from './pages/LoginPage';
8+
import NotfoundPage from './pages/NotfoundPage';
9+
import UnauthorizedPage from './pages/UnauthorizedPage';
810

911
import './App.css';
12+
import Background from './components/Background';
1013

1114
const queryClient = new QueryClient()
1215

@@ -19,11 +22,19 @@ function App() {
1922
{/* public routes */}
2023
<Route path="/" element={<LandingPage />} />
2124
<Route path="/login" element={<LoginPage />} />
25+
<Route path="/unauthorized" element={<UnauthorizedPage />} />
2226

23-
{/* protected routes */}
24-
<Route path="/dev" element={<DeveloperPage />} />
27+
{/* admin routes */}
28+
<Route path="/admin" element={<AdminPage />} />
29+
<Route path="/admin/suggestions" element={<div>Admin Suggestions</div>} />
30+
<Route path="/admin/quests" element={<div>Admin Quests</div>} />
31+
<Route path="/admin/users" element={<div>Admin Users</div>} />
32+
33+
{/* user routes */}
34+
<Route path="*" element={<NotfoundPage />} />
2535
</Routes>
2636
</Router>
37+
<Background />
2738
</QueryClientProvider>
2839
)
2940
}

src/hocs/WithAuth/WithAuth.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
11
import React, { useEffect, useState, ComponentType } from "react";
22
import { useNavigate } from "react-router-dom";
33

4-
const withAuth = <P extends object>(WrappedComponent: ComponentType<P>) => {
4+
const withAuth = <P extends object>(WrappedComponent: ComponentType<P>, requiredRole?: "admin") => {
55
const ComponentWithAuth: React.FC<P> = (props) => {
66
const navigate = useNavigate();
77
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
8+
const [userRole, setUserRole] = useState<string | null>(null);
89

910
useEffect(() => {
1011
const token = localStorage.getItem("token");
12+
const role = localStorage.getItem("role"); // Assuming the role is stored in local storage
1113
if (!token) {
1214
navigate("/login");
1315
return;
1416
}
1517

1618
setIsAuthenticated(true);
19+
setUserRole(role);
1720
}, [navigate]);
1821

1922
if (!isAuthenticated) {
2023
return null;
2124
}
2225

26+
if (requiredRole && userRole !== requiredRole) {
27+
navigate("/unauthorized");
28+
return null;
29+
}
30+
2331
return <WrappedComponent {...props} />;
2432
};
2533

2634
return ComponentWithAuth;
2735
};
2836

29-
export default withAuth;
37+
export default withAuth;

src/hocs/WithAuth/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import withAuth from './WithAuth';
1+
import withAuth from './withAuth';
22

33
export default withAuth;

src/pages/LandingPage.tsx

+5-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import MenuSpacer from "../components/MenuSpacer"
55

66
import logoImg from '../assets/placeholder-logo.png'
77
import useAuth from "@/hooks/useAuth";
8-
import Background from "@/components/Background";
98
import questService from "@/service/questService";
109
import { Quest } from "@/models/QuestModels/questResponse";
1110
import { useEffect, useState } from "react";
@@ -89,13 +88,13 @@ const LandingPage = () => {
8988
<MenuButton text="NEWS" onClick={undefined} />
9089
<MenuButton text="completed quests" onClick={undefined} />
9190
<MenuButton text="SUGGESTIONS" onClick={() => setIsSuggestionsOpen(true)} />
92-
{
93-
user && user.role === "admin" &&
94-
<MenuButton text="DEVELOPER" onClick={() => navigate("/dev")} />
95-
}
9691
<MenuSpacer />
9792

9893
<MenuButton text="SETTINGS" onClick={undefined} />
94+
{
95+
user && user.role === "admin" &&
96+
<MenuButton text="ADMIN" onClick={() => navigate("/admin")} />
97+
}
9998
<MenuSpacer />
10099

101100
{
@@ -131,12 +130,10 @@ const LandingPage = () => {
131130

132131
{
133132
isSuggestionsOpen &&
134-
<SuggestionsPanel
133+
<SuggestionsPanel
135134
onClose={() => setIsSuggestionsOpen(false)}
136135
/>
137136
}
138-
139-
<Background />
140137
</main>
141138
);
142139
}

src/pages/LoginPage.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useNavigate } from "react-router-dom";
22

33
import LoginPanel from "@/components/LoginPanel";
4-
import Background from "@/components/Background";
54

65
const LoginPage: React.FC = () => {
76
const navigate = useNavigate();
@@ -12,8 +11,6 @@ const LoginPage: React.FC = () => {
1211
onLoginSuccess={() => navigate("/")}
1312
onRegistrationSuccess={() => navigate("/")}
1413
/>
15-
16-
<Background />
1714
</main>
1815
);
1916
}

src/pages/NotfoundPage.tsx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
import Button from "@/components/Button";
3+
import { useNavigate } from "react-router-dom";
4+
5+
const NotfoundPage: React.FC = () => {
6+
const navigate = useNavigate();
7+
8+
return (
9+
<div className="fixed inset-0 z-50 flex items-center justify-center">
10+
<div className="flex flex-col p-4 rounded-md bg-secondary text-text">
11+
<h2 className="text-2xl font-bold">Error: 404</h2>
12+
<span className="py-2">Looks like you got lost</span>
13+
<Button type="confirm" text="back to base" onClick={() => navigate("/")} />
14+
</div>
15+
</div>
16+
);
17+
}
18+
19+
export default NotfoundPage;

src/pages/UnauthorizedPage.tsx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
import Button from "@/components/Button";
3+
import { useNavigate } from "react-router-dom";
4+
5+
const NotfoundPage: React.FC = () => {
6+
const navigate = useNavigate();
7+
8+
return (
9+
<div className="fixed inset-0 z-50 flex items-center justify-center">
10+
<div className="flex flex-col p-4 rounded-md bg-secondary text-text">
11+
<h2 className="text-2xl font-bold">Error: 429</h2>
12+
<span className="py-2">Hey, stay out of places your shouldn't be</span>
13+
<Button type="confirm" text="I concede" onClick={() => navigate("/")} />
14+
</div>
15+
</div>
16+
);
17+
}
18+
19+
export default NotfoundPage;

src/pages/DeveloperPage.tsx src/pages/admin/AdminPage.tsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ import useAuth from "@/hooks/useAuth";
77
import MenuButton from "@/components/MenuButton"
88
import MenuSpacer from "@/components/MenuSpacer"
99
import QuestModal from "@/components/QuestModal";
10-
import withAuth from "@/hocs/WithAuth";
1110

1211
import logoImg from '@/assets/placeholder-logo.png'
13-
import Background from "@/components/Background";
1412
import { Dialog, DialogContent } from "@radix-ui/react-dialog";
1513
import Button from "@/components/Button";
14+
import withAuth from "@/hocs/withAuth";
1615

17-
const DeveloperPage = () => {
16+
const AdminPage = () => {
1817
const navigate = useNavigate();
1918
const { accessToken } = useAuth();
2019
const [currentQuest, setCurrentQuest] = useState<Quest | null>(null);
@@ -34,9 +33,12 @@ const DeveloperPage = () => {
3433

3534
<div className="flex flex-col items-start mt-20">
3635
<MenuButton text="RANDOM QUEST" onClick={handleGetRandomQuest} />
36+
<MenuButton text="TEST MODAL" onClick={() => setIsQuestModalOpen(true)} />
3737
<MenuSpacer />
3838

39-
<MenuButton text="TEST MODAL" onClick={() => setIsQuestModalOpen(true)} />
39+
<MenuButton text="view suggestions" onClick={() => navigate("/admin/suggestions")} />
40+
<MenuButton text="view quests" onClick={() => navigate("/admin/quests")} />
41+
<MenuButton text="view users" onClick={() => navigate("/admin/users")} />
4042
<MenuSpacer />
4143

4244
<MenuButton text="back" onClick={() => navigate("/")} />
@@ -50,7 +52,7 @@ const DeveloperPage = () => {
5052
className="bg-slate-100"
5153
>
5254
<p>
53-
{JSON.stringify(currentQuest)}
55+
{JSON.stringify(currentQuest)}
5456
</p>
5557
<Button type="confirm" text="close" onClick={() => setCurrentQuest(null)} />
5658
</DialogContent>
@@ -73,12 +75,10 @@ const DeveloperPage = () => {
7375
"Escape with the loot"
7476
]}
7577
/>
76-
77-
<Background />
7878
</main>
7979
);
8080
}
8181

82-
const AuthenticatedDeveloperPage = withAuth(DeveloperPage);
82+
const AuthenticatedAdminPage = withAuth(AdminPage, "admin");
8383

84-
export default AuthenticatedDeveloperPage;
84+
export default AuthenticatedAdminPage;

0 commit comments

Comments
 (0)