[8.2] Review Alert

Author name: Joylynne Grace C. Esportuno
Reviewers: Jethro Lagmay
Creation Date: March 27, 2026
References: https://github.com/wyzlab/WyzQuests/issues/55
Status: Approved and Merged


INTRODUCTION & GOALS

Problem Summary

Review Alert notifies a quest creator in the notification bell when a reviewer finalizes a review. The reviewer can either approve the quest or request changes. The status update API changes quests.publishing_status, then creates an in-app notification for the quest creator and sends a companion status email.

From the creator's perspective, the notification bell shows that a reviewed quest needs attention or has been approved. From the system perspective, Review Alert is a non-blocking side effect of the reviewer status workflow.

Goals

  • Notify the creator when a reviewer approves a quest.

  • Notify the creator when a reviewer requests changes.

Non-Goals

  • Review Alert does not create or manage reviewer comments.

  • Review Alert does not persist the optional final notes typed in SubmitReviewModal.

  • Review Alert does not provide realtime notification delivery; the bell polls every 30 seconds.

Glossary

  • Review Alert — In-app notification sent to a creator after reviewer final review action.

  • Review Submitted — Notification type used when a quest is approved.

  • Changes Requested — Notification type used when a reviewer rejects/returns a quest for revision.

  • Creator — The quests.creator_id user who receives the review alert.

  • Reviewer — The REVIEWER or ADMIN user submitting the review decision.

  • Notification Bell (Notifications.tsx) — the UI dropdown that lists notifications.

  • Fire-and-Forget — A side effect that logs errors but does not throw back into the main workflow.


High-Level Architecture

System Diagram

Technologies Used

  • Next.js, TypeScript, Supabase, Zod, and Sonner toast


DETAILED DESIGN & IMPLEMENTATION

Data Model / Schema

#### quests
 
Review Alert is triggered after a quest status update.
 
Relevant fields:
 
- id
 
- title
 
- creator_id
 
- publishing_status
 
- canvas_metadata
 
Allowed review status inputs from updateQuestStatusSchema:
 
```ts
 
"approved" | "changes_requested"
 
```
 
Approval path validates canvas_metadata before updating status.
 
#### notifications
 
Review alerts are stored in the shared notifications table.
 
Relevant fields:
 
- id
 
- from_user_id
 
- to_user_id
 
- title
 
- body
 
- link
 
- data
 
- is_read
 
- read_at
 
- created_at
 
Approved notification shape:
 
```json
 
{
 
"from_user_id": "reviewer-app-user-id",
 
"to_user_id": "creator-app-user-id",
 
"title": "Review Submitted",
 
"body": "Review completed for \"Quest title\"",
 
"link": "/quest-editor/quest-id/overview",
 
"data": {
 
"type": "REVIEW_SUBMITTED",
 
"quest_id": "quest-id"
 
},
 
"is_read": false
 
}
 
```
 
Changes-requested notification shape:
 
```json
 
{
 
"from_user_id": "reviewer-app-user-id",
 
"to_user_id": "creator-app-user-id",
 
"title": "Changes Requested",
 
"body": "Revisions needed on \"Quest title\"",
 
"link": "/quest-editor/quest-id/content/visual-canvas?comments=true",
 
"data": {
 
"type": "CHANGES_REQUESTED",
 
"quest_id": "quest-id"
 
},
 
"is_read": false
 
}
 
```
 
#### app_users
 
Used to resolve:
 
- reviewer display name for email
 
- creator email/name for email
 
- internal UUIDs for notification sender/recipient
 
Notification user IDs use internal app_users.id, not Clerk IDs.

API Specification

#### PATCH /api/reviewer/update-quest-status
 
- Authentication: Required
 
- Authorized roles: REVIEWER, ADMIN
 
- Purpose: Finalize review status and trigger creator review alert.
 
- Request:
 
```json
 
{
 
"quest_id": "quest-uuid",
 
"publishing_status": "approved"
 
}
 
```
 
- Supported status values:
 
- approved
 
- changes_requested
 
- Success response:
 
```json
 
{
 
"success": true,
 
"message": "Quest status successfully updated to approved",
 
"data": {
 
"id": "quest-uuid",
 
"publishing_status": "approved"
 
}
 
}
 
```
 
- Validation and behavior:
 
- Fetches quest creator_id, title, and canvas_metadata.
 
- If approving, runs quest content validation first.
 
- Updates quests.publishing_status.
 
- Calls status-specific in-app notification helper.
 
