diff --git a/backend/peer_notes/settings.py b/backend/peer_notes/settings.py index bef179d..cbaefc6 100644 --- a/backend/peer_notes/settings.py +++ b/backend/peer_notes/settings.py @@ -25,7 +25,9 @@ SECRET_KEY = "django-insecure-rh0s*u8$uugtt10cxbifjriaz%@&p1w!)c2=y^undd2*nx5 # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = ["10.20.4.109", "73.7.29.136", "localhost"] +ALLOWED_HOSTS = ["10.20.4.109", "73.7.29.136", "localhost", "127.0.0.1", "http://localhost:5173"] +# ALLOWED_HOSTS = [] + # Application definition @@ -50,6 +52,7 @@ REST_FRAMEWORK = { } MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", @@ -57,7 +60,6 @@ MIDDLEWARE = [ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", - "corsheaders.middleware.CorsMiddleware", ] ROOT_URLCONF = "peer_notes.urls" @@ -134,6 +136,7 @@ STATIC_URL = "static/" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" AUTH_USER_MODEL = "api.PeerUser" CORS_ALLOW_ALL_ORIGINS = True +CORS_ALLOW_ALL_METHODS = True # CORS_ALLOWED_ORIGINS = [ # "http://localhost:5173" # ] diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b4ef972..a2b5d29 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -31,12 +31,26 @@ export default function App() { ) } function Navbar() { + const linkStyle = { + textDecoration: 'none', + color: 'black', + background: '#B1D4E0', + padding: '8px 16px', + borderRadius: '5px', + margin: '0 5px' + }; const session = useContext(SessionContext); + const logout = () => { + destroySessionCookie(); + window.location.reload(); + } const links = session ? ( <> - Home - Logout + PeerNotes Logo + Home + Search + Logout ): ( Login diff --git a/frontend/src/assets/file.svg b/frontend/src/assets/file.svg new file mode 100644 index 0000000..fc1d4a2 --- /dev/null +++ b/frontend/src/assets/file.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/components/MainSearch.tsx b/frontend/src/components/MainSearch.tsx deleted file mode 100644 index 1a9617e..0000000 --- a/frontend/src/components/MainSearch.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import '../styles/MainScreenWrapper.css'; - -interface Filters { - professor: string; - course: string; - topic: string; -} - -const MainSearch: React.FC = () => { - const [filters, setFilters] = useState({ - professor: '', - course: '', - topic: '', - }); - - const navigate = useNavigate(); - - const handleChange = (event: React.ChangeEvent) => { - const { name, value } = event.target; - setFilters((prevFilters: Filters) => ({ - ...prevFilters, - [name]: value, - })); - }; - - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - const input = filters.toString() - const searchParams = new URLSearchParams(input) - navigate(`/results?${searchParams}`); - }; - - return ( - <> - PeerNotes Logo -
-
- - -
-
- - -
-
- - -
- -
- - ); -} - -export default MainSearch; diff --git a/frontend/src/hooks/sessionRedirect.ts b/frontend/src/hooks/sessionRedirect.ts index c90d30a..80ddd7c 100644 --- a/frontend/src/hooks/sessionRedirect.ts +++ b/frontend/src/hooks/sessionRedirect.ts @@ -8,7 +8,7 @@ export const useSessionRedirect = () => { // Redirect to home if session is defined useEffect(() => { if (session !== undefined) { - navigate('/'); + navigate('/search'); } }, [session, navigate]) } \ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 88bae49..63c137f 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -8,8 +8,8 @@ import { } from "react-router-dom"; import Login from './screens/Login.tsx'; import Signup from './screens/Signup.tsx'; -import Results from './components/Results.tsx'; -import MainSearch from './components/MainSearch.tsx'; +import Results from './screens/Results.tsx'; +import MainSearch from './screens/MainSearch.tsx'; const router = createBrowserRouter([ { diff --git a/frontend/src/screens/Login.tsx b/frontend/src/screens/Login.tsx index 23a1cd5..54e5da6 100644 --- a/frontend/src/screens/Login.tsx +++ b/frontend/src/screens/Login.tsx @@ -21,8 +21,15 @@ export default function Login() { }, body: JSON.stringify({ username, password }), }) - .then(() => { - navigate('/'); + .then(response => response.json()) + .then(data => { + console.log("Login response data:", data); + if (data.token) { + // localStorage.setItem('authToken', data.token); + navigate('/search'); + } else { + console.error('No token received:', data); + } }) .catch((error) => { console.error('Error:', error); diff --git a/frontend/src/screens/MainSearch.tsx b/frontend/src/screens/MainSearch.tsx new file mode 100644 index 0000000..6f3b840 --- /dev/null +++ b/frontend/src/screens/MainSearch.tsx @@ -0,0 +1,148 @@ +import React, { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import '../styles/MainScreenWrapper.css'; +import { getSessionCookie } from '../contexts/session'; +import { Professor, Course, Topic } from "../types/types"; + +interface Filters extends Record { + professor: string; + course: string; + topic: string; +} + +const MainSearch: React.FC = () => { + const [filters, setFilters] = useState({ + professor: '', + course: '', + topic: '', + }); + const [professors, setProfessors] = useState([]); + const [courses, setCourses] = useState([]); + const [topics, setTopics] = useState([]); + const navigate = useNavigate(); + + useEffect(() => { + // Fetch professors + fetchProfessors(); + // Fetch courses + fetchCourses(); + // Fetch topics + fetchTopics(); + }, []); + + const getAuthHeaders = () => { + const token = getSessionCookie(); + // const token = localStorage.getItem('authToken'); + console.log("Using token for API call:", token); + return { + 'Authorization': `Token ${token}`, + 'Content-Type': 'application/json' + }; + }; + + const fetchProfessors = async () => { + try { + const response = await fetch('http://localhost:8000/api/professors', { + method: 'GET', + headers: getAuthHeaders(), + }); + const data = await response.json(); + console.log("Professors fetched:", data); + + if (Array.isArray(data)) { + console.log("Professors fetched:", data); + setProfessors(data); + } else { + console.error('Data fetched is not an array:', data); + } + } catch (error) { + console.error('Error fetching professors:', error); + } + }; + + const fetchCourses = async () => { + try { + const response = await fetch('http://localhost:8000/api/courses', { + method: 'GET', + headers: getAuthHeaders(), + }); + const data = await response.json(); + if (Array.isArray(data)) { + setCourses(data); + } else { + console.error('Data fetched is not an array:', data); + } + } catch (error) { + console.error('Error fetching courses:', error); + } + }; + + const fetchTopics = async () => { + try { + const response = await fetch('http://localhost:8000/api/topics', { + method: 'GET', + headers: getAuthHeaders(), + }); + const data = await response.json(); + if (Array.isArray(data)) { + setTopics(data); + } else { + console.error('Data fetched is not an array:', data); + } + } catch (error) { + console.error('Error fetching topics:', error); + } + }; + + const handleChange = (event: React.ChangeEvent) => { + const { name, value } = event.target; + setFilters((prevFilters: Filters) => ({ + ...prevFilters, + [name]: value, + })); + }; + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + const searchParams = new URLSearchParams(filters); + navigate(`/results?${searchParams}`); + }; + + return ( + <> + PeerNotes Logo +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + ); +} + +export default MainSearch; diff --git a/frontend/src/components/Results.tsx b/frontend/src/screens/Results.tsx similarity index 94% rename from frontend/src/components/Results.tsx rename to frontend/src/screens/Results.tsx index 22e19e2..b8fb0ce 100644 --- a/frontend/src/components/Results.tsx +++ b/frontend/src/screens/Results.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; -import styles from '../screens/Results.module.css'; // Make sure this path is correct +import styles from '../styles/Results.module.css'; // Make sure this path is correct interface File { id: string; @@ -40,7 +40,7 @@ const Results: React.FC = () => { }, [location]); const handleSearchAgain = () => { - navigate('/'); + navigate('/search'); }; if (isLoading) return
Loading...
; diff --git a/frontend/src/styles/App.css b/frontend/src/styles/App.css index 2909c89..b77c0f5 100644 --- a/frontend/src/styles/App.css +++ b/frontend/src/styles/App.css @@ -1,12 +1,18 @@ nav { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1rem 2rem; - border: 3px solid #f1f1f1; - border-radius: 5px; - color: black; - background-color: white; + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + margin: 0; + width: 100%; + background-color: #145DA0; + border: none; + border-radius: 0; + position: fixed; + top: 0; + left: 0; + z-index: 1000; + box-sizing: border-box; } .App { display: flex; diff --git a/frontend/src/screens/Results.module.css b/frontend/src/styles/Results.module.css similarity index 100% rename from frontend/src/screens/Results.module.css rename to frontend/src/styles/Results.module.css diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts new file mode 100644 index 0000000..ff5b577 --- /dev/null +++ b/frontend/src/types/types.ts @@ -0,0 +1,15 @@ +export interface Professor { + id: number; + name: string; +} +export interface Course { + id: number; + name: string; + number: string; +} + +export interface Topic { + id: number; + name: string; + description: string; +} \ No newline at end of file