Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
.idea
.vs
.env
1 change: 1 addition & 0 deletions client/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
Expand Down
28 changes: 15 additions & 13 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions client/src/AdminHome.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './AdminHome.css';
import { useAuth } from './AuthContext';
import { BASE_URL } from './App';

const AdminHome = () => {
const [announcementText, setAnnouncementText] = useState('');
Expand All @@ -14,7 +15,7 @@ const AdminHome = () => {

const fetchAnnouncements = async () => {
try {
const response = await axios.get('http://localhost:5000/announcements');
const response = await axios.get(`${BASE_URL}/announcements`);
setAnnouncements(response.data);
} catch (error) {
console.error('Error fetching announcements:', error);
Expand All @@ -24,7 +25,7 @@ const AdminHome = () => {

const handleAnnouncementSubmit = async () => {
try {
await axios.post('http://localhost:5000/announcement', { message: announcementText });
await axios.post(`${BASE_URL}/announcement`, { message: announcementText });
setAnnouncementText('');
fetchAnnouncements();
} catch (error) {
Expand All @@ -35,7 +36,7 @@ const AdminHome = () => {
const handleDeleteAnnouncement = async (id) => {
if (window.confirm('Are you sure you want to delete this announcement?')) {
try {
const response = await axios.delete(`http://localhost:5000/announcement/${id}`);
const response = await axios.delete(`${BASE_URL}/announcement/${id}`);
if (response.status === 200) {
alert('Announcement deleted successfully');
// Refresh the announcements list
Expand All @@ -55,7 +56,7 @@ const AdminHome = () => {
const handleReset = async () => {
if (window.confirm('Are you sure you want to reset the semester? This action cannot be undone.')) {
try {
await axios.post('http://localhost:5000/admin/reset');
await axios.post(`${BASE_URL}/admin/reset`);
alert('Reset successful');
fetchAnnouncements();
} catch (error) {
Expand Down
7 changes: 6 additions & 1 deletion client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import Search from './Search';
import Register from './Register';
import Schedule from './Schedule';
import ScheduleW from './ScheduleW';
import Emails from './Emails';
import { NavLink, useNavigate } from 'react-router-dom';
import './Navbar.css';
import { AuthProvider, useAuth } from './AuthContext'; // Adjust the path if necessary
import bannerImage from './images/banner.jpg';

export const BASE_URL = process.env.REACT_APP_BASE_URL;

function Navigation() {
const { isAuthenticated, isAdmin, logout } = useAuth();
const [showLogoutConfirm, setShowLogoutConfirm] = useState(false);
Expand Down Expand Up @@ -77,8 +80,9 @@ function Navigation() {
{!isAdmin && <NavLink to="/profile" activeClassName="active">Profile</NavLink>}
{!isAdmin && <NavLink to="/form" activeClassName="active">Form</NavLink>}
{isAdmin && <NavLink to="/search" activeClassName="active">Search</NavLink>}
{isAdmin && <NavLink to="/emails" activeClassName="active">Emails</NavLink>}
{isAdmin && <NavLink to="/schedule" activeClassName="active">PRP</NavLink>}
{isAdmin && <NavLink to="/schedule-w" activeClassName="active">Waived</NavLink>}
{isAdmin && <NavLink to="/schedule-w" activeClassName="active">Waived</NavLink>}
<button className="logout-button" onClick={handleLogoutClick}>
Logout
</button>
Expand Down Expand Up @@ -110,6 +114,7 @@ function App() {
<Route path="/search" element={<Search />} />
<Route path="/schedule" element={<Schedule />} />
<Route path="/schedule-w" element={<ScheduleW />} />
<Route path="/emails" element={<Emails />} />
</Routes>
</Router>
</AuthProvider>
Expand Down
3 changes: 2 additions & 1 deletion client/src/AuthContext.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, createContext, useContext, useEffect } from 'react';
import axios from 'axios';
import { BASE_URL } from './App';

const AuthContext = createContext();

Expand All @@ -20,7 +21,7 @@ export const AuthProvider = ({ children }) => {


try {
const response = await axios.get('http://localhost:5000/userData', { params: { userId: loggedInUserId } });
const response = await axios.get(`${BASE_URL}/userData`, { params: { userId: loggedInUserId } });
if (response.data.waive === 'admin') setIsAdmin(true); // Set admin flag to true
else setIsAdmin(false); // Set admin flag to false
setUser(response.data);
Expand Down
89 changes: 89 additions & 0 deletions client/src/Emails.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
.emails-container {
max-width: 800px;
margin: 40px auto;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}


/* Filter container styling */
.filter-container {
display: flex;
align-items: center;
margin-top: 20px;
margin-bottom: 20px;
margin-left: 20px;
margin-right: 20px;
padding: 10px;
background: #f8f9fa;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

/* Label styling */
.filter-container label {
font-weight: bold;
margin-right: 10px;
font-size: 1.1em;
color: #007bff;

}

/* Select dropdown styling */
.filter-container select {
flex: 1;
padding: 8px;
border-radius: 4px;
border: 1px solid #ccc;
font-size: 1em;
background: #ffffff;
transition: border-color 0.3s ease;
}

.filter-container select:hover {
border-color: #007bff;
}

/* Table styling */
table {
width: 100%;
margin-top: 20px;
border-collapse: collapse;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-left: 20px;
margin-right: 20px !important;
}

table thead {
background-color: #f5f5f5;
}

table th, table td {
padding: 12px 15px;
text-align: left;
border: 1px solid #ddd;
font-size: 1em;
}

table th {
font-weight: bold;
color: #555;
}

table tbody tr:nth-child(even) {
background-color: #f9f9f9;
}

table tbody tr:hover {
background-color: #f0f0f0;
color: #333;
}

/* Logout button styling */
.logout-button:hover {
background-color: #0056b3;
}
88 changes: 88 additions & 0 deletions client/src/Emails.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import './Emails.css';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { BASE_URL } from './App';

function Emails() {
const [users, setUsers] = useState([]);
const [filter, setFilter] = useState("All");
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);


useEffect(() => {
//getting all user data
const fetchUsers = async () => {
try {
setLoading(true);
const response = await axios.get(`${BASE_URL}/users`, {
params: {
waive: ["yes", "no"],
}
}); console.log('Fetched users:', response.data);
setUsers(response.data);
} catch (error) {
console.error('Error fetching users:', error);
setError('Error fetching users');
} finally {
setLoading(false);
}
};

fetchUsers();
}, []);


// returns correct output based on filter selection
const filteredUsers = Array.isArray(users) ? users.filter(user => {
if (filter === "All") return true;

if (filter === "Registered") return user.waive === "no";
if (filter === "Waived") return user.waive === "yes";
if (filter === "Uploaded document") return typeof user.pdfFileUrl === "string" && user.pdfFileUrl.length > 0;
if (filter === "Did not upload document") return !user.pdfFileUrl || user.pdfFileUrl.length === 0;

return false;
}) : [];

if (loading) return <p>Loading...</p>;
if (error) return <p>{error}</p>;

return (
<div>
<div className="filter-container">
<label htmlFor="filter">Select Status:</label>
<select
id="filter"
value={filter}
onChange={(e) => setFilter(e.target.value)}
>
<option value="All">All</option>
<option value="Registered">Registered</option>
<option value="Waived">Waived</option>
<option value="Uploaded document">Uploaded document</option>
<option value="Did not upload document">Did not upload document</option>
</select>
</div>

<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{filteredUsers.map((user, index) => (
<tr key={index}>
<td>{user.formData?.name || user.username}</td>
<td>{user.email}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}

export default Emails;
7 changes: 5 additions & 2 deletions client/src/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useAuth } from './AuthContext';
import './Form.css';
import { BASE_URL } from './App';

function Form() {
const { user, updateFormData, updateWaiveOption } = useAuth();
Expand Down Expand Up @@ -50,13 +51,15 @@ function Form() {
const handleFormSubmit = async (event) => {
event.preventDefault();
try {
await axios.post('http://localhost:5000/saveFormData', { userId: user.id, formData }); //Post to Database
console.log(user.id)
await axios.post(`${BASE_URL}/saveFormData`, { userId: user.id, formData }); //Post to Database
updateFormData(formData); //Update user context of formData
setIsReadOnly(true); // Make fields read-only after saving
await axios.post('http://localhost:5000/saveWaiveOption', { userId: user.id, waive: waiverOption === 'waiver' ? 'yes' : 'no' }); // Post to Database
await axios.post(`${BASE_URL}`, { userId: user.id, waive: waiverOption === 'waiver' ? 'yes' : 'no' }); // Post to Database
updateWaiveOption(waiverOption === 'waiver' ? 'yes' : 'no' ); //Update user context of waiveOption
console.log('Form data saved successfully');
} catch (error) {
console.log(error.toJSON())
console.error('Error saving form data', error);
}
};
Expand Down
Loading