- Sends a non-blocking status email.
 
#### GET /api/notifications/get-notifications?page=<page>&limit=<limit>&unread_only=<boolean>
 
- Authentication: Required
 
- Purpose: Fetch creator notifications for the bell dropdown.
 
- Success response:
 
```json
 
{
 
"success": true,
 
"message": "Notifications fetched successfully",
 
"data": {
 
"notifications": [
 
{
 
"id": "notification-id",
 
"title": "Review Submitted",
 
"body": "Review completed for \"Quest title\"",
 
"link": "/quest-editor/quest-id/overview",
 
"is_read": false,
 
"data": {
 
"type": "REVIEW_SUBMITTED",
 
"quest_id": "quest-id"
 
},
 
"created_at": "2026-06-30T00:00:00.000Z"
 
}
 
],
 
"totalCount": 1,
 
"hasMore": false,
 
"currentPage": 1
 
}
 
}
 
```
 
#### PATCH /api/notifications/update-notifications
 
- Authentication: Required
 
- Purpose: Mark a review alert as read after click or explicit Mark as Read.
 
- Request:
 
```json
 
{
 
"id": "notification-uuid"
 
}
 
```
 
- Security: Updates only rows where to_user_id equals the authenticated user.
 
#### DELETE /api/notifications/delete-notifications
 
- Authentication: Required
 
- Purpose: Delete one notification from the bell dropdown.
 
- Relation to Review Alert: Optional cleanup action; not part of creating the review alert.

Logic & Workflows

Reviewer Approval Workflow

1. Reviewer opens SubmitReviewModal.

2. Modal fetches unresolved comment count from /api/reviewer/comments?quest_id=<questID>.

3. If unresolved comments exist, approval is disabled.

4. Reviewer confirms Approve & Publish.

5. Modal calls /api/reviewer/update-quest-status with publishing_status = approved.

6. API validates request and reviewer/admin role.

7. API validates quest content.

8. API updates quests.publishing_status to approved.

9. API calls notifyCreatorOfReviewApproved.

10. Notification helper inserts a REVIEW_SUBMITTED notification for the creator.

11. API sends a non-blocking "quest approved" email.

12. Reviewer is routed back to /reviewer/queue.

Reviewer Requests Changes Workflow

1. Reviewer opens SubmitReviewModal.

2. Reviewer confirms Reject & Return to Draft.

3. Modal calls /api/reviewer/update-quest-status with publishing_status = changes_requested.

4. API validates request and reviewer/admin role.

5. API updates quests.publishing_status to changes_requested.

6. API calls notifyCreatorOfChangesRequested.

7. Notification helper inserts a CHANGES_REQUESTED notification for the creator.

8. API sends a non-blocking "changes requested" email.

9. Reviewer is routed back to /reviewer/queue.

Notification Insert Workflow

1. Status helper fetches quest title and creator_id.

2. Helper calls sendCommentNotification.

3. sendCommentNotification skips notification if reviewer and creator are the same user.

4. It resolves title, body, and link from notification templates.

5. It inserts into notifications.

6. Insert errors are logged and do not block the status update response.

Creator Bell Workflow

1. Notifications.tsx loads notifications after Clerk user is available.

2. It calls /api/notifications/get-notifications?page=1&limit=10.

3. It stores notifications locally.

4. It computes unreadCount from loaded notifications.

5. Bell badge appears when unread count is greater than zero.

6. The dropdown lists review alerts with title and body.

7. Creator can filter read/unread notifications.

8. Notifications poll every 30 seconds and can be manually refreshed.

Creator Click Workflow

1. Creator clicks the review alert row.

2. If unread, UI optimistically marks it read and sends PATCH /api/notifications/update-notifications.

3. UI navigates with router.push(notification.link).

4. Approved review alert routes to /quest-editor/<questId>/overview.

5. Changes-requested review alert routes to /quest-editor/<questId>/content/visual-canvas?comments=true.

6. If the read API fails, local read state rolls back.


INFRASTRUCTURE & OPERATIONS

Dependencies

  • Supabase tables:

    • quests

    • notifications

    • app_users

  • Notification table indexes:

    • idx_notifications_to_user_id

    • idx_notifications_to_user_unread

    • idx_notifications_created_at

  • Auth helpers:

    • authenticateUser

    • authenticateAnyRole

  • Quest validation for approval path.

  • Email infrastructure for companion QuestStatusEmail.

  • APP_URL for email links.

Monitoring & Alerting

