Skip to content

feat: provide superadmins and/or admins a way to clear past notifications #117

Description

@NoelVarghese2006

Clear Past Notifications

Goal: Provide superadmins (and optionally admins) a way to delete notifications that have already been sent.

Background

  • The scheduled_notifications table stores both pending (sent_at IS NULL) and sent (sent_at IS NOT NULL) notifications.
  • The Danger Zone reset (POST /superadmin/reset-hackathon with reset_notifications: true) already bulk-deletes all notifications (sent + pending) via Hackathon.Reset().
  • The existing individual delete (DELETE /superadmin/notifications/{notificationID}) is blocked for sent notifications by AND sent_at IS NULL in the store query, returning 409.
  • The frontend "Sent" tab in the notifications page is read-only — no delete buttons.

Solution

Remove the AND sent_at IS NULL guard from the individual delete path so superadmins can delete any single notification regardless of its sent status. Add delete buttons to the "Sent" tab in the UI.

Changes

Backend

internal/store/scheduled_notifications.go

Remove AND sent_at IS NULL from the Delete() query:

- DELETE FROM scheduled_notifications WHERE id = $1 AND sent_at IS NULL
+ DELETE FROM scheduled_notifications WHERE id = $1

This eliminates the ErrConflict path (which was only reachable when the row existed but had sent_at IS NOT NULL). The only error cases after this change are ErrNotFound (no row with that ID) or a database error.

cmd/api/scheduled_notifications.go

Remove the 409 conflict case from deleteScheduledNotificationHandler:

 if err := app.store.ScheduledNotifications.Delete(r.Context(), id); err != nil {
     switch {
     case errors.Is(err, store.ErrNotFound):
         app.notFoundResponse(w, r, errors.New("notification not found"))
         return
-    case errors.Is(err, store.ErrConflict):
-        app.conflictResponse(w, r, errors.New("notification already sent"))
-        return
     }
     app.internalServerError(w, r, err)
     return
 }

cmd/api/scheduled_notifications_test.go

  • Remove the test case "returns 409 when already sent" from TestDeleteScheduledNotification.
  • Add a test case "deletes a sent notification" that asserts 204.

Frontend

client/web/src/pages/superadmin/notifications/components/NotificationsTable.tsx

  1. Add an "Actions" column header to the sent tab's <TableHeader>.
  2. Add a delete button (Trash2 icon) to each sent row, reusing the existing setDeleteTarget / deleteTarget state and the same confirmation AlertDialog.
  3. Update the confirmation dialog description text from "Already-sent notifications cannot be deleted" to something generic like "This action cannot be undone."

No changes needed to the store, API module, or types — the existing remove action and deleteScheduledNotification API call already work for any notification ID.

Files Modified

File Change
internal/store/scheduled_notifications.go Remove AND sent_at IS NULL from Delete()
cmd/api/scheduled_notifications.go Remove 409 conflict case from handler
cmd/api/scheduled_notifications_test.go Update tests
client/web/src/pages/superadmin/notifications/components/NotificationsTable.tsx Add delete buttons to sent rows, update dialog text

Not in Scope

  • Bulk "clear all sent" button — the Danger Zone reset already covers this.
  • Admin role access — the existing route is superadmin-only. Extending to admins would require a separate route group and middleware change.
  • Schema migration — no changes needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfrontendReact/TypeScript client work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions