Skip to content

Commit 9cce517

Browse files
added pdf sending functionality in the assignments
1 parent 5ee72c6 commit 9cce517

File tree

6 files changed

+157
-93
lines changed

6 files changed

+157
-93
lines changed

admin/src/components/Assignment/Assignment.jsx

Lines changed: 103 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,36 @@ import { toast } from "react-toastify";
2222
import axios from "axios";
2323
import AppLayout from "../../layout/AppLayout";
2424

25-
2625
const Assignment = () => {
2726
const [title, setTitle] = useState("");
2827
const [description, setDescription] = useState("");
2928
const [questions, setQuestions] = useState("");
3029
const [deadline, setDeadline] = useState("");
3130
const [loading, setLoading] = useState(false);
31+
const [pdfFile, setPdfFile] = useState(null);
3232
const backendUrl = import.meta.env.VITE_BACKEND_URL;
3333

3434
const handleSubmit = async (e) => {
3535
e.preventDefault();
36-
setTimeout(setLoading(true), 2000);
36+
if (!pdfFile) {
37+
toast.error("Please upload a PDF file for the assignment.");
38+
return;
39+
}
40+
setLoading(true);
41+
// Prepare form data
42+
const formData = new FormData();
43+
formData.append("title", title);
44+
formData.append("description", description);
45+
formData.append("questions", questions);
46+
formData.append("deadline", deadline);
47+
formData.append("pdfFile", pdfFile);
3748

3849
try {
39-
const response = await axios.post(`${backendUrl}/api/v7/postAssignment`, {
40-
title,
41-
description,
42-
questions,
43-
deadline,
44-
});
50+
const response = await axios.post(
51+
`${backendUrl}/api/v7/postAssignment`,
52+
formData,
53+
{ headers: { "Content-Type": "multipart/form-data" } }
54+
);
4555
if (response.data.success) {
4656
toast.success(response.data.message);
4757
}
@@ -61,86 +71,95 @@ const Assignment = () => {
6171
<div className="min-h-screen w-full flex ml-[23%]">
6272
<div className="flex w-full gap-8">
6373
{/* Sidebar */}
64-
65-
66-
<div className="form-details flex justify-center items-center h-screen w-[70%]">
67-
<form
68-
onSubmit={handleSubmit}
69-
className="w-full h-[90%] lg:w-3/4 p-6 bg-white rounded-lg shadow-md"
70-
>
71-
<div className="space-y-6">
72-
<h1 className="text-3xl font-semibold text-gray-800 text-center">
73-
Post New Assignment: Empower Your Students with Engaging Challenges!
74-
</h1>
75-
76-
{/* Title Input */}
77-
<div>
78-
<label className="block text-gray-600 font-medium">Title</label>
79-
<input
80-
type="text"
81-
placeholder="Enter assignment title"
82-
value={title}
83-
required
84-
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
85-
onChange={(e) => setTitle(e.target.value)}
86-
/>
87-
</div>
88-
89-
{/* Description Input */}
90-
<div>
91-
<label className="block text-gray-600 font-medium">Description</label>
92-
<input
93-
type="text"
94-
placeholder="Enter assignment description"
95-
value={description}
96-
required
97-
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
98-
onChange={(e) => setDescription(e.target.value)}
99-
/>
100-
</div>
101-
102-
{/* Questions Input */}
103-
<div>
104-
<label className="block text-gray-600 font-medium">Questions</label>
105-
<input
106-
type="text"
107-
placeholder="Enter assignment questions"
108-
value={questions}
109-
required
110-
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
111-
onChange={(e) => setQuestions(e.target.value)}
112-
/>
113-
</div>
114-
115-
{/* Deadline Input */}
116-
<div>
117-
<label className="block text-gray-600 font-medium">Deadline</label>
118-
<input
119-
type="date"
120-
value={deadline}
121-
required
122-
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
123-
onChange={(e) => setDeadline(e.target.value)}
124-
/>
125-
</div>
12674

127-
{/* Submit Button */}
128-
<div className="flex justify-center">
129-
<button
130-
disabled={loading}
131-
type="submit"
132-
className="w-full p-3 bg-green-500 text-white font-medium rounded-md disabled:opacity-50"
133-
>
134-
{loading ? "Posting..." : "Post Assignment"}
135-
</button>
75+
<div className="form-details flex justify-center items-center h-screen w-[70%]">
76+
<form
77+
onSubmit={handleSubmit}
78+
className="w-full h-[90%] lg:w-3/4 p-6 bg-white rounded-lg shadow-md"
79+
>
80+
<div className="space-y-6">
81+
<h1 className="text-3xl font-semibold text-gray-800 text-center">
82+
Post New Assignment: Empower Your Students with Engaging Challenges!
83+
</h1>
84+
85+
{/* Title Input */}
86+
<div>
87+
<label className="block text-gray-600 font-medium">Title</label>
88+
<input
89+
type="text"
90+
placeholder="Enter assignment title"
91+
value={title}
92+
required
93+
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
94+
onChange={(e) => setTitle(e.target.value)}
95+
/>
96+
</div>
97+
98+
{/* Description Input */}
99+
<div>
100+
<label className="block text-gray-600 font-medium">Description</label>
101+
<input
102+
type="text"
103+
placeholder="Enter assignment description"
104+
value={description}
105+
required
106+
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
107+
onChange={(e) => setDescription(e.target.value)}
108+
/>
109+
</div>
110+
111+
{/* Questions Input */}
112+
<div>
113+
<label className="block text-gray-600 font-medium">Questions</label>
114+
<input
115+
type="text"
116+
placeholder="Enter assignment questions"
117+
value={questions}
118+
required
119+
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
120+
onChange={(e) => setQuestions(e.target.value)}
121+
/>
122+
</div>
123+
124+
{/* Deadline Input */}
125+
<div>
126+
<label className="block text-gray-600 font-medium">Deadline</label>
127+
<input
128+
type="date"
129+
value={deadline}
130+
required
131+
className="w-full mt-2 p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
132+
onChange={(e) => setDeadline(e.target.value)}
133+
/>
134+
</div>
135+
136+
<div>
137+
<label className="block text-gray-600 font-medium">Upload PDF</label>
138+
<input
139+
type="file"
140+
accept="application/pdf"
141+
required
142+
onChange={(e) => setPdfFile(e.target.files[0])}
143+
className="mt-2 block w-full text-sm text-gray-500 file:py-2 file:px-4 file:border file:border-gray-300 file:rounded-md file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100"
144+
/>
145+
</div>
146+
147+
{/* Submit Button */}
148+
<div className="flex justify-center">
149+
<button
150+
disabled={loading}
151+
type="submit"
152+
className="w-full p-3 bg-green-500 text-white font-medium rounded-md disabled:opacity-50"
153+
>
154+
{loading ? "Posting..." : "Post Assignment"}
155+
</button>
156+
</div>
136157
</div>
137-
</div>
138-
</form>
139-
</div>
140-
158+
</form>
159+
</div>
141160
</div>
142161
</div>
143162
);
144163
};
145164

146-
export default AppLayout()(Assignment);
165+
export default AppLayout(Assignment);

client/src/Student Dashboard/Assignments/Assignment.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import React, { useEffect } from "react";
2-
import { useState } from "react";
1+
import React, { useEffect, useState } from "react";
32
import axios from "axios";
43
import Layout from "../Layout/Layout";
54

@@ -9,6 +8,7 @@ type Assignment = {
98
description: string;
109
questions: string;
1110
deadline: string;
11+
pdfUrl: string;
1212
};
1313

1414
const Assignment: React.FC = () => {
@@ -96,9 +96,14 @@ const Assignment: React.FC = () => {
9696
</div>
9797
</div>
9898
<div className="bg-gray-50 px-5 py-3">
99-
<button className="w-full text-blue-600 hover:text-blue-800 font-medium text-sm transition-colors duration-200">
100-
View Assignment →
101-
</button>
99+
<a
100+
href={assignment.pdfUrl}
101+
target="_blank"
102+
rel="noreferrer"
103+
className="block w-full text-center bg-blue-500 text-white py-2 rounded-md hover:bg-blue-600 transition-colors duration-200"
104+
>
105+
Download PDF
106+
</a>
102107
</div>
103108
</div>
104109
))}

server/branch_wise_placement.png

-53.8 KB
Binary file not shown.

server/controllers/assignmentController.js

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,62 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
*/
17-
17+
const cloudinary = require('cloudinary').v2;
1818
const Assignment = require("../models/assignmentModels");
1919

2020
// code for posting the assignment from the admin panel to the student server
2121
const postAssignment = async (req, res) => {
2222
const { title, description, questions, deadline } = req.body;
2323

2424
try {
25+
26+
if (!req.file) {
27+
return res.status(400).json({
28+
success: false,
29+
message: "Pdf file is required",
30+
});
31+
}
32+
2533
const existingAssignment = await Assignment.findOne({ title });
2634
if (existingAssignment) {
2735
return res.status(409).json({
2836
success: false,
2937
message: "Assignment already exist",
3038
});
3139
}
40+
41+
let pdfUrl;
42+
43+
// Upload avatar to Cloudinary
44+
try {
45+
const result = await new Promise((resolve, reject) => {
46+
const stream = cloudinary.uploader.upload_stream(
47+
{ resource_type: "image" },
48+
(error, result) => {
49+
if (error) return reject(error);
50+
resolve(result);
51+
}
52+
);
53+
stream.end(req.file.buffer); // Pass the buffer to the stream
54+
});
55+
56+
pdfUrl = result.secure_url;
57+
} catch (uploadError) {
58+
console.error("Error uploading avatar to Cloudinary:", uploadError);
59+
return res.status(500).json({
60+
success: false,
61+
message: "Error uploading avatar",
62+
error: uploadError.message,
63+
});
64+
}
65+
66+
3267
const assignment = await Assignment.create({
3368
title,
3469
description,
3570
questions,
36-
deadline
71+
deadline,
72+
pdfUrl,
3773
});
3874

3975
return res.status(201).json({

server/models/assignmentModels.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ const assignmentSchema = new mongoose.Schema({
3636
type: Date,
3737
required: true,
3838
},
39+
pdfUrl: {
40+
type: String,
41+
required: true,
42+
},
3943
});
4044

4145
const Assignment = mongoose.model("assignment", assignmentSchema);

server/routes/assignmentRoutes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ limitations under the License.
1818
const express = require('express');
1919
const {postAssignment,getAssignment,deleteAssignment}=require("../controllers/assignmentController")
2020
const assignmentRouter = express.Router();
21-
22-
assignmentRouter.post('/postAssignment',postAssignment);
21+
const upload = require('../middlewares/multer');
22+
assignmentRouter.post('/postAssignment',upload.single("pdfFile"),postAssignment);
2323
assignmentRouter.get('/getAssignment',getAssignment);
2424
assignmentRouter.delete('/assignment/:id',deleteAssignment);
2525

0 commit comments

Comments
 (0)