Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for Navigation #289

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/backend/src/router/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ router.get('/logout', (req: Request, res: Response) => {
res.status(500).json({ error: 'Failed to log out' });
} else {
res.clearCookie('jwt');
res.redirect('http://localhost:5173/');
res.json({
message: 'Logged Out!',
success: true,
});
}
});
});
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@radix-ui/react-slot": "^1.0.2",
"@repo/store": "*",
"@repo/ui": "*",
"axios": "^1.6.8",
"chess.js": "^1.0.0-beta.8",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
Expand Down
12 changes: 2 additions & 10 deletions apps/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Game } from './screens/Game';
import Login from './screens/Login';
import { Suspense } from 'react';
import { RecoilRoot } from 'recoil';
import { useUser } from '@repo/store/useUser';
import { Loader } from './components/Loader';
import { Layout } from './layout';

Expand All @@ -22,19 +21,12 @@ function App() {
}

function AuthApp() {
const user = useUser();
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout children={<Landing />} />} />
<Route
path="/login"
element={<Login />}
/>
<Route
path="/game/:gameId"
element={<Layout children={<Game />} />}
/>
<Route path="/login" element={<Login />} />
<Route path="/game/:gameId" element={<Layout children={<Game />} />} />
</Routes>
</BrowserRouter>
);
Expand Down
20 changes: 4 additions & 16 deletions apps/frontend/src/components/constants/side-nav.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
import { logout } from '@/services/auth';
import { PuzzleIcon, LogInIcon, LogOutIcon, SettingsIcon } from 'lucide-react';
const BACKEND_URL =
import.meta.env.VITE_APP_BACKEND_URL ?? 'http://localhost:3000';

export const UpperNavItems = [
{
title: 'Play',
icon: PuzzleIcon,
href: '/game/random',
color: 'text-green-500',
},
//
// {
// title: 'Puzzles',
// icon: PuzzleIcon,
// href: '/',
// color: 'text-sky-500',
// },
// {
// title: 'Learn',
// icon: PuzzleIcon,
// href: '/',
// color: 'text-sky-500',
// },
];

export const LowerNavItems = [
Expand All @@ -33,8 +20,9 @@ export const LowerNavItems = [
{
title: 'Logout',
icon: LogOutIcon,
href: `${BACKEND_URL}/logout`,
href: '/logout',
color: 'text-green-500',
action: 'logout',
},
{
title: 'Settings',
Expand Down
49 changes: 37 additions & 12 deletions apps/frontend/src/components/side-nav.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import { cn } from '@/lib/utils';
import { useSidebar } from '@/hooks/useSidebar';
import { buttonVariants } from '@/components/ui/button';
import { useLocation } from 'react-router-dom';
import { useLocation, useNavigate } from 'react-router-dom';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@/components/subnav-accordian';
import { useEffect, useState } from 'react';
import { SyntheticEvent, useEffect, useState } from 'react';
import { ChevronDownIcon } from '@radix-ui/react-icons';
import { type LucideIcon } from 'lucide-react';
import { useUser } from '@repo/store/useUser';
import { api } from '@/lib/api';
import { useRecoilState } from 'recoil';
import { userAtom } from '../../../../packages/store/src/atoms/user';
import { LANDING_PAGE } from '@/constants/routes';

export interface NavItem {
title: string;
href: string;
href?: string;
icon: LucideIcon;
color?: string;
isChidren?: boolean;
children?: NavItem[];
action?: string;
}

interface SideNavProps {
Expand All @@ -29,7 +33,8 @@ interface SideNavProps {
}

export function SideNav({ items, setOpen, className }: SideNavProps) {
const user = useUser();
const [user, setUser] = useRecoilState(userAtom);
const navigate = useNavigate();
const location = useLocation();
const { isOpen } = useSidebar();
const [openItem, setOpenItem] = useState('');
Expand All @@ -44,6 +49,30 @@ export function SideNav({ items, setOpen, className }: SideNavProps) {
}
}, [isOpen]);

const handleLogout = async () => {
await api.get('/auth/logout/');
// Perform Cleanup
setUser(null);
navigate(LANDING_PAGE);
};

const executeAction = (action: string) => {
switch (action) {
case 'logout':
handleLogout();
break;
default:
console.error('Invalid Action Identifier');
}
};

const handleNavItemClick = (event: SyntheticEvent, navItem: NavItem) => {
event.preventDefault();
if (setOpen) setOpen(false);
if (navItem.action) executeAction(navItem.action);
else if (navItem.href) navigate(navItem.href);
};

return (
<nav className="dark">
{items.map((item) =>
Expand Down Expand Up @@ -79,14 +108,12 @@ export function SideNav({ items, setOpen, className }: SideNavProps) {
<ChevronDownIcon className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
)}
</AccordionTrigger>
<AccordionContent className="mt-2 space-y-4 pb-1">
<AccordionContent className="mt-2 space-y-4 pb-1 cursor-pointer">
{item.children?.map((child) => (
<a
key={child.title}
href={child.href}
onClick={() => {
if (setOpen) setOpen(false);
}}
onClick={(event) => handleNavItemClick(event, child)}
className={cn(
buttonVariants({ variant: 'ghost' }),
'group relative flex h-12 justify-start gap-x-3',
Expand Down Expand Up @@ -121,9 +148,7 @@ export function SideNav({ items, setOpen, className }: SideNavProps) {
<a
key={item.title}
href={item.href}
onClick={() => {
if (setOpen) setOpen(false);
}}
onClick={(event) => handleNavItemClick(event, item)}
className={cn(
buttonVariants({ variant: 'ghost' }),
'group relative flex h-12 justify-start',
Expand Down
3 changes: 3 additions & 0 deletions apps/frontend/src/constants/endpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const BACKEND_URL =
import.meta.env.VITE_APP_BACKEND_URL ?? 'http://localhost:3000';
export const WS_URL = import.meta.env.VITE_APP_WS_URL ?? 'ws://localhost:8080';
4 changes: 4 additions & 0 deletions apps/frontend/src/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// ROUTES
export const LANDING_PAGE = '/';
export const LOGIN = '/login';
export const GAME = '/game';
3 changes: 1 addition & 2 deletions apps/frontend/src/hooks/useSocket.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useEffect, useState } from 'react';
import { useUser } from '@repo/store/useUser';

const WS_URL = import.meta.env.VITE_APP_WS_URL ?? 'ws://localhost:8080';
import { WS_URL } from '@/constants/endpoints';

export const useSocket = () => {
const [socket, setSocket] = useState<WebSocket | null>(null);
Expand Down
13 changes: 13 additions & 0 deletions apps/frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { BACKEND_URL } from '@/constants/endpoints';
import axios, { CreateAxiosDefaults } from 'axios';

const config: CreateAxiosDefaults = {
baseURL: BACKEND_URL,
timeout: 8000,
headers: {
'Content-Type': 'application/json',
},
withCredentials: true,
};

export const api = axios.create(config);
26 changes: 11 additions & 15 deletions apps/frontend/src/screens/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export interface GameResult {
by: string;
}


const GAME_TIME_MS = 10 * 60 * 1000;

import { useRecoilValue, useSetRecoilState } from 'recoil';
Expand All @@ -60,10 +59,7 @@ export const Game = () => {
const [added, setAdded] = useState(false);
const [started, setStarted] = useState(false);
const [gameMetadata, setGameMetadata] = useState<Metadata | null>(null);
const [result, setResult] = useState<
GameResult
| null
>(null);
const [result, setResult] = useState<GameResult | null>(null);
const [player1TimeConsumed, setPlayer1TimeConsumed] = useState(0);
const [player2TimeConsumed, setPlayer2TimeConsumed] = useState(0);

Expand All @@ -79,8 +75,7 @@ export const Game = () => {
if (!user) {
window.location.href = '/login';
}
}, [user])

}, [user]);

useEffect(() => {
if (!socket) {
Expand Down Expand Up @@ -131,8 +126,12 @@ export const Game = () => {
break;

case GAME_ENDED:
const wonBy = message.payload.status === 'COMPLETED' ?
message.payload.result !== 'DRAW' ? 'CheckMate' : 'Draw' : 'Timeout';
const wonBy =
message.payload.status === 'COMPLETED'
? message.payload.result !== 'DRAW'
? 'CheckMate'
: 'Draw'
: 'Timeout';
setResult({
result: message.payload.result,
by: wonBy,
Expand All @@ -148,8 +147,7 @@ export const Game = () => {
blackPlayer: message.payload.blackPlayer,
whitePlayer: message.payload.whitePlayer,
});



break;

case USER_TIMEOUT:
Expand Down Expand Up @@ -227,7 +225,7 @@ export const Game = () => {
};

if (!socket) return <div>Connecting...</div>;

if (!user) return;
return (
<div className="">
{result && (
Expand Down Expand Up @@ -270,9 +268,7 @@ export const Game = () => {
)}
</div>
<div>
<div
className={`w-full flex justify-center text-white`}
>
<div className={`w-full flex justify-center text-white`}>
<ChessBoard
started={started}
gameId={gameId ?? ''}
Expand Down
4 changes: 1 addition & 3 deletions apps/frontend/src/screens/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import Google from '../assets/google.png';
import Github from '../assets/github.png';
import { useNavigate } from 'react-router-dom';

const BACKEND_URL =
import.meta.env.VITE_APP_BACKEND_URL ?? 'http://localhost:3000';
import { BACKEND_URL } from '@/constants/endpoints';

const Login = () => {
const navigate = useNavigate();
Expand Down
11 changes: 3 additions & 8 deletions apps/ws/src/SocketManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,9 @@ export class SocketManager {
console.error('User was not interested in any room?');
return;
}
const room = this.interestedSockets.get(roomId) || []
const remainingUsers = room.filter(u =>
u.userId !== user.userId
)
this.interestedSockets.set(
roomId,
remainingUsers
);
const room = this.interestedSockets.get(roomId) || [];
const remainingUsers = room.filter((u) => u.userId !== user.userId);
this.interestedSockets.set(roomId, remainingUsers);
if (this.interestedSockets.get(roomId)?.length === 0) {
this.interestedSockets.delete(roomId);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/store/src/atoms/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface User {
name: string;
}

export const userAtom = atom<User>({
export const userAtom = atom<User | null>({
key: 'user',
default: selector({
key: 'user/default',
Expand Down
Loading