mirror of
https://github.com/AmanTahiliani/PeerNotes.git
synced 2026-08-07 11:55:12 -04:00
Merge pull request #9 from AmanTahiliani/filterpage_sahej
Second page on search results
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
69
frontend/src/components/Results.tsx
Normal file
69
frontend/src/components/Results.tsx
Normal 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;
|
||||
@@ -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 />,
|
||||
|
||||
57
frontend/src/screens/Results.module.css
Normal file
57
frontend/src/screens/Results.module.css
Normal 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 */
|
||||
}
|
||||
@@ -8,3 +8,17 @@ nav {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -15,10 +15,17 @@ 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 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user