Skip to content
Merged
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
Binary file added nextstep-frontend/assets/NextStep.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added nextstep-frontend/assets/NextStepLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion nextstep-frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/png" href="/NextStepLogo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Next Step</title>
</head>
Expand Down
Binary file added nextstep-frontend/public/NextStepLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
1 change: 1 addition & 0 deletions nextstep-frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
width: 100%;
margin: 0 auto;
text-align: center;
background-color: #f9f9f9;
}

.logo {
Expand Down
26 changes: 15 additions & 11 deletions nextstep-frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,43 @@ import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-d
import Login from './pages/Login';
import Register from './pages/Register';
import Profile from './pages/Profile';
import './App.css'
import './App.css';
import Feed from './pages/Feed';
import Footer from './components/Footer';
import RequireAuth from './hoc/RequireAuth';
import NewPost from './pages/NewPost';
import PostDetails from './pages/PostDetails';
import Chat from './pages/Chat';
import Resume from './pages/Resume';
import TopBar from './components/TopBar';
import LeftBar from './components/LeftBar';
import Layout from './components/Layout';
import MainDashboard from './pages/MainDashboard';
import Quiz from './pages/Quiz';
import { Box } from '@mui/material';

const App: React.FC = () => {
return (
<>
<Box height="90vh" display='flex' width="100%">
<Router>
<LeftBar />
<Routes>
<Route path="/" element={<Layout className="login"><Login /></Layout>} />
<Route path="/login" element={<Layout className="login"><Login /></Layout>} />
<Route path="/register" element={<Layout className="register"><Register /></Layout>} />
<Route path="/feed" element={<RequireAuth><TopBar /><Layout className="feed"><Feed /></Layout></RequireAuth>} />
<Route path="/profile" element={<RequireAuth><TopBar /><Layout className="profile"><Profile /></Layout></RequireAuth>} />
<Route path="/new-post" element={<RequireAuth><TopBar /><Layout className="new-post"><NewPost /></Layout></RequireAuth>} />
<Route path="/post/:postId" element={<RequireAuth><TopBar /><Layout className="post-details"><PostDetails /></Layout></RequireAuth>} />
<Route path="/chat" element={<RequireAuth><TopBar /><Layout className="chat"><Chat /></Layout></RequireAuth>} />
<Route path="/resume" element={<RequireAuth><TopBar /><Layout className="resume"><Resume /></Layout></RequireAuth>} />
<Route path="/main-dashboard" element={<RequireAuth><TopBar /><Layout className="main-dashboard"><MainDashboard /></Layout></RequireAuth>} />
<Route path="/quiz" element={<RequireAuth><TopBar /><Layout className="quiz"><Quiz /></Layout></RequireAuth>} />
<Route path="/feed" element={<RequireAuth><Layout className="feed"><Feed /></Layout></RequireAuth>} />
<Route path="/profile" element={<RequireAuth><Layout className="profile"><Profile /></Layout></RequireAuth>} />
<Route path="/new-post" element={<RequireAuth><Layout className="new-post"><NewPost /></Layout></RequireAuth>} />
<Route path="/post/:postId" element={<RequireAuth><Layout className="post-details"><PostDetails /></Layout></RequireAuth>} />
<Route path="/chat" element={<RequireAuth><Layout className="chat"><Chat /></Layout></RequireAuth>} />
<Route path="/resume" element={<RequireAuth><Layout className="resume"><Resume /></Layout></RequireAuth>} />
<Route path="/main-dashboard" element={<RequireAuth><Layout className="main-dashboard"><MainDashboard /></Layout></RequireAuth>} />
<Route path="/quiz" element={<RequireAuth><Layout className="quiz"><Quiz /></Layout></RequireAuth>} />
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</Router>
<Footer/>
</Box>
<Footer/>
</>
);
};
Expand Down
9 changes: 5 additions & 4 deletions nextstep-frontend/src/components/Layout.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
.layout-container {
margin-left: 100; /* push content to the right of the sidebar */
width: calc(100% - 100);
height: 100%;
padding-top: 10vh;
padding-top: 5vh;
overflow-y: auto;
max-width: none;
align-content: flex-start;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
}
119 changes: 119 additions & 0 deletions nextstep-frontend/src/components/LeftBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { useRef, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Box, Drawer, List, ListItem, ListItemIcon, ListItemText, IconButton } from '@mui/material';
import { Home, Person, Message, Logout, DocumentScannerTwoTone, Feed, Quiz, Menu, ChevronLeft } from '@mui/icons-material';
import { getUserAuth, removeUserAuth } from "../handlers/userAuth.ts";
import api from "../serverApi.ts";
import logo from '../../assets/NextStep.png';

const LeftBar: React.FC = () => {
const userAuthRef = useRef(getUserAuth());
const navigate = useNavigate();
const [collapsed, setCollapsed] = useState(false);

useEffect(() => {
// Automatically collapse the sidebar if the user is disconnected
if (!userAuthRef.current) {
setCollapsed(true);
}
}, [userAuthRef.current]);

const handleLogout = async () => {
if (userAuthRef.current) {
await api.post(`/auth/logout`, {
refreshToken: userAuthRef.current.refreshToken,
});
removeUserAuth();
}
navigate('/logout');
};

const toggleCollapse = () => {
setCollapsed(!collapsed);
};

return (
<Drawer
variant="permanent"
sx={{
width: collapsed ? 60 : 180,
flexShrink: 0,
[`& .MuiDrawer-paper`]: {
width: collapsed ? 60 : 180,
boxSizing: 'border-box',
backgroundColor: '#233752',
color: 'white',
overflowX: 'hidden',
transition: 'width 0.3s',
},
}}
>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: collapsed ? 'center' : 'space-between',
padding: '8px',
}}
>
{!collapsed && (
<Box
component="img"
src={logo}
alt="Logo"
sx={{ height: 120, width: 150 }}
/>
)}
<IconButton onClick={toggleCollapse} sx={{ color: 'white' }}>
{collapsed ? <Menu /> : <ChevronLeft fontSize="large" />}
</IconButton>
</Box>
<List>
<ListItem button onClick={() => navigate('/main-dashboard')} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<Home sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Home" />}
</ListItem>
<ListItem button onClick={() => navigate('/resume')} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<DocumentScannerTwoTone sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Resume" />}
</ListItem>
<ListItem button onClick={() => navigate('/quiz')} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<Quiz sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Quiz" />}
</ListItem>
<ListItem button onClick={() => navigate('/feed')} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<Feed sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Feed" />}
</ListItem>
<ListItem button onClick={() => navigate('/chat')} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<Message sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Chat" />}
</ListItem>
<ListItem button onClick={() => navigate('/profile')} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<Person sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Profile" />}
</ListItem>
<ListItem button onClick={handleLogout} sx={{ cursor: 'pointer' }}>
<ListItemIcon>
<Logout sx={{ color: 'white' }} />
</ListItemIcon>
{!collapsed && <ListItemText primary="Logout" />}
</ListItem>
</List>
</Drawer>
);
};

