From 4b1cb0e7f18004b19091ad18598930a4d121050a Mon Sep 17 00:00:00 2001
From: JBB0807 <104856796+JBB0807@users.noreply.github.com>
Date: Mon, 5 May 2025 14:51:13 -0700
Subject: [PATCH 1/6] submit assignment now creates a fly machine
---
src/pages/AssignmentPage.jsx | 66 +++++++++++++++++++++++++++++-------
1 file changed, 54 insertions(+), 12 deletions(-)
diff --git a/src/pages/AssignmentPage.jsx b/src/pages/AssignmentPage.jsx
index d8b5941..e0bec79 100644
--- a/src/pages/AssignmentPage.jsx
+++ b/src/pages/AssignmentPage.jsx
@@ -5,10 +5,12 @@ const AssignmentPage = () => {
const [studentName, setStudentName] = useState("");
const [campID, setCampID] = useState("");
const [programID, setProgramID] = useState("");
+ const [appName, setAppName] = useState("");
+ const [qrCodeNumber, setQrCodeNumber] = useState("");
const [password, setPassword] = useState("");
- const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [file, setFile] = useState(null);
+
const [projects, setProjects] = useState([]);
const [showModal, setShowModal] = useState(false);
const [editingIndex, setEditingIndex] = useState(null);
@@ -44,7 +46,6 @@ const AssignmentPage = () => {
setCampID("");
setProgramID("");
setPassword("");
- setTitle("");
setDescription("");
setFile(null);
setEditingIndex(null);
@@ -56,12 +57,48 @@ const AssignmentPage = () => {
const newProject = {
studentname: studentName,
campid: campID,
+ appname: appName,
+ qrcodenumber: qrCodeNumber,
+ passwordhash: password,
programid: programID,
- title,
description,
- fileName: file ? file.name : null,
+ file: file,
+ intructorid: 9,
};
+ //callt the api to upload a new assignment
+ const formData = new FormData();
+ formData.append("studentname", studentName);
+ formData.append("campid", campID);
+ formData.append("programid", programID);
+ formData.append("appname", appName);
+ formData.append("qrcodenumber", qrCodeNumber);
+ formData.append("password", password);
+ formData.append("description", description);
+ formData.append("intructoid", 9);
+ if (file) {
+ formData.append("file", file, file.name);
+ }
+
+ fetch("http://localhost:8082/instructor/create", {
+ method: "POST",
+ body: formData,
+ })
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error("Failed to submit assignment");
+ }
+ return response.json();
+ })
+ .then((data) => {
+ console.log("Assignment submitted successfully:", data);
+ fetchAssignments(); // Refresh the assignments list
+ })
+ .catch((error) => {
+ console.error("Error submitting assignment:", error);
+ alert("Failed to submit assignment. Please try again.");
+ });
+
if (editingIndex !== null) {
const updatedProjects = [...projects];
updatedProjects[editingIndex] = newProject;
@@ -80,7 +117,6 @@ const AssignmentPage = () => {
setStudentName(project.studentname || project.studentName || "");
setCampID(project.campid || project.campID || "");
setProgramID(project.programid || project.programID || "");
- setTitle(project.title || "");
setDescription(project.description || "");
setFile(null);
setEditingIndex(index);
@@ -111,12 +147,23 @@ const AssignmentPage = () => {
- setCampID(e.target.value)} required />
+ setCampID(e.target.value)} required />
- setProgramID(e.target.value)} required />
+ setProgramID(e.target.value)} required />
+
+
+
+
+ setAppName(e.target.value)} required />
+
+
+
+
+
+ setQrCodeNumber(e.target.value)} required />
@@ -124,11 +171,6 @@ const AssignmentPage = () => {
setPassword(e.target.value)} required />
-
-
- setTitle(e.target.value)} required />
-
-
From 8e1af2e846878a3db37ca4e64a97800e9cc606db Mon Sep 17 00:00:00 2001
From: JBB0807 <104856796+JBB0807@users.noreply.github.com>
Date: Mon, 5 May 2025 18:49:51 -0700
Subject: [PATCH 2/6] added changes to verify student using QR code number and
password instead
---
src/pages/AssignmentPage.jsx | 2 +-
src/pages/SignIn.jsx | 14 +++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/pages/AssignmentPage.jsx b/src/pages/AssignmentPage.jsx
index e0bec79..985ff15 100644
--- a/src/pages/AssignmentPage.jsx
+++ b/src/pages/AssignmentPage.jsx
@@ -75,7 +75,7 @@ const AssignmentPage = () => {
formData.append("qrcodenumber", qrCodeNumber);
formData.append("password", password);
formData.append("description", description);
- formData.append("intructoid", 9);
+ formData.append("instructorid", 9);
if (file) {
formData.append("file", file, file.name);
}
diff --git a/src/pages/SignIn.jsx b/src/pages/SignIn.jsx
index ff2372e..9f6462e 100644
--- a/src/pages/SignIn.jsx
+++ b/src/pages/SignIn.jsx
@@ -5,7 +5,7 @@ const authUrl = import.meta.env.VITE_AUTH_URL;
function SignInForm() {
const [state, setState] = React.useState({
- assignmentID: "",
+ qrNumber: "",
password: "",
});
const handleChange = (evt) => {
@@ -19,8 +19,8 @@ function SignInForm() {
const handleOnSubmit = (evt) => {
evt.preventDefault();
- const { assignmentId, password } = state;
- console.log(`You are loggind in with email: ${assignmentId} and password: ${password}`);
+ const { qrNumber, password } = state;
+ console.log(`You are loggind in with email: ${qrNumber} and password: ${password}`);
console.log("Submitting login request with state:", state);
fetch(`${authUrl}/auth/student/login`, {
@@ -59,10 +59,10 @@ function SignInForm() {
*/}
Date: Mon, 5 May 2025 19:03:02 -0700
Subject: [PATCH 3/6] change harcoded URL to .env/secrets
---
.env | 4 ++--
.env.development | 2 +-
src/pages/AssignmentPage.jsx | 6 ++++--
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/.env b/.env
index ddf3a43..827b820 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
-#VITE_AUTH_URL="http://localhost:8080"
-VITE_AUTH_URL="https://byte-camp-auth-service.fly.dev"
\ No newline at end of file
+VITE_AUTH_URL="https://byte-camp-auth-service.fly.dev"
+VITE_ASSIGNMENT_URL="https://assignment-service.internal"
\ No newline at end of file
diff --git a/.env.development b/.env.development
index 7dc9c2c..7affb16 100644
--- a/.env.development
+++ b/.env.development
@@ -1,2 +1,2 @@
VITE_AUTH_URL="http://localhost:8080"
-#VITE_AUTH_URL="https://byte-camp-auth-service.fly.dev"
\ No newline at end of file
+VITE_ASSIGNMENT_URL="http://localhost:8082"
\ No newline at end of file
diff --git a/src/pages/AssignmentPage.jsx b/src/pages/AssignmentPage.jsx
index 985ff15..ba560b7 100644
--- a/src/pages/AssignmentPage.jsx
+++ b/src/pages/AssignmentPage.jsx
@@ -15,6 +15,8 @@ const AssignmentPage = () => {
const [showModal, setShowModal] = useState(false);
const [editingIndex, setEditingIndex] = useState(null);
+ const VITE_ASSIGNMENT_URL = import.meta.env.VITE_ASSIGNMENT_URL;
+
useEffect(() => {
document.title = "Assignment";
fetchAssignments();
@@ -22,7 +24,7 @@ const AssignmentPage = () => {
const fetchAssignments = async () => {
try {
- const res = await fetch("http://localhost:8082/instructor/list/9", {
+ const res = await fetch(`${VITE_ASSIGNMENT_URL}/instructor/list/9`, {
// credentials: "include",
});
if (!res.ok) throw new Error("Failed to fetch");
@@ -80,7 +82,7 @@ const AssignmentPage = () => {
formData.append("file", file, file.name);
}
- fetch("http://localhost:8082/instructor/create", {
+ fetch(`${VITE_ASSIGNMENT_URL}/instructor/create`, {
method: "POST",
body: formData,
})
From 8a62bbfa1ed3f33f12614ef694167c07ce1eacb8 Mon Sep 17 00:00:00 2001
From: JBB0807 <104856796+JBB0807@users.noreply.github.com>
Date: Mon, 5 May 2025 19:22:38 -0700
Subject: [PATCH 4/6] adjusted monaco editor to get the QR Code number instead
of assignment id
---
src/pages/CodeEditor.jsx | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/pages/CodeEditor.jsx b/src/pages/CodeEditor.jsx
index 709f84c..f16f689 100644
--- a/src/pages/CodeEditor.jsx
+++ b/src/pages/CodeEditor.jsx
@@ -4,8 +4,11 @@ import EditorPanel from "../components/EditorPanel";
import PreviewPanel from "../components/PreviewPanel";
export default function PageCodeEditor() {
- const { assignmentId: routeId } = useParams();
- const assignmentId = routeId || "52";
+
+ const { qrCodeNumber: routeId } = useParams();
+ // console.log("Assignment ID:", assignmentId);
+ const qrCodeNumber = routeId || "2256";
+ console.log("QR Code Number:", qrCodeNumber);
const [appName, setAppName] = useState("");
const [code, setCode] = useState("# NOW LOADING");
@@ -15,14 +18,14 @@ export default function PageCodeEditor() {
}, []);
useEffect(() => {
- fetch(`https://assignment-service.fly.dev/student/assignment/${assignmentId}`)
+ fetch(`https://assignment-service.fly.dev/student/assignment/${qrCodeNumber}`)
.then((res) => {
if (!res.ok) throw new Error("Failed to fetch assignment");
return res.json();
})
.then((data) => setAppName(data.appname))
.catch((err) => console.error("Assignment fetch error:", err));
- }, [assignmentId]);
+ }, [qrCodeNumber]);
useEffect(() => {
if (!appName) return;
From 4ee194f102272d6212bd36c975a433946cafdaba Mon Sep 17 00:00:00 2001
From: JBB0807 <104856796+JBB0807@users.noreply.github.com>
Date: Mon, 5 May 2025 23:38:31 -0700
Subject: [PATCH 5/6] validation for existing appname and qrcode
---
.env | 2 +-
src/pages/AssignmentPage.jsx | 336 +++++++++++++++++++++++++++--------
2 files changed, 267 insertions(+), 71 deletions(-)
diff --git a/.env b/.env
index 827b820..d44cade 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
VITE_AUTH_URL="https://byte-camp-auth-service.fly.dev"
-VITE_ASSIGNMENT_URL="https://assignment-service.internal"
\ No newline at end of file
+VITE_ASSIGNMENT_URL="http://assignment-service.internal"
\ No newline at end of file
diff --git a/src/pages/AssignmentPage.jsx b/src/pages/AssignmentPage.jsx
index ba560b7..4601c70 100644
--- a/src/pages/AssignmentPage.jsx
+++ b/src/pages/AssignmentPage.jsx
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import "../scss/components/_assignment.scss";
const AssignmentPage = () => {
+ const [assignmentId, setAssignmentId] = useState("");
const [studentName, setStudentName] = useState("");
const [campID, setCampID] = useState("");
const [programID, setProgramID] = useState("");
@@ -10,27 +11,97 @@ const AssignmentPage = () => {
const [password, setPassword] = useState("");
const [description, setDescription] = useState("");
const [file, setFile] = useState(null);
-
+
const [projects, setProjects] = useState([]);
const [showModal, setShowModal] = useState(false);
const [editingIndex, setEditingIndex] = useState(null);
+ const [user, setUser] = useState([]);
+
const VITE_ASSIGNMENT_URL = import.meta.env.VITE_ASSIGNMENT_URL;
+ const authUrl = import.meta.env.VITE_AUTH_URL;
useEffect(() => {
document.title = "Assignment";
+ getCurrentUser();
fetchAssignments();
}, []);
+ useEffect(() => {
+ if (!appName) return; // Don't alert for empty name
+ const timer = setTimeout(() => {
+ fetch(`${VITE_ASSIGNMENT_URL}/instructor/checkAssignmentByAppName/${appName}`)
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error("Failed to fetch assignment by app name");
+ }
+ return response.json();
+ })
+ .then((data) => {
+ if (data.exists) {
+ alert("This app name already exists. Please choose a different one.");
+ }
+ })
+ .catch((error) => {
+ console.error("Error fetching assignment by app name:", error);
+ });
+ }, 1000); // 1 second delay
+
+ return () => clearTimeout(timer); // Clear timeout on name change
+ }, [appName]);
+
+ useEffect(() => {
+ if (!qrCodeNumber) return; // Don't alert for empty QR code number
+ console.log("Checking QR code number:", qrCodeNumber); // Added console log
+ const timer = setTimeout(() => {
+ fetch(`${VITE_ASSIGNMENT_URL}/instructor/checkAssignmentByQRCode/${qrCodeNumber}`)
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error("Failed to fetch assignment by QR code number");
+ }
+ return response.json();
+ })
+ .then((data) => {
+ console.log("QR code fetch result:", data); // Added console log
+ if (data.exists) {
+ alert("This QR code number already exists. Please choose a different one.");
+ }
+ })
+ .catch((error) => {
+ console.error("Error fetching assignment by QR code number:", error);
+ });
+ }, 1000); // 1 second delay
+
+ return () => clearTimeout(timer); // Clear timeout on QR code number change
+ }, [qrCodeNumber]);
+
+ const getCurrentUser = async () => {
+ try {
+ const authResponse = await fetch(`${authUrl}/auth/current_user`, {
+ credentials: "include",
+ });
+
+ const user = await authResponse.json();
+ setUser(user);
+ } catch (error) {
+ console.error("Error fetching current user:", error);
+ }
+ };
+
const fetchAssignments = async () => {
try {
+ // if (user) {
+ // console.log("Current user:", user, `${VITE_ASSIGNMENT_URL}/instructor/list/${user.userId}`);
+ // const res = await fetch(`${VITE_ASSIGNMENT_URL}/instructor/list/${user.userId}`, {
+ // // credentials: "include",
+ // });
+ //replace this with commented code above to get the instructor id from the auth service
const res = await fetch(`${VITE_ASSIGNMENT_URL}/instructor/list/9`, {
// credentials: "include",
});
- if (!res.ok) throw new Error("Failed to fetch");
+ if (!res.ok) throw new Error("Failed to fetch");
const data = await res.json();
-
// Optional: Remove duplicate assignment IDs if needed
const unique = Array.from(
@@ -38,6 +109,7 @@ const AssignmentPage = () => {
);
setProjects(unique);
+ // }
} catch (error) {
console.error("Error fetching assignments:", error);
}
@@ -53,69 +125,87 @@ const AssignmentPage = () => {
setEditingIndex(null);
};
- const handleSubmit = (e) => {
+ const handleSubmit = async (e) => {
e.preventDefault();
- const newProject = {
- studentname: studentName,
- campid: campID,
- appname: appName,
- qrcodenumber: qrCodeNumber,
- passwordhash: password,
- programid: programID,
- description,
- file: file,
- intructorid: 9,
- };
+ if (!user.userId) return alert("Please login to submit an assignment.");
- //callt the api to upload a new assignment
+ //Create the form data needed for both create and edit
const formData = new FormData();
formData.append("studentname", studentName);
formData.append("campid", campID);
formData.append("programid", programID);
- formData.append("appname", appName);
formData.append("qrcodenumber", qrCodeNumber);
formData.append("password", password);
formData.append("description", description);
- formData.append("instructorid", 9);
- if (file) {
- formData.append("file", file, file.name);
- }
-
- fetch(`${VITE_ASSIGNMENT_URL}/instructor/create`, {
- method: "POST",
- body: formData,
- })
- .then((response) => {
- if (!response.ok) {
- throw new Error("Failed to submit assignment");
- }
- return response.json();
- })
- .then((data) => {
- console.log("Assignment submitted successfully:", data);
- fetchAssignments(); // Refresh the assignments list
- })
- .catch((error) => {
- console.error("Error submitting assignment:", error);
- alert("Failed to submit assignment. Please try again.");
- });
if (editingIndex !== null) {
- const updatedProjects = [...projects];
- updatedProjects[editingIndex] = newProject;
- setProjects(updatedProjects);
+ //edit mode
+ await fetch(`${VITE_ASSIGNMENT_URL}/instructor/update/${assignmentId}`, {
+ method: "PUT",
+ body: formData,
+ })
+ .then((response) => {
+
+ if (!response.ok) {
+ console.error("Failed to edit assignment:", response.statusText);
+ throw new Error("Failed to edit assignment");
+ }
+ return response.json();
+ })
+ .then((data) => {
+ console.log("Assignment edited successfully:", data);
+ })
+ .catch((error) => {
+ console.error("Error submitting assignment:", error);
+ alert(`Failed to submit assignment. ${error.message}`);
+ });
} else {
- setProjects([...projects, newProject]);
+ //create mode
+ formData.append("instructorid", 9);
+ formData.append("appname", appName);
+
+ if (file) {
+ formData.append("file", file, file.name);
+ } else {
+ throw new Error("Failed to submit assignment: file not found.");
+ }
+
+ await fetch(`${VITE_ASSIGNMENT_URL}/instructor/create`, {
+ method: "POST",
+ body: formData,
+ })
+ .then((response) => {
+ if (!response.ok) {
+ console.error("Failed to submit assignment:", response.statusText);
+ throw new Error("Failed to submit assignment");
+ }
+ return response.json();
+ })
+ .then((data) => {
+ console.log("Assignment submitted successfully:", data);
+ })
+ .catch((error) => {
+ console.error("Error submitting assignment:", error);
+ alert(`Failed to submit assignment. ${error.message}`);
+ });
}
- alert(editingIndex !== null ? "Assignment updated!" : "Assignment submitted!");
+ alert(
+ editingIndex !== null ? "Assignment updated!" : "Assignment submitted!"
+ );
+
+ fetchAssignments(); // Refresh the assignments list
resetForm();
setShowModal(false);
};
const handleEdit = (index) => {
const project = projects[index];
+ setAssignmentId(project.assignmentid || project.assignmentId || "");
+ setAppName(project.appname || project.appName || "");
+ setQrCodeNumber(project.qrcodenumber || project.qrCodeNumber || "");
+ setPassword(project.passwordhash || project.password || "");
setStudentName(project.studentname || project.studentName || "");
setCampID(project.campid || project.campID || "");
setProgramID(project.programid || project.programID || "");
@@ -126,66 +216,145 @@ const AssignmentPage = () => {
};
const handleDelete = (index) => {
- const updated = projects.filter((_, i) => i !== index);
- setProjects(updated);
+ const project = projects[index];
+ if (window.confirm("Are you sure you want to delete this assignment?")) {
+ fetch(`${VITE_ASSIGNMENT_URL}/instructor/delete/${project.assignmentid}`, {
+ method: "DELETE",
+ })
+ .then((response) => {
+ if (!response.ok) {
+ console.error("Failed to delete assignment:", response.statusText);
+ throw new Error("Failed to delete assignment");
+ }
+ return response.json();
+ })
+ .then((data) => {
+ console.log("Assignment deleted successfully:", data);
+ alert("Assignment deleted successfully!");
+ fetchAssignments(); // Refresh the assignments list
+ })
+ .catch((error) => {
+ console.error("Error deleting assignment:", error);
+ alert(`Failed to delete assignment. ${error.message}`);
+ });
+ }
};
return (
Assignments
-
+
{showModal && (
-
{editingIndex !== null ? "Edit Assignment" : "New Assignment"}
+
+ {editingIndex !== null ? "Edit Assignment" : "New Assignment"}
+
@@ -197,31 +366,58 @@ const AssignmentPage = () => {
{projects.map((project, index) => (
- Student Name: {project.studentname || project.studentName} |{" "}
+ Student Name:{" "}
+ {project.studentname || project.studentName} |{" "}
CampID: {project.campid || project.campID} |{" "}
- ProgramID: {project.programid || project.programID}
+ ProgramID:{" "}
+ {project.programid || project.programID}
{project.title &&
{project.title}
}
{project.description &&
{project.description}
}
- {project.fileName &&
Uploaded File: {project.fileName}
}
+ {project.fileName && (
+
+ Uploaded File: {project.fileName}
+
+ )}
{project.assignmenturl && (
- View Assignment
+
+ View Assignment
+
)}
{project.originalfile && (
- Original File |{" "}
- Editable File
+
+ Original File
+ {" "}
+ |{" "}
+
+ Editable File
+
)}
-
+
))}
From a28dc7d3562f7f43ff07b39d20389bb7a2cf66a9 Mon Sep 17 00:00:00 2001
From: JBB0807 <104856796+JBB0807@users.noreply.github.com>
Date: Mon, 5 May 2025 23:51:35 -0700
Subject: [PATCH 6/6] nave items displayed based on role
---
src/components/Navbar.jsx | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx
index 537cb27..a37fc43 100644
--- a/src/components/Navbar.jsx
+++ b/src/components/Navbar.jsx
@@ -14,7 +14,7 @@ const Navbar = () => {
async function handleLogout() {
window.open(`${authUrl}/auth/logout`, "_self");
- };
+ }
useEffect(() => {
// Set active link based on current path
@@ -128,18 +128,22 @@ const Navbar = () => {
*/}
-
-
- 🎯
- ASSIGNMENT
-
-
-
+
+ {user && user.role === "instructor" && (
+
+
+ 🎯
+ ASSIGNMENT
+
+
+
+ )}
+ {user && user.role === "student" && (
{
+ )}
{user ? (