Merge branch 'main' of github.com:AmanTahiliani/PeerNotes

This commit is contained in:
2024-04-12 17:29:02 -04:00
7 changed files with 209 additions and 19 deletions

View File

@@ -1,6 +1,6 @@
import "./styles/App.css";
import { Link, useNavigate } from 'react-router-dom';
import MainSearch from './components/MainSearch';
import { Outlet } from "react-router-dom";
import { SessionContext, destroySessionCookie, getSessionCookie } from "./contexts/session";
import { useState, useEffect, useContext } from "react";
@@ -24,14 +24,7 @@ export default function App() {
<SessionContext.Provider value={session}>
<Navbar />
<div className="App" style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', height: '90vh' , gap: 15}}>
<img
src="/PeerNotes.png"
alt="PeerNotes Logo"
style={{
height: "100px"
}}
/>
<MainSearch />
<Outlet />
</div>
</SessionContext.Provider>
</>

View File

@@ -1,38 +1,77 @@
import React from 'react';
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<Filters>({
professor: '',
course: '',
topic: '',
});
const navigate = useNavigate();
const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const { name, value } = event.target;
setFilters((prevFilters: Filters) => ({
...prevFilters,
[name]: value,
}));
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const input = filters.toString()
const searchParams = new URLSearchParams(input)
navigate(`/results?${searchParams}`);
};
return (
<div className="filter-container">
<>
<img
src="/PeerNotes.png"
alt="PeerNotes Logo"
style={{
height: "100px"
}}
/>
<form onSubmit={handleSubmit} className="filter-container">
<div className="filter-item">
<label htmlFor="professors">Professors:</label>
<select id="professors">
<select id="professors" name="professor" value={filters.professor} onChange={handleChange}>
<option value="">Select a Professor</option>
{/* temporary */}
{/* temporary options */}
<option value="professor1">Professor 1</option>
<option value="professor2">Professor 2</option>
</select>
</div>
<div className="filter-item">
<label htmlFor="courses">Course:</label>
<select id="courses">
<select id="courses" name="course" value={filters.course} onChange={handleChange}>
<option value="">Select a Course</option>
{/* temporary */}
{/* temporary options */}
<option value="course1">Course 1</option>
<option value="course2">Course 2</option>
</select>
</div>
<div className="filter-item">
<label htmlFor="topics">Topic:</label>
<select id="topics">
<select id="topics" name="topic" value={filters.topic} onChange={handleChange}>
<option value="">Select a Topic</option>
{/* temporary */}
{/* temporary options */}
<option value="topic1">Topic 1</option>
<option value="topic2">Topic 2</option>
</select>
</div>
<button type="submit" className="submit-button">Submit</button>
</div>
</form>
</>
);
}

View File

@@ -0,0 +1,69 @@
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
interface File {
id: string;
name: string; // do we even use id and name?
professor: string;
course: string;
type?: string; // Assumed type is optional
// what other properties to add?semester?
}
const Results: React.FC = () => {
const [files, setFiles] = useState<File[]>([]);
const [isLoading, setLoading] = useState(false);
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
const fetchFiles = async () => {
setLoading(true);
try {
// Need to double check this
const queryString = location.search; // Includes the '?' prefix
const response = await fetch(`/api/path-to-filefilterview${queryString}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setFiles(data);
} catch (e) {
console.error("Could not fetch files", e);
} finally {
setLoading(false);
}
};
fetchFiles();
}, [location]);
const handleSearchAgain = () => {
navigate('/');
};
if (isLoading) return <div>Loading...</div>;
return (
<div className={styles.wrapper}>
<div className={styles.header}>
<img src="/PeerNotes.png" alt="PeerNotes Logo" className={styles.logo} />
<button onClick={handleSearchAgain} className={styles.searchAgainButton}>Search Again</button>
</div>
<div className={styles.resultsContainer}>
{isLoading ? (
<p>Loading...</p>
) : files.length ? (
<table className={styles.resultsTable}>
{/* Table structure here */}
</table>
) : (
<p>No results found.</p>
)}
</div>
</div>
);
};
export default Results;

View File

@@ -8,6 +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';
const router = createBrowserRouter([
{
@@ -15,8 +17,17 @@ const router = createBrowserRouter([
element: <App />,
children: [
// add more routes here
{
path: "search",
element: <MainSearch />,
},
{
path: "results",
element: <Results/>,
},
]
},
{
path: "/login",
element: <Login />,

View File

@@ -0,0 +1,57 @@
.wrapper {
display: flex;
flex-direction: column;
height: 100vh;
color: #FFFFFF;
}
.header {
display: flex;
justify-content: space-between;
padding: 10px 20px;
position: fixed;
width: 100%;
top: 0;
left: 0;
background-color: #145DA0;
}
.logo {
height: 80px; /* Adjust according to preference */
margin-right: auto;
}
.resultsContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 100px; /* Adjust based on header height to ensure content doesn't overlap */
margin: auto;
width: 90%;
max-width: 600px;
}
.resultsTable {
/* to be filled out */
width: 100%;
}
.searchAgainButton {
height: 50px;
padding: 4px 8px;
background-color: #0C2D48;
color: white;
border: none;
border-radius: 4px;
font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
cursor: pointer;
margin-right: 35px;
margin-top: 15px;
}
.searchAgainButton:hover {
background-color: #B1D4E0; /* lighter shade for hover effect */
}

View File

@@ -7,4 +7,18 @@ nav {
border-radius: 5px;
color: black;
background-color: white;
}
}
.App {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center; /* If you're centering the content */
height: 100vh; /* Full height */
margin-top: -100px; /* Move up */
}
body {
background-color: #0C2D48;
font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
}

View File

@@ -15,9 +15,16 @@ html, body {
justify-content: center;
padding: 20px;
background: #B1D4E0;
gap: 15;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* shadow */
}
.logo {
height: 100px; /* Adjust this value as needed */
width: auto; /* Keep the logo's aspect ratio */
margin-bottom: 15px; /* Gap between logo and search box */
}
.filter-item + .filter-item {
margin-top: 20px; /* space between filter items */