export default LeftBar;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface Job {
salary?: string;
}

interface LinkedInIntegrationProps {
interface LinkedinJobsProps {
jobs: Job[];
loadingJobs: boolean;
fetchJobs: (settings: LinkedInSettings) => Promise<void>;
Expand All @@ -30,7 +30,7 @@ interface LinkedInSettings {
skills: string[];
}

const LinkedInIntegration: React.FC<LinkedInIntegrationProps> = ({
const LinkedinJobs: React.FC<LinkedinJobsProps> = ({
jobs,
loadingJobs,
fetchJobs,
Expand Down Expand Up @@ -164,8 +164,7 @@ const LinkedInIntegration: React.FC<LinkedInIntegrationProps> = ({
/>
))}
</Stack>
<TextField
label="Add Skill"
{settings.skills.length < 3 && <TextField
variant="outlined"
fullWidth
onKeyDown={(e) => {
Expand All @@ -181,10 +180,10 @@ const LinkedInIntegration: React.FC<LinkedInIntegrationProps> = ({
input.value = '';
}
}}
placeholder={settings.skills.length >= 3 ? "Reached max of 3 skills" : "Type a skill and press Enter"}
disabled={settings.skills.length >= 3} // Disable input if 3 skills are already added
placeholder="Type a skill and press Enter"
sx={{ mt: 1 }}
/>
}
</Grid>
<br />
<Box sx={{ textAlign: 'center', mb: 3 }}>
Expand Down Expand Up @@ -312,4 +311,4 @@ const LinkedInIntegration: React.FC<LinkedInIntegrationProps> = ({
);
};

export default LinkedInIntegration;
export default LinkedinJobs;
66 changes: 0 additions & 66 deletions nextstep-frontend/src/components/TopBar.tsx

This file was deleted.

Loading
Loading