[8.3] View Feedback

Author name: Joylynne Grace C. Esportuno
Reviewers: Joshua Uriel Tribiana
Creation Date: June 30, 2026
References: https://github.com/wyzlab/WyzQuests/issues/56
Status: Approved and Merged


INTRODUCTION & GOALS

Problem Summary

View Feedback lets a creator jump from a review notification directly to the relevant reviewer feedback inside the quest editor. When a reviewer comments on a node or requests changes, the system stores an in-app notification containing a deep link. Clicking that notification marks it as read and routes the creator to the quest's visual canvas with query parameters that automatically open the feedback sheet.

Goals

  • Notify quest creators when reviewers leave feedback or request changes.

  • Store notification links that route creators back to the reviewed quest.

  • Open the reviewer feedback sheet automatically when comments=true is present in the URL.

  • Select and filter to a specific canvas node when node_id=<nodeId> is present.

  • Mark notifications as read when a creator clicks them.

  • Allow creators to reply to reviewer feedback threads.

  • Support both exploration and linear visual canvas modes.

Non-Goals

  • View Feedback does not create reviewer comments; comments are created by the commenting APIs.

  • View Feedback does not edit canvas content directly.

  • View Feedback does not currently persist reviewer final notes from SubmitReviewModal.

  • View Feedback does not currently guarantee the notification scrolls to a specific comment thread by comment_id.

  • View Feedback does not send browser push notifications.

Glossary

  • View Feedback — The creator workflow for opening reviewer comments from a notification deep link.

  • Reviewer Feedback Panel — Creator-facing label for CommentPanel.

  • Comment Panel — Shared right-side sheet used by reviewers and creators for comments/feedback.

  • Deep Link — A URL with query parameters such as ?comments=true&node_id=<nodeId>.

  • Notification Link — The notifications.link value used by the notification bell to navigate.

  • Node Feedback — A comment attached to a canvas node ID.

  • Reviewer Status Notification — Notification created when a reviewer approves a quest or requests changes.

  • Read Statenotifications.is_read and notifications.read_at.


HIGH-LEVEL ARCHITECTURE

System Diagram

Technologies Used

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


DETAILED DESIGN & IMPLEMENTATION

Data Model/Schema

#### `notifications`
Created by `20260415_create_notifications_table.sql`.
 
Relevant fields:
- `id`
- `from_user_id`
- `to_user_id`
- `title`
- `body`
- `link`
- `data`
- `is_read`
- `read_at`
- `created_at`
 
Example notification for a node-level comment:
```json
{
"from_user_id": "reviewer-app-user-id",
"to_user_id": "creator-app-user-id",
"title": "Comment on \"Quiz 1\"",
"body": "New feedback on \"Intro to Fractions\"",
"link": "/quest-editor/quest-id/content/visual-canvas?comments=true&node_id=node-123",
"data": {
"type": "NEW_COMMENT",
"quest_id": "quest-id",
"node_id": "node-123",
"comment_id": "comment-id"
},
"is_read": false
}
```
 
Supported notification types from `COMMENT_NOTIFICATION_TYPES`:
- `NEW_COMMENT`
- `COMMENT_RESOLVED`
- `COMMENT_REPLY`
- `REVIEW_SUBMITTED`
- `CHANGES_REQUESTED`
 
#### `quest_comments`
Used by the feedback panel to display reviewer feedback.
 
Relevant fields:
- `id`
- `quest_id`
- `node_id`
- `app_user_id`
- `guest_invite_id`
- `content`
- `is_resolved`
- `parent_comment_id`
- `created_at`
- `updated_at`
 
The list API groups comments into threads:
```ts
{
comment: Comment;
replies: Comment[];
}
```
 
#### `quests`
Used to resolve:
- `id`
- `title`
- `creator_id`
- `canvas_metadata`
- `publishing_status`
 
`creator_id` determines who receives review notifications. `canvas_metadata` is used to compute node display names such as `TEXT 1` or `QUIZ 2`.
 
#### `app_users`
Used for internal user IDs and display names:
- `id`
- `name`
- `email`
- `role`
 
Notification `from_user_id` and `to_user_id` use internal `app_users.id` UUIDs, not Clerk string IDs.

API Specification