Current implementation logs notification and email failures but does not persist delivery attempts. Monitor:

  • Database update error

  • Status update blocked by database policies or invalid Quest ID.

  • [comment-notifications] Failed to send REVIEW_SUBMITTED

  • [comment-notifications] Failed to send CHANGES_REQUESTED

  • [comment-notifications] Quest lookup failed

  • Failed to send status email

  • [get-notifications] Database error

Recommended alert thresholds:

  • Review status update failures above 2% over 15 minutes.

  • Notification insert failures above 2% over 15 minutes.

  • Repeated quest lookup failures for status notification helpers.

  • Creator reports of missing review alerts after successful reviewer status updates.

Deployment Plan

1. Confirm notifications table migration is applied.

2. Confirm reviewers/admins can call /api/reviewer/update-quest-status.

3. Submit a test quest for review.

4. As reviewer, approve the quest.

5. Confirm quests.publishing_status = approved.

6. Confirm creator receives a REVIEW_SUBMITTED notification.

7. Click the notification and verify it routes to quest overview.

8. Submit another test quest and request changes.

9. Confirm creator receives a CHANGES_REQUESTED notification.

10. Click the notification and verify it routes to the visual canvas with feedback panel open.

11. Confirm unread badge count decreases after click.

12. Verify companion status emails in a staging SMTP inbox.


TESTING & QUALITY ASSURANCE

Test Strategy

Recommended test coverage:

  • API test /api/reviewer/update-quest-status:

    • unauthenticated request

    • unauthorized role

    • invalid body

    • quest not found

    • approval blocked by validation errors

    • approved status updates quest and triggers approval notification

    • changes requested status updates quest and triggers changes notification

    • email failure does not fail status update

  • Unit test notification template output:

    • REVIEW_SUBMITTED title/body/link

    • CHANGES_REQUESTED title/body/link

    • data payload includes type and quest_id

  • Component test SubmitReviewModal:

    • approval disabled with unresolved comments

    • approve calls status API with approved

    • reject calls status API with changes_requested

  • Component test Notifications.tsx:

    • review alerts render title/body

    • unread badge count includes review alerts

    • click marks read and navigates to link

  • E2E test:

    • reviewer approves quest

    • creator sees notification bell badge

    • creator opens notification and lands on overview

  • E2E test:

    • reviewer requests changes

    • creator sees notification bell badge

    • creator opens notification and lands on feedback view

Known Limitations

  • SubmitReviewModal includes optional final notes, but notes are not sent to the API or stored.

  • In-app notification insertion is fire-and-forget and does not retry.

  • Email delivery is separate and non-blocking; email success does not guarantee in-app notification success.

  • Notification polling is every 30 seconds; there is no realtime bell update.


MAINTENANCE & SUPPORT

Troubleshooting

Creator does not see a review alert

  • Confirm /api/reviewer/update-quest-status returned success.

  • Confirm quests.creator_id is the expected creator app user UUID.

  • Check notifications table for a row with to_user_id = creator_id.

  • Check [comment-notifications] logs.

  • Confirm reviewer and creator are not the same user; self-notifications are skipped.

Review alert appears but badge count is wrong

  • Confirm the notification has is_read = false.

  • Refresh the notification bell.

  • Wait for the 30-second polling interval.

  • Check whether the notification is on a later page not loaded by the client.

Approval did not create alert

  • Confirm quest content validation passed.

  • Confirm publishing_status was exactly approved.

  • Check notifyCreatorOfReviewApproved logs.

  • Inspect notifications.data.type for REVIEW_SUBMITTED.

Changes requested did not open feedback view

  • Confirm notification link is /quest-editor/<questId>/content/visual-canvas?comments=true.

  • Confirm QuestEditorLayout receives comments=true.

  • See docs/VIEW_FEEDBACK_TECHNICAL_GUIDE.md for feedback deep-link troubleshooting.

Status email was sent but bell notification is missing

  • Email and in-app notifications are separate side effects.

  • Check sendCommentNotification insert logs.

  • Confirm notification insert RLS/service-role behavior in Supabase.

Bell notification exists but creator cannot open the linked page

  • Confirm creator still owns or can access the quest.

  • Confirm the quest editor route exists.

  • Confirm the link path matches current routing conventions.

Changelog

  • 1.0 - Approved, Initial internal technical guide for Review Alert notification behavior, 03/27/2026


Document Version

  • 1.0 - Published, Review Alert technical documentation created for internal review, 06/30/2026


Was this article helpful?