diff --git a/.env b/.env index ddf3a43..d44cade 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="http://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/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 ? ( { + const [assignmentId, setAssignmentId] = useState(""); 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); + 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 { - const res = await fetch("http://localhost:8082/instructor/list/9", { + // 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( @@ -34,6 +109,7 @@ const AssignmentPage = () => { ); setProjects(unique); + // } } catch (error) { console.error("Error fetching assignments:", error); } @@ -44,43 +120,95 @@ const AssignmentPage = () => { setCampID(""); setProgramID(""); setPassword(""); - setTitle(""); setDescription(""); setFile(null); setEditingIndex(null); }; - const handleSubmit = (e) => { + const handleSubmit = async (e) => { e.preventDefault(); - const newProject = { - studentname: studentName, - campid: campID, - programid: programID, - title, - description, - fileName: file ? file.name : null, - }; + if (!user.userId) return alert("Please login to submit an 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("qrcodenumber", qrCodeNumber); + formData.append("password", password); + formData.append("description", description); 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 || ""); - setTitle(project.title || ""); setDescription(project.description || ""); setFile(null); setEditingIndex(index); @@ -88,60 +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"} +

    - setStudentName(e.target.value)} required /> + setStudentName(e.target.value)} + required + />
    - 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 + disabled={editingIndex !== null} + s + /> +
    + +
    + + setQrCodeNumber(e.target.value)} + required + />
    - setPassword(e.target.value)} required /> -
    - -
    - - setTitle(e.target.value)} required /> + setPassword(e.target.value)} + required + />
    - +
    -
    - - setFile(e.target.files[0])} /> -
    + {editingIndex === null && ( +
    + + setFile(e.target.files[0])} + /> +
    + )}
    - - + +
    @@ -153,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 +

    )}
    - +
    ))} 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; 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() {
    */}