From b460067dfa8262b4a5821e51c5c735da196e936e Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 21 Apr 2024 15:42:12 -0400 Subject: [PATCH] add upload file boilerplate + changes to results page --- frontend/src/App.tsx | 4 +- frontend/src/main.tsx | 5 ++ frontend/src/screens/MainSearch.tsx | 30 +++++++++++- frontend/src/screens/RegisterFile.tsx | 66 ++++++++++++++++++++++++++ frontend/src/screens/Results.tsx | 39 ++++++++++----- frontend/src/styles/App.css | 5 ++ frontend/src/styles/RegisterFile.css | 48 +++++++++++++++++++ frontend/src/styles/Results.module.css | 15 ++++++ frontend/src/types/types.ts | 8 ++++ 9 files changed, 206 insertions(+), 14 deletions(-) create mode 100644 frontend/src/screens/RegisterFile.tsx create mode 100644 frontend/src/styles/RegisterFile.css diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c97b420..27f8456 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -23,7 +23,7 @@ export default function App() { <> -
+
@@ -49,7 +49,7 @@ function Navbar() { <>
PeerNotes Logo - Home + Upload Search
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 63c137f..e47fb01 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -10,6 +10,7 @@ import Login from './screens/Login.tsx'; import Signup from './screens/Signup.tsx'; import Results from './screens/Results.tsx'; import MainSearch from './screens/MainSearch.tsx'; +import RegisterFile from './screens/RegisterFile.tsx'; const router = createBrowserRouter([ { @@ -25,6 +26,10 @@ const router = createBrowserRouter([ path: "results", element: , }, + { + path: "register", + element: , + }, ] }, diff --git a/frontend/src/screens/MainSearch.tsx b/frontend/src/screens/MainSearch.tsx index c65377a..98b98bd 100644 --- a/frontend/src/screens/MainSearch.tsx +++ b/frontend/src/screens/MainSearch.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import '../styles/MainScreenWrapper.css'; import { getAuthHeaders } from '../utils/getAuthHeaders'; -import { Professor, Course, Topic } from "../types/types"; +import { Professor, Course, Topic, Semester } from "../types/types"; interface Filters extends Record { professor: string; @@ -19,6 +19,7 @@ const MainSearch: React.FC = () => { const [professors, setProfessors] = useState([]); const [courses, setCourses] = useState([]); const [topics, setTopics] = useState([]); + const [semesters, setSemesters] = useState([]); const navigate = useNavigate(); useEffect(() => { @@ -28,6 +29,8 @@ const MainSearch: React.FC = () => { fetchCourses(); // Fetch topics fetchTopics(); + // Fetch semesters + fetchSemesters(); }, []); @@ -82,6 +85,22 @@ const MainSearch: React.FC = () => { console.error('Error fetching topics:', error); } }; + const fetchSemesters = async () => { + try { + const response = await fetch('http://localhost:8000/api/semesters', { + method: 'GET', + headers: getAuthHeaders(), + }); + const data = await response.json(); + if (Array.isArray(data)) { + setSemesters(data); + } else { + console.error('Data fetched is not an array:', data); + } + } catch (error) { + console.error('Error fetching courses:', error); + } + }; const handleChange = (event: React.ChangeEvent) => { const { name, value } = event.target; @@ -128,6 +147,15 @@ const MainSearch: React.FC = () => { ))}
+
+ + +
diff --git a/frontend/src/screens/RegisterFile.tsx b/frontend/src/screens/RegisterFile.tsx new file mode 100644 index 0000000..78fab0a --- /dev/null +++ b/frontend/src/screens/RegisterFile.tsx @@ -0,0 +1,66 @@ +import "../styles/RegisterFile.css"; +import { RegisteredFile } from "../types/types"; +import { useState, useEffect } from "react"; + +export default function RegisterFile() { + const [registeredFiles, setRegisteredFiles] = useState([]); + + useEffect(() => { + fetchRegisteredFiles(); + }, []) + const fetchRegisteredFiles = () => { + return + fetch("http://localhost:5000/files") // replace with local api endpoint + .then(response => response.json()) + .then(data => { + setRegisteredFiles(data); + }) + .catch(error => console.error(error)); + } + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + // handle file upload + const formData = new FormData(event.target as HTMLFormElement); + const file = formData.get('file'); + console.log(file, typeof file) + + } + return ( +
+
+

Upload a File

+

Host a local file for the GT community!

+
+ + + +
+
+
+

Registered Files

+ + + + + + + + + + + + {registeredFiles.map((file) => ( + + + + + + + + ))} + +
File NameOriginal AuthorProfessorSemesterStatus
{file.filename}{file.original_author.username}{file.professor.name}{file.semester.name}{file.status}
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/screens/Results.tsx b/frontend/src/screens/Results.tsx index 573477a..f889044 100644 --- a/frontend/src/screens/Results.tsx +++ b/frontend/src/screens/Results.tsx @@ -49,17 +49,34 @@ const Results: React.FC = () => { {isLoading ? (

Loading...

) : files.length ? ( - files.map((file) => ( -
-

{file.filename}

-

Course: {file.course.name} {file.course.number}

-

Professor: {file.professor.name}

-

Semester: {file.semester.name}

-

Upvotes: {file.upvotes.length}

-

Downvotes: {file.downvotes.length}

-

Download

-
- )) + + + + + + + + + + + + + + + {files.map((file) => ( + + + + + + + + + + + ))} + +
FilenameCourseProfessorSemesterUpvotesDownvotesOriginal AuthorDownload
{file.filename}{file.course.name} {file.course.number}{file.professor.name}{file.semester.name}{file.upvotes.length}{file.downvotes.length}{file.original_author.username}Download
) : (

No results found.

)} diff --git a/frontend/src/styles/App.css b/frontend/src/styles/App.css index 8d255d0..f7ca5de 100644 --- a/frontend/src/styles/App.css +++ b/frontend/src/styles/App.css @@ -1,3 +1,6 @@ +html { + width: 100%; +} nav { display: flex; justify-content: space-between; @@ -26,10 +29,12 @@ nav div { justify-content: center; /* If you're centering the content */ height: 100vh; /* Full height */ margin-top: -100px; /* Move up */ + width: 100%; } body { background-color: #0C2D48; font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif; + width: 100%; } \ No newline at end of file diff --git a/frontend/src/styles/RegisterFile.css b/frontend/src/styles/RegisterFile.css new file mode 100644 index 0000000..d1be3a4 --- /dev/null +++ b/frontend/src/styles/RegisterFile.css @@ -0,0 +1,48 @@ +h1 { +color: white; +} +.container { + display: flex; + gap: 10rem; + justify-content: space-between; +} + +.file-upload-card { + padding: 1em; + background-color: #B1D4E0; + border-radius: 5px; +} +.file-upload-card h1 { + color: black; +} + +.file-card { + padding: 1em; + background-color: #2E8BC0; + border-radius: 5px; + display: flex; + flex-direction: row; +} + .submit-button { + padding: 8px 16px; + margin-top: 20px; /* Adds space above the button */ + background-color: #2E8BC0; /* Example background color */ + color: white; /* Text color */ + border: none; + border-radius: 4px; + cursor: pointer; + font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif; + } + + th { + text-align: center; + padding: 1rem; + border: 1px solid #FFFFFF; + color: white; + } + td { + text-align: center; + border: 1px solid #FFFFFF; + background-color: #B1D4E0; + color: black; + } diff --git a/frontend/src/styles/Results.module.css b/frontend/src/styles/Results.module.css index 88bbef0..f488d55 100644 --- a/frontend/src/styles/Results.module.css +++ b/frontend/src/styles/Results.module.css @@ -70,4 +70,19 @@ .searchAgainButton:hover { background-color: #B1D4E0; /* lighter shade for hover effect */ + } + + table { + width: 100%; + } + th { + text-align: center; + padding: 1rem; + border: 1px solid #FFFFFF; + } + td { + text-align: center; + border: 1px solid #FFFFFF; + background-color: #B1D4E0; + color: black; } \ No newline at end of file diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts index 579b27b..2d7d0ee 100644 --- a/frontend/src/types/types.ts +++ b/frontend/src/types/types.ts @@ -36,4 +36,12 @@ export interface File { semester: Semester; upvotes: number[]; downvotes: number[]; +} + +enum Status { + HOSTED = "HOSTED", + PRIVATE = 'PRIVATE', +} +export interface RegisteredFile extends File { + status: Status; } \ No newline at end of file