Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/db/services/announcement.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { db } from ".."
import { IAnnouncementService } from "../../types/abstracts/announcement-service.abstract"
import { Announcement } from "../../types/entities/Announcement"
import { InsertAnnouncement, SelectAnnouncement, announcements } from "../models/announcement.model"
import { desc } from "drizzle-orm"
import { desc, eq } from "drizzle-orm"

export const announcementService: IAnnouncementService = {
async addAnnouncement(text: string): Promise<Announcement> {
Expand Down Expand Up @@ -35,4 +35,8 @@ export const announcementService: IAnnouncementService = {
date: record.createdAt,
}))
},

async deleteAnnouncement(id: number): Promise<void> {
await db.delete(announcements).where(eq(announcements.id, id))
},
}
82 changes: 82 additions & 0 deletions src/routers/announcement.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,85 @@ export const announcement = new Elysia({ prefix: "/announcement" })
},
},
)
.delete(
"/admin/:id",
async ({ params }) => {
const id = Number(params.id)

if (isNaN(id) || id <= 0) {
return { error: "Invalid announcement ID" }
}

// Check if announcement exists before deleting
const allAnnouncements = await announcementService.getAllAnnouncements()
const announcementExists = allAnnouncements.some((ann) => ann.id === id)

if (!announcementExists) {
return { error: "Announcement not found" }
}

await announcementService.deleteAnnouncement(id)
return { success: true }
},
{
tags: ["Announcement"],
detail: {
description: "Deletes an announcement by its ID (admin endpoint).",
security: [
{
basicAuth: [],
},
],
responses: {
"200": {
description: "Successfully deleted the announcement.",
content: {
"application/json": {
schema: {
type: "object",
properties: {
success: {
type: "boolean",
description: "Indicates if the operation was successful",
},
},
},
},
},
},
"400": {
description: "Bad request (e.g., invalid announcement ID).",
content: {
"application/json": {
schema: {
type: "object",
properties: {
error: {
type: "string",
description: "Error message",
},
},
},
},
},
},
"404": {
description: "Announcement not found.",
content: {
"application/json": {
schema: {
type: "object",
properties: {
error: {
type: "string",
description: "Error message",
},
},
},
},
},
},
},
},
},
)
140 changes: 114 additions & 26 deletions src/routers/queue.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,46 @@ export const queue = new Elysia({ prefix: "/queue" })
addStudentToQueue: t.Object({
idNumber: t.String({ description: "The student's ID number" }),
}),
dequeueStudent: t.Object({
idNumber: t.String({ description: "The student's ID number to remove from the queue" }),
}),
})
.delete("/admin/reset", () => queueNumberService.resetAll(), {
tags: ["Queue"],
detail: {
description: "Deletes all the queue numbers for every course.",
},
})
.delete(
"/number",
async ({ headers }: QueueContext) => {
const studentId = headers.idNumber
// TODO: Student dequeue feature has been disabled. Students cannot remove themselves from the queue.
// If you need to remove a student from the queue, use the admin endpoint or contact a coordinator.
// .delete(
// "/number",
// async ({ headers }: QueueContext) => {
// const studentId = headers.idNumber

if (!studentId) {
return error(400, "Student ID not found")
}
// if (!studentId) {
// return error(400, "Student ID not found")
// }

return await queueNumberService.dequeueById(studentId)
},
{
// @ts-expect-error TODO: Change this to an updated version of the basicAuth middleware once my patch is merged
beforeHandle: [validateQueueToken],
tags: ["Queue"],
detail: {
description: "Deletes a student's own queue number.",
responses: {
"200": {
description: "Successfully deleted the student's queue number.",
},
"401": {
description: "Unauthorized.",
},
},
},
},
)
// return await queueNumberService.dequeueById(studentId)
// },
// {
// // @ts-expect-error TODO: Change this to an updated version of the basicAuth middleware once my patch is merged
// beforeHandle: [validateQueueToken],
// tags: ["Queue"],
// detail: {
// description: "Deletes a student's own queue number.",
// responses: {
// "200": {
// description: "Successfully deleted the student's queue number.",
// },
// "401": {
// description: "Unauthorized.",
// },
// },
// },
// },
// )
.get(
"/number",
async ({ headers }: QueueContext) => {
Expand Down Expand Up @@ -281,6 +286,89 @@ export const queue = new Elysia({ prefix: "/queue" })
},
},
)
.delete(
"/admin/number",
async ({ body }) => {
const studentId = body.idNumber

if (!studentId) {
return { error: "Student ID is required" }
}

// Check if student has a queue number
const queueNumber = await queueNumberService.findByStudentId(studentId)
if (!queueNumber) {
return { error: "Student does not have a queue number" }
}

await queueNumberService.dequeueById(studentId)
return { success: true }
},
{
body: "dequeueStudent",
tags: ["Queue"],
detail: {
description: "Removes a student from the queue by their ID number (admin endpoint).",
security: [
{
basicAuth: [],
},
],
requestBody: {
required: true,
description: "The student's ID number.",
content: {
"application/json": {
schema: {
type: "object",
properties: {
idNumber: {
type: "string",
description: "The student's ID number to remove from the queue",
},
},
required: ["idNumber"],
},
},
},
},
responses: {
"200": {
description: "Successfully removed the student from the queue.",
content: {
"application/json": {
schema: {
type: "object",
properties: {
success: {
type: "boolean",
description: "Indicates if the operation was successful",
},
},
},
},
},
},
"400": {
description: "Bad request (e.g., student ID missing or student does not have a queue number).",
content: {
"application/json": {
schema: {
type: "object",
properties: {
error: {
type: "string",
description: "Error message",
},
},
},
},
},
},
},
},
},
)
// TODO: Uncomment when you wish to re-enable self-enqueueing for students
// .post(
// "/:course/number",
Expand Down
1 change: 1 addition & 0 deletions src/types/abstracts/announcement-service.abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { Announcement } from "../entities/Announcement"
export type IAnnouncementService = {
addAnnouncement(text: string): Promise<Announcement>
getAllAnnouncements(): Promise<Announcement[]>
deleteAnnouncement(id: number): Promise<void>
}