Skip to content

Commit

Permalink
Merge pull request #59 from JumboCode/ConnectStudent
Browse files Browse the repository at this point in the history
Connecting Students and Classes
  • Loading branch information
myix765 authored Nov 25, 2024
2 parents 2dfd20f + 7d75fcd commit e4f418e
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 67 deletions.
38 changes: 38 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ const Level = mongoose.model("Level", LevelSchema)

//------------------ ENDPOINTS ------------------//

/* USER RELATED ENDPOINTS */

// Sign up
app.post('/api/users', async (req, res) => {
try {
Expand Down Expand Up @@ -208,6 +210,9 @@ app.get('/api/users', async (req, res) => {
}
})


/* CONTACT RELATED ENDPOINTS */

// Post Contact
app.post('/api/contact', async (req, res) => {
const { name, email, subject, message } = req.body
Expand All @@ -227,6 +232,9 @@ app.post('/api/contact', async (req, res) => {
}
})


/* CLASS RELATED ENDPOINTS */

// Get Classes
app.get('/api/classes', async (req, res) => {
try {
Expand Down Expand Up @@ -263,6 +271,36 @@ app.get("/api/conversations", async (req, res) => {
}
})

// Get Student's classes
app.get('/api/students-classes', async (req, res) => {
try {
const allowedFields = ['_id'];
const filters = validateInput(req.query, allowedFields);

//apply the filters directly to the database query
const data = await User.findOne(filters, { enrolledClasses: 1, _id: 0 });
res.json(data);

} catch (err) {
res.status(500).send(err);
}
})

// Get class by ID
app.get('/api/class', async (req, res) => {
try {
const allowedFields = ['_id'];
const filters = validateInput(req.query, allowedFields);

//apply the filters directly to the database query
const data = await Class.findOne(filters);
res.json(data)

} catch (err) {
res.status(500).send(err);
}
})

// Enroll in a class
app.put('/api/users/:id/enroll', async (req, res) => {
const { classId } = req.body
Expand Down
32 changes: 26 additions & 6 deletions src/api/class-wrapper.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import axios from 'axios'

const apiUrl = (endpoint) => `${endpoint}`

// query should be a string
const getClasses = async (query = "") => {
try {
const response = await axios.get(apiUrl(`/api/classes?${query}`))
const response = await axios.get(`/api/classes?${query}`)
return response.data
} catch (error) {
console.error('Error fetching courses:', error)
Expand All @@ -15,7 +13,7 @@ const getClasses = async (query = "") => {
// query should be a string
const getLevels = async (query = "") => {
try {
const response = await axios.get(apiUrl(`/api/levels?${query}`));
const response = await axios.get(`/api/levels?${query}`);
return response.data
} catch (error) {
console.error('Error fetching levels:', error);
Expand All @@ -24,7 +22,7 @@ const getLevels = async (query = "") => {

const getConversations = async () => {
try {
const response = await axios.get(apiUrl("/api/conversations/"))
const response = await axios.get("/api/conversations/")
return response.data
} catch (error) {
console.error('Error fetching conversations:', error)
Expand Down Expand Up @@ -61,10 +59,32 @@ const unenrollInClass = async (classId, userId) => {
}
}

const getStudentClasses = async (studentId) => {
const queryString = new URLSearchParams(`_id=${studentId}`);
try {
const response = await axios.get(`/api/students-classes?${queryString.toString()}`);
return response.data;
} catch (error) {
console.error("Error fetching student's classes:", error);
}
}

const getClassById = async (classId) => {
const queryString = new URLSearchParams(`_id=${classId}`);
try {
const response = await axios.get(`/api/class?${queryString.toString()}`);
return response.data;
} catch (error) {
console.error("Error fetching class from id:", error);
}
}

export {
getClasses,
getLevels,
getConversations,
enrollInClass,
unenrollInClass
unenrollInClass,
getStudentClasses,
getClassById,
}
2 changes: 1 addition & 1 deletion src/components/NavBar/NavBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const NavBar = () => {
<img className="h-14 w-auto" src={dillarLogo} alt="Dillar English Academy" />
</Link>
{/* Desktop navigation */}
<div className="hidden sm:flex sm:items-center sm:space-x-4">
<div className="hidden sm:flex sm:items-center lg:space-x-20 md:space-x-10">
<NavLink href="/levels">Classes</NavLink>
<NavLink href="/contact">Contact</NavLink>
<NavLink href="/about">About</NavLink>
Expand Down
30 changes: 15 additions & 15 deletions src/pages/AdminView.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { useEffect, useState } from "react";

const AdminView = () => {
const [user, setUser] = useState(null);
const [user, setUser] = useState(null);

useEffect(() => {
const params = new URLSearchParams(location.search);
const user = {
firstName: params.get('firstName'),
lastName: params.get('lastName'),
username: params.get('username')
};
setUser(user);
}, []);
useEffect(() => {
const params = new URLSearchParams(location.search);
const user = {
firstName: params.get('firstName'),
lastName: params.get('lastName'),
username: params.get('username')
};
setUser(user);
}, []);

return (
<div>
<h1>Admin: {user ? `${user.firstName} ${user.lastName}` : 'Loading...'}</h1>
</div>
);
return (
<div className="h-full">
<h1>Admin: {user ? `${user.firstName} ${user.lastName}` : 'Loading...'}</h1>
</div>
);
};

export default AdminView;
2 changes: 1 addition & 1 deletion src/pages/ClassesPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const ClassesPage = () => {
if (loading || !level) return <></>;

return (
<div className="min-h-screen bg-white">
<div className="h-full bg-white">
{/* Banner Section */}
<div className="bg-gradient-to-r from-[#FFFFFF] from-5% via-[#D3EDFC] via-35% via-[#B2A0FA] via-75% via-[#8AC7F4] to-[#3F96EA] py-12">
<div className="max-w-7xl mx-auto px-8">
Expand Down
48 changes: 21 additions & 27 deletions src/pages/PageNotFound.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,26 @@ import { useLocation } from 'wouter';
import Button from '../components/Button/Button';

const PageNotFound = () => {
const [, setLocation] = useLocation();

return (
<div className="flex items-center justify-center h-5/6">
<div>
<h1 className="flex items-center justify-center h-5/6 text-6xl mb-2 font-bold pt-5 py-5" >Page Not Found</h1>
<h2 className="flex items-center justify-center text-3xl mb-2 font-normal"> The page you're looking for doesn't exist.</h2>
<div className='flex items-center justify-center space-x-5 whitespace-nowrap pt-8'>
<Button
label={"Return Home"}
onClick={() => setLocation("/")}
isOutline={false}
/>
<Button
label={"Get Help"}
onClick={() => setLocation("/")}
isOutline={true}
/>
</div>


</div>


</div>
)
const [, setLocation] = useLocation();

return (
<div className="flex flex-col items-center justify-center h-full">
<h1 className="text-6xl mb-2 font-bold pt-5 py-5" >Page Not Found</h1>
<h2 className="text-3xl mb-2 font-normal"> The page you're looking for doesn't exist.</h2>
<div className='flex space-x-5 whitespace-nowrap pt-8'>
<Button
label={"Return Home"}
onClick={() => setLocation("/")}
isOutline={false}
/>
<Button
label={"Get Help"}
onClick={() => setLocation("/")}
isOutline={true}
/>
</div>
</div>
)
}

export default PageNotFound
export default PageNotFound;
58 changes: 41 additions & 17 deletions src/pages/StudentPortal.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,47 @@
import { useEffect, useState } from "react";
import { useEffect, useState } from 'react';
import Class from '@/components/Class';
import { getClassById, getStudentClasses } from '@/api/class-wrapper';

const StudentPortal = () => {
const [user, setUser] = useState(null);
const [classes, setClasses] = useState([]);
const [user, setUser] = useState(null);

useEffect(() => {
const params = new URLSearchParams(location.search);
const user = {
firstName: params.get('firstName'),
lastName: params.get('lastName'),
username: params.get('username')
};
setUser(user);
}, []);
useEffect(() => {
const params = new URLSearchParams(location.search);
const user = {
firstName: params.get('firstName'),
lastName: params.get('lastName'),
username: params.get('username')
};
setUser(user);

return (
<div>
<h1>Student: {user ? `${user.firstName} ${user.lastName}` : 'Loading...'}</h1>
</div>
);
};
// get classes for student
const fetchData = async () => {
// fetch a specific user
const response = await getStudentClasses("671edb6d31e448b23d0dc384");
const classes = await Promise.all(
response.enrolledClasses.map(async (classID) => {
const classResponse = await getClassById(classID);
return classResponse; // Return the class details
})
);
setClasses(classes);
};

fetchData();
}, []);

return (
<div className='h-full'>
<h1>Student: {user ? `${user.firstName} ${user.lastName}` : 'Loading...'}</h1>
<div className='grid grid-cols-3'>
{classes.map((classObj, classIndex) => (
<Class key={classIndex} classObj={classObj} />
))}
</div>
</div>
);

}

export default StudentPortal;

0 comments on commit e4f418e

Please sign in to comment.