diff --git a/.gitignore b/.gitignore
index fc81720..1248287 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
# testing
/coverage
+.env
# production
/build
diff --git a/examples.env b/examples.env
new file mode 100644
index 0000000..6a2b176
--- /dev/null
+++ b/examples.env
@@ -0,0 +1 @@
+REACT_APP_API_HOST=YOURHOSTHERE
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index c86f0a5..ce80e39 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,8 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "axios": "^1.7.7",
+ "dotenv": "^16.4.5",
"framer-motion": "^11.9.0",
"react": "^18.3.1",
"react-dnd": "^16.0.1",
@@ -5569,6 +5571,31 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/axios/node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@@ -7312,11 +7339,15 @@
}
},
"node_modules/dotenv": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
- "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">=10"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
}
},
"node_modules/dotenv-expand": {
@@ -14875,6 +14906,12 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -15368,6 +15405,15 @@
}
}
},
+ "node_modules/react-scripts/node_modules/dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/react-select": {
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.2.tgz",
diff --git a/package.json b/package.json
index 411a892..6206772 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,8 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "axios": "^1.7.7",
+ "dotenv": "^16.4.5",
"framer-motion": "^11.9.0",
"react": "^18.3.1",
"react-dnd": "^16.0.1",
diff --git a/src/components/Courses.jsx b/src/components/Courses.jsx
index b7c2854..2c4fe53 100644
--- a/src/components/Courses.jsx
+++ b/src/components/Courses.jsx
@@ -1,16 +1,9 @@
-import { useState } from 'react';
-
-const Courses = ({ courses }) => {
- const [openCourses, setOpenCourses] = useState(
- Array(courses.length).fill(false),
- );
-
- const toggleDropdown = (index) => {
- setOpenCourses((prev) => {
- const newOpenCourses = [...prev];
- newOpenCourses[index] = !newOpenCourses[index];
- return newOpenCourses;
- });
+const Courses = ({ courses, openCourses, toggleDropdown }) => {
+ const displayCredit = (minCredit, maxCredit) => {
+ if (minCredit === maxCredit) {
+ return `${minCredit} Credits`;
+ }
+ return `${minCredit} - ${maxCredit} Credits`;
};
return (
@@ -27,19 +20,37 @@ const Courses = ({ courses }) => {
>
- {course.id}
+ {course.department}-{course.code}
- {course.name}
+ {course.title}
- {course.credits} Credits
+ {displayCredit(course.creditMin, course.creditMax)}
{openCourses[index] && (
-
{course.description}
+
{course.description || 'No description'}
+
+ {course.semesterList.length > 0 ? (
+
+ Offered: {course.semesterList.join(', ')}
+
+ ) : (
+
No semesters offered
+ )}
+
+
+ {course.attributeList.length > 0 ? (
+
+ Attributes: {course.attributeList.join(', ')}
+
+ ) : (
+
No attributes
+ )}
+
)}
@@ -87,9 +98,27 @@ const styles = {
},
CourseBlurb: {
marginLeft: '2em',
+ marginRight: '2em',
marginTop: '0.5em',
+ marginBottom: '0.5em',
fontSize: '1em',
color: '#555',
+ backgroundColor: '#e0e0e0', // Slightly darker background color
+ borderRadius: '8px',
+ padding: '1em',
+ },
+ bubbleContainer: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ gap: '0.5em',
+ marginTop: '0.5em',
+ },
+ bubble: {
+ backgroundColor: '#d0d0d0', // Slightly darker background color for bubbles
+ borderRadius: '15px',
+ padding: '0.5em 1em',
+ fontSize: '0.9em',
+ color: '#333',
},
};
diff --git a/src/components/SearchCourse.jsx b/src/components/SearchCourse.jsx
index 01edf16..894ea93 100644
--- a/src/components/SearchCourse.jsx
+++ b/src/components/SearchCourse.jsx
@@ -1,6 +1,6 @@
-import { useState } from 'react';
+import { useState, useEffect } from 'react';
+import axios from 'axios';
import Select from 'react-select';
-
import Courses from '../components/Courses';
import filterIcon from '../assets/images/filter.svg';
import expandedIcon from '../assets/images/expanded.svg';
@@ -17,7 +17,7 @@ const styles = {
backgroundColor: 'rgb(254, 226, 226)',
borderRadius: '0.75rem',
fontFamily: 'Single Day, cursive',
- height: '32em',
+ height: '656px',
overflow: 'hidden',
},
coursesContainer: {
@@ -25,7 +25,7 @@ const styles = {
borderRadius: '0.75rem',
overflowY: 'auto',
paddingBottom: '10px',
- maxHeight: 'calc(100% - 90px)',
+ maxHeight: 'calc(100% - 100px)',
},
heading: {
textAlign: 'left',
@@ -71,41 +71,14 @@ const styles = {
fontSize: '15px',
color: '#8D8D8D',
marginLeft: '10px',
- marginBottom: '-10px',
+ marginBottom: '-5px',
},
};
-const courseData = Array.from({ length: 2000 }, (_, index) => ({
- id: `Test ${index + 1}`,
- name: `CourseName ${index + 1}`,
- credits: 4,
- description: `This is a brief description of Course ${index + 1}.`,
-}));
-
-const subjectOptions = [
- { value: '', label: 'All Subjects' },
- { value: 'programming', label: 'Programming' },
- { value: 'math', label: 'Math' },
- { value: 'science', label: 'Science' },
-];
-
-const attributeOptions = [
- { value: '', label: 'All Attributes' },
- { value: 'programming', label: 'Programming' },
- { value: 'math', label: 'Math' },
- { value: 'science', label: 'Science' },
-];
-
-const semesterOptions = [
- { value: '', label: 'All Semesters' },
- { value: 'Fall', label: 'Fall' },
- { value: 'Spring', label: 'Spring' },
- { value: 'Summer', label: 'Summer' },
-];
-
const customStyles = {
control: (base) => ({
...base,
+ display: 'flex',
backgroundColor: 'none',
border: 'none',
lineHeight: '20px',
@@ -128,13 +101,101 @@ const customStyles = {
}),
menu: (base) => ({
...base,
- width: '400px',
}),
indicatorSeparator: () => ({ display: 'none' }),
};
+const subjectOptions = [
+ { value: '', label: 'All Subjects' },
+ { value: 'programming', label: 'Programming' },
+ { value: 'math', label: 'Math' },
+ { value: 'science', label: 'Science' },
+ // Add more subjects as needed
+];
+
+const attributeOptions = [
+ { value: '', label: 'All Attributes' },
+ { value: 'online', label: 'Online' },
+ { value: 'in-person', label: 'In-Person' },
+ // Add more attributes as needed
+];
+
+const semesterOptions = [
+ { value: '', label: 'All Semesters' },
+ { value: 'Fall', label: 'Fall' },
+ { value: 'Spring', label: 'Spring' },
+ { value: 'Summer', label: 'Summer' },
+ // Add more semesters as needed
+];
+
+const HOST = process.env.REACT_APP_API_HOST;
+
const SearchCourse = ({ isToolboxExpanded }) => {
const [showFilterOptions, setShowFilterOptions] = useState(false);
+ const [courses, setCourses] = useState([]);
+ const [searchPrompt, setSearchPrompt] = useState('');
+ const [selectedSubjects, setSelectedSubjects] = useState([]);
+ const [selectedAttributes, setSelectedAttributes] = useState([]);
+ const [selectedSemesters, setSelectedSemesters] = useState([]);
+ const [openCourses, setOpenCourses] = useState([]);
+
+ useEffect(() => {
+ const fetchCourses = async () => {
+ try {
+ const response = await axios.get(`${HOST}/api/v1/course/all`);
+ setCourses(response.data);
+ setOpenCourses(Array(response.data.length).fill(false));
+ } catch (error) {
+ console.error('Error fetching courses:', error);
+ }
+ };
+
+ fetchCourses();
+ }, []);
+
+ const handleSearch = async () => {
+ const params = new URLSearchParams();
+
+ if (searchPrompt) {
+ params.append('searchPrompt', searchPrompt);
+ }
+ if (selectedSubjects.length > 0) {
+ params.append(
+ 'deptFilters',
+ selectedSubjects.map((s) => s.value).join(','),
+ );
+ }
+ if (selectedAttributes.length > 0) {
+ params.append(
+ 'attrFilters',
+ selectedAttributes.map((a) => a.value).join(','),
+ );
+ }
+ if (selectedSemesters.length > 0) {
+ params.append(
+ 'semFilters',
+ selectedSemesters.map((s) => s.value).join(','),
+ );
+ }
+
+ try {
+ const response = await axios.get(
+ `${HOST}/api/v1/course/search?${params.toString()}`,
+ );
+ setCourses(response.data);
+ setOpenCourses(Array(response.data.length).fill(false));
+ } catch (error) {
+ console.error('Error searching courses:', error);
+ }
+ };
+
+ const toggleDropdown = (index) => {
+ setOpenCourses((prev) => {
+ const newOpenCourses = [...prev];
+ newOpenCourses[index] = !newOpenCourses[index];
+ return newOpenCourses;
+ });
+ };
return (
{
type="text"
style={styles.input}
placeholder="Find Courses Here..."
+ value={searchPrompt}
+ onChange={(e) => setSearchPrompt(e.target.value)}
+ onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
/>
{
{!showFilterOptions &&

}
{showFilterOptions &&

}
+
{showFilterOptions && (
@@ -172,6 +237,10 @@ const SearchCourse = ({ isToolboxExpanded }) => {
name="subject"
options={subjectOptions}
styles={customStyles}
+ value={selectedSubjects}
+ onChange={setSelectedSubjects}
+ menuPosition={'fixed'}
+ isMulti
/>
@@ -184,6 +253,10 @@ const SearchCourse = ({ isToolboxExpanded }) => {
name="attribute"
options={attributeOptions}
styles={customStyles}
+ value={selectedAttributes}
+ onChange={setSelectedAttributes}
+ menuPosition={'fixed'}
+ isMulti
/>
@@ -196,12 +269,20 @@ const SearchCourse = ({ isToolboxExpanded }) => {
name="semester"
options={semesterOptions}
styles={customStyles}
+ value={selectedSemesters}
+ onChange={setSelectedSemesters}
+ menuPosition={'fixed'}
+ isMulti
/>
)}
-
+
);