Skip to content

Commit 9f8b5cf

Browse files
committed
I created enrollment button, and tried to create unerollment but need help
1 parent 724f072 commit 9f8b5cf

File tree

3 files changed

+138
-3
lines changed

3 files changed

+138
-3
lines changed

backend/internal/handlers/courses.go

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func Course(c *fiber.Ctx) error {
6161
Preload("Modules").
6262
Preload("Modules.Content", func(db *gorm.DB) *gorm.DB {
6363
return db.Order("id ASC")
64-
}).
64+
}).
6565
Preload("Tags").
6666
Where("id = ?", courseID).
6767
First(&course).Error; err != nil {
@@ -223,6 +223,70 @@ func Enroll(c *fiber.Ctx) error {
223223
})
224224
}
225225

226+
// Uneroll user into course
227+
func Unenroll(c *fiber.Ctx) error {
228+
user_id := c.Params("user_id")
229+
course_id := c.Params("course_id")
230+
231+
var user entity.Account
232+
// Check if the user exists
233+
if err := database.DB.Where("id = ?", user_id).First(&user).Error; err != nil {
234+
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
235+
}
236+
237+
var course entity.Course
238+
// Check if the course exists
239+
if err := database.DB.Where("id = ?", course_id).First(&course).Error; err != nil {
240+
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Course not found"})
241+
}
242+
243+
// Check if the user is enrolled in the course
244+
if err := database.DB.Model(&user).Association("Courses").Find(&course); err != nil {
245+
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User is not enrolled in this course"})
246+
}
247+
248+
// Unenroll user into course
249+
if err := database.DB.Model(&user).Association("Courses").Delete(&course); err != nil {
250+
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Error unenrolling into course"})
251+
}
252+
253+
return c.JSON(fiber.Map{
254+
"message": fmt.Sprintf("Successfully unenrolled user id %d in course %s", user.ID, course.Title),
255+
})
256+
}
257+
258+
func CheckEnrollmentStatus(c *fiber.Ctx) error {
259+
user_id := c.Params("user_id")
260+
course_id := c.Params("course_id")
261+
262+
var user entity.Account
263+
// Check if the user exists
264+
if err := database.DB.Where("id = ?", user_id).First(&user).Error; err != nil {
265+
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
266+
}
267+
268+
var course entity.Course
269+
// Check if the course exists
270+
if err := database.DB.Where("id = ?", course_id).First(&course).Error; err != nil {
271+
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Course not found"})
272+
}
273+
274+
// Check if the user is enrolled in the course
275+
isEnrolled := false
276+
if err := database.DB.Table("enrollment").
277+
Where("account_id = ? AND course_id = ?", user_id, course_id).
278+
Select("count(*) > 0").
279+
Scan(&isEnrolled).Error; err != nil {
280+
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error checking enrollment status"})
281+
}
282+
283+
// Return the enrollment status
284+
return c.JSON(fiber.Map{
285+
"message": "Enrollment status checked successfully",
286+
"isEnrolled": isEnrolled,
287+
})
288+
}
289+
226290
// Create a module inside a course
227291
func CreateModule(c *fiber.Ctx) error {
228292
creator_id, err := strconv.Atoi(c.Params("creator_id"))
@@ -372,7 +436,7 @@ func EditContent(c *fiber.Ctx) error {
372436
if err := os.Remove("./content" + path); err != nil {
373437
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"message": err.Error()})
374438
}
375-
} else if !os.IsNotExist(err){
439+
} else if !os.IsNotExist(err) {
376440
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"message": err.Error()})
377441
}
378442

@@ -480,7 +544,7 @@ func EditThumbnail(c *fiber.Ctx) error {
480544
if err := os.Remove(fmt.Sprintf("./content/%d/thumbnail.png", course_id)); err != nil {
481545
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"message": err.Error()})
482546
}
483-
} else if !os.IsNotExist(err){
547+
} else if !os.IsNotExist(err) {
484548
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"message": err.Error()})
485549
}
486550

backend/internal/router/route.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,5 @@ func SetupRoutes(app *fiber.App) {
9292
app.Post("/edit-content/:creator_id/:content_id", handlers.EditContent)
9393
app.Post("/edit-thumbnail/:creator_id/:course_id", handlers.EditThumbnail)
9494
app.Post("/enroll/:user_id/:course_id", handlers.Enroll)
95+
app.Delete("/unenroll/:user_id/:course_id", handlers.Unenroll)
9596
}

frontend/src/components/pages/Course.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export function Course() {
1010
const [userInfo, setUserInfo] = useState(null);
1111
const [error, setError] = useState(null);
1212
const [file, setFile] = useState(null);
13+
const [isEnrolled, setIsEnrolled] = useState(false);
1314
const [newContentName, setNewContentName] = useState({
1415
title: "",
1516
});
@@ -118,6 +119,67 @@ export function Course() {
118119
}
119120
};
120121

122+
const handleEnroll = async () => {
123+
const userId = Cookies.get('userId');
124+
125+
if (!userId) {
126+
setError('User ID not found');
127+
return;
128+
}
129+
130+
try {
131+
const response = await fetch(`http://localhost:4000/Enroll/${userId}/${courseID}`, {
132+
method: "POST",
133+
headers: {
134+
"Content-Type": "application/json",
135+
},
136+
});
137+
const data = await response.json();
138+
if (response.ok) {
139+
Notiflix.Notify.success("Succesfully enrolled in the course!");
140+
setTimeout(() => {
141+
window.location.reload();
142+
}, 500);
143+
} else {
144+
Notiflix.Notify.failure(data.message || "Enrollment failed");
145+
}
146+
} catch (error) {
147+
Notiflix.Notify.failure("Error occurred during enrollment");
148+
}
149+
150+
};
151+
152+
const handleUnenroll = async () => {
153+
const userId = Cookies.get('userId');
154+
155+
if (!userId) {
156+
setError('User ID not found');
157+
return;
158+
}
159+
160+
try {
161+
const response = await fetch(`http://localhost:4000/Unenroll/${userId}/${courseID}`, {
162+
method: "DELETE",
163+
headers: {
164+
"Content-Type": "application/json",
165+
},
166+
});
167+
const data = await response.json();
168+
if (response.ok) {
169+
Notiflix.Notify.success("Succesfully unenrolled in the course!");
170+
setTimeout(() => {
171+
window.location.reload();
172+
}, 500);
173+
} else {
174+
Notiflix.Notify.failure(data.message || "Unenrollment failed");
175+
}
176+
} catch (error) {
177+
Notiflix.Notify.failure("Error occurred during Unenrollment");
178+
}
179+
180+
};
181+
182+
121183
useEffect(() => {
122184
const userId = Cookies.get('userId');
123185

@@ -248,6 +310,14 @@ export function Course() {
248310
<div className="flex flex-1 justify-end flex-wrap gap-5 ml-20">
249311
{editThumbnail}
250312
{createButton}
313+
{userInfo.role === "student" && (
314+
<button
315+
onClick={isEnrolled ? handleUnenroll : handleEnroll}
316+
className={`p-2 rounded shadow text-white font-semibold ${isEnrolled ? 'bg-red-500 hover:bg-red-700' : 'bg-green-500 hover:bg-green-700'}`}
317+
>
318+
{isEnrolled ? 'Unenroll from Course' : 'Enroll in Course'}
319+
</button>
320+
)}
251321
</div>
252322
</div>
253323
<div className="grid grid-cols-1 gap-6">

0 commit comments

Comments
 (0)