#### `GET /api/notifications/get-notifications?page=<page>&limit=<limit>&unread_only=<boolean>`
- Authentication: Required
- Purpose: Fetch paginated notifications for the current user.
- Query defaults:
- `page`: `1`
- `limit`: `10`
- `limit` max: `50`
- Success response:
```json
{
"success": true,
"message": "Notifications fetched successfully",
"data": {
"notifications": [
{
"id": "notification-id",
"title": "Changes Requested",
"body": "Revisions needed on \"Quest title\"",
"link": "/quest-editor/quest-id/content/visual-canvas?comments=true",
"is_read": false,
"data": {
"type": "CHANGES_REQUESTED",
"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 one notification as read.
- Request:
```json
{
"id": "notification-uuid"
}
```
- Security: Updates only when `to_user_id` matches the authenticated user.
- Success response:
```json
{
"success": true,
"message": "Notification marked as read",
"data": {
"id": "notification-uuid"
}
}
```
 
#### `POST /api/reviewer/comments/create`
- Authentication: `REVIEWER`, `CREATOR`, `ADMIN`, or `AGENCY`
- Purpose: Create a node comment or reply and notify the relevant users.
- Request:
```json
{
"quest_id": "quest-uuid",
"node_id": "node-123",
"content": "Please clarify this question.",
"parent_comment_id": null
}
```
- Notification side effect:
- Calls `notifyCreatorOfNewComment`.
- If `parent_comment_id` exists, also calls `notifyParentAuthorOfReply`.
- Notification failures are logged but do not fail comment creation.
 
#### `PATCH /api/reviewer/update-quest-status`
- Authentication: `REVIEWER` or `ADMIN`
- Purpose: Reviewer finalizes the review as `approved` or `changes_requested`.
- Request:
```json
{
"quest_id": "quest-uuid",
"publishing_status": "changes_requested"
}
```
- Notification side effect:
- `changes_requested` calls `notifyCreatorOfChangesRequested`.
- `approved` calls `notifyCreatorOfReviewApproved`.
- Also sends a non-blocking status email.
- Notes:
- Approval validates quest content before updating status.
- `SubmitReviewModal` has a final-notes input, but those notes are not currently sent to this API.
 
#### `GET /api/reviewer/comments?quest_id=<quest_id>&node_id=<node_id>`
- Authentication: Required reviewer/commenting access
- Purpose: Fetch comment threads for the feedback panel.
- Query:
- `quest_id`: required UUID
- `node_id`: optional node filter
- Response includes `threads`, `totalCount`, and `currentUserId`.
 
#### `GET /api/reviewer/comments/export?quest_id=<quest_id>&format=csv`
- Authentication: Required reviewer/commenting access
- Purpose: Export feedback threads as CSV from the feedback panel.
- Response: CSV file download.

Logic & Worflows

Reviewer Comment to Creator Feedback Workflow

  1. Reviewer opens the quest in read-only canvas mode.

  2. Reviewer clicks a node; the canvas sets CommentingContext.selectedNodeId and opens the comment panel.

  3. Reviewer submits a comment through /api/reviewer/comments/create.

  4. API sanitizes and inserts the comment into quest_comments.

  5. API computes a human-readable node display name from canvas_metadata.

  6. API calls notifyCreatorOfNewComment with the quest ID, node ID, display name, and comment ID.

  7. Notification helper resolves the quest creator and inserts a NEW_COMMENT notification.

  8. Notification link points to /quest-editor/<questId>/content/visual-canvas?comments=true&node_id=<nodeId>.

Reviewer Requests Changes Workflow

  1. Reviewer opens SubmitReviewModal.

  2. Reviewer chooses Reject & Return to Draft.

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

  4. API updates quests.publishing_status.

  5. API calls notifyCreatorOfChangesRequested.

  6. Notification helper inserts a CHANGES_REQUESTED notification.

  7. Notification link points to /quest-editor/<questId>/content/visual-canvas?comments=true.

  8. Creator clicks the notification and lands on the visual canvas with the feedback panel open.

Creator Clicks Notification Workflow

  1. Notifications.tsx polls /api/notifications/get-notifications every 30 seconds while a user is present.

  2. Creator clicks a notification row.

  3. If unread, UI optimistically marks it read.

  4. Client sends PATCH /api/notifications/update-notifications.

  5. Client calls router.push(notification.link).

  6. QuestEditorLayout reads comments=true into commentsMode.

  7. QuestEditorLayout renders CommentPanel with isCreatorView={true} and forceOpen={commentsMode}.

  8. CommentPanel opens the sheet and, if node_id exists, sets selectedNodeId.

  9. CommentPanel fetches /api/reviewer/comments?quest_id=<questId>.

  10. If a node is selected, the panel enables node filtering and fetches comments for that node.

Creator Feedback Panel Behavior

  1. The sheet title is Reviewer Feedback.

  2. Creator sees an info banner explaining they can reply in each thread.

  3. Creator can toggle node filtering when a node is selected.

  4. Creator can export feedback to CSV when comments exist.

  5. New top-level comment form is hidden for creators; creators interact through replies in existing threads.

  6. Closing the sheet removes the comments query parameter through router.replace.

Approval Notification Behavior

  1. Reviewer approval triggers a REVIEW_SUBMITTED notification.

  2. Current link points to /quest-editor/<questId>/overview.

  3. This means approval notifications do not open the feedback panel by default.


INFRASTRUCTURE & OPERATIONS

Dependencies

  • Supabase tables:

    • notifications

    • quest_comments

    • quests

    • app_users

  • Auth helpers:

    • authenticateUser

    • authenticateAnyRole

  • Visual canvas routes and React Flow rendering

  • CommentingProvider mounted in QuestEditorLayout

  • APP_URL for status email links

  • Browser session storage for hash-based notification scroll behavior used by other notification types

Monitoring & Alerting

Current implementation relies on server logs and client behavior. Monitor:

  • [comment-notifications] Failed to send

  • [comment-notifications] Quest lookup failed

  • [reviewer/comments/create] Insert error

  • [get-notifications] Database error

  • [update-notifications] Database error

  • Failed to fetch comments

  • Failed to update quest status

Deployment Plan

  1. Confirm notifications table migration and indexes are applied.

  2. Confirm quest_comments APIs are deployed and accessible to reviewers and creators.

  3. Confirm QuestEditorLayout mounts CommentingProvider and CommentPanel for creator view.

  4. Add reviewer feedback on a test quest node.

  5. Confirm creator receives a NEW_COMMENT notification.

  6. Click the notification and verify URL includes comments=true&node_id=<nodeId>.

  7. Verify the visual canvas opens and the Reviewer Feedback sheet is open.

  8. Verify comments are filtered to the selected node.

  9. Submit changes_requested from SubmitReviewModal.

  10. Confirm creator receives a CHANGES_REQUESTED notification and the feedback sheet opens.

  11. Confirm the notification is marked read after click.


TESTING QUALITY & ASSURANCE

Test Strategy

  • Unit test notification template links in comment-notifications.ts.

  • API test GET /api/notifications/get-notifications for pagination, unread-only filtering, and ownership.

  • API test PATCH /api/notifications/update-notifications for ownership enforcement.

  • API test /api/reviewer/comments/create verifies notification side effects are called without blocking comment creation.

  • API test /api/reviewer/update-quest-status verifies status-specific notification functions are called.

  • Component test Notifications.tsx for click behavior:

    • optimistic read update

    • read API call

    • navigation to stored link

  • Component test CommentPanel for comments=true auto-open and node_id selection.

  • E2E test:

    • reviewer comments on a node

    • creator clicks notification

    • creator lands on canvas with feedback sheet open and node-filtered comments visible

  • E2E test:

    • reviewer requests changes

    • creator clicks notification

    • creator lands on canvas with feedback sheet open

Known Limitations

  • SubmitReviewModal collects final notes but does not send or persist them.

  • Approval notifications route to quest overview, not the feedback panel.

  • CHANGES_REQUESTED notifications open all feedback but do not identify a specific comment or node.

  • notifications.data.comment_id is stored but not currently used by CommentPanel to scroll to a specific thread.

  • Notification polling runs every 30 seconds; there is no realtime subscription.

  • The notification click handler supports hash storage for other flows, but reviewer feedback links currently rely on query parameters.

  • Closing the feedback sheet removes comments but leaves node_id in the URL.

  • Comment notification insertion is fire-and-forget; failures do not retry.


MAINTENANCE & SUPPORT

Troubleshooting

Creator clicks notification but feedback panel does not open

  • Confirm the notification link contains comments=true.

  • Confirm the route is under /quest-editor/<questId>/... so QuestEditorLayout is mounted.

  • Confirm CommentPanel receives forceOpen={commentsMode}.

  • Check browser console for route or fetch errors.

Feedback panel opens but shows no comments

  • Confirm comments exist in quest_comments for the quest.

  • If node_id is present, confirm the comment uses the same node_id.

  • Try removing node_id from the URL to show all quest comments.

  • Check /api/reviewer/comments?quest_id=<questId>&node_id=<nodeId>.

Notification does not appear for creator

  • Confirm notifyCreatorOfNewComment or notifyCreatorOfChangesRequested was called.

  • Confirm the quest has a valid creator_id.

  • Check [comment-notifications] server logs.

  • Inspect notifications.to_user_id and confirm it matches the creator's internal app_users.id.

Notification remains unread after click

  • Check /api/notifications/update-notifications response.

  • Confirm the notification belongs to the authenticated user.

  • Confirm notifications.is_read and read_at update in Supabase.

Creator cannot reply to feedback

  • Confirm the thread is displayed in CommentThread.

  • Confirm the creator has an allowed role for /api/reviewer/comments/create.

  • Check request payload includes parent_comment_id.

  • Check validation errors for empty or oversized comment content.

Reviewer requested changes but creator lands on content page instead of feedback panel

  • In-app CHANGES_REQUESTED notifications should link to visual canvas with comments=true.

  • Status email links currently use /quest-editor/<questId>/content, which does not explicitly open the feedback panel.

  • Update the email notification link to the same visual-canvas deep link if email click-through must open View Feedback.

Changelog

  • 1.0 - Approved, Initial internal technical guide for View Feedback notification deep links, 04/15/2026


Document version:

  • 1.0 - Published, Feature pushed to dev server after initial dev review, 06/30/2026


Was this article helpful?