feat: split header notifications into Unread and Archive views#155
Merged
Conversation
Previously the notification bell fetched every notification the user
had ever received (read or unread) in a single combined list, making
it hard to focus on actionable items. This change splits the dropdown
into two views — Unread (default on every open) and Archive — gated
by a single toggle button in the dropdown head.
Changes:
- Backend: GET /api/v1/app-notification/notification accepts a new
optional `filter` query param ('unread' | 'archived'). 'unread' adds
`notSeen: { $in: [userId] }` to the aggregation match; 'archived'
adds `notSeen: { $nin: [userId] }`. Default is 'unread' to keep the
bell focused on actionable items. Refactored the match clauses into
a `baseMatch` array so the filter is appended cleanly; query shape
and pagination are otherwise unchanged.
- Header.vue: added a `notificationFilter` ref ('unread' by default),
a "View Archive" / "View Unread" toggle in the dropdown head, a
`switchNotificationFilter()` handler that resets paging state and
refetches, and an `openNotificationsDropdown()` helper that the
bell click handlers now use so each fresh dropdown open lands in
Unread. `markRead()` and `markAllRead()` clear the read items from
the local list while the Unread filter is active so the dropdown
reflects the filter without an extra refetch. The "Mark all as
read" button visibility now keys off `notifications.length` (the
list is already filtered to unread on this view) rather than the
server-side `totalNotification` counter, which can lag and falsely
hide the button.
- i18n: added Header.View_Archive / Header.View_Unread to the English
locale; other locales fall back to English via vue-i18n until
translators backfill (flagged as a follow-up).
Out of scope (deferred per user instruction): goals 3 and 4 from the
original spec — creator-prefs fire policy verification and email
preference parity audit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes goals 3 & 4 of the notification refactor. Two parallel bypasses in handleNotification.HandleBothNotification let task creators and company owners through the project-level watcher filter (the Ignore / All Activity / Participating setting in the List of Watcher panel): - Task branch (taskId path): Task_Leader was Set-union'd into the recipient list AFTER `projectData.watchers` had already filtered out any user set to "ignore". So a creator who had set the project to Ignore still ended up in `assigneeUsers`, and the downstream per-event preference check (NOTIFICATIONS_SETTINGS — a separate preference layer that defaults email=true) emitted both an in-app and an email notification. Now Task_Leader is included only if their project-watcher setting is not "ignore". - Project branch (type === 'project'): same pattern — companyOwnerId was union'd in unconditionally, bypassing the watcher filter. Honours "ignore" too. This explains the goal-4 symptom of "I'm getting emails for events I disabled": the disablement was set at the project-watcher layer, but the bypass routed the recipient straight to the per-event layer where email was still on. Other recipient paths are untouched. Default behaviour for users who have not chosen "ignore" is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previously the notification bell fetched every notification the user had ever received (read or unread) in a single combined list, making it hard to focus on actionable items. This change splits the dropdown into two views — Unread (default on every open) and Archive — gated by a single toggle button in the dropdown head.
Changes:
filterquery param ('unread' | 'archived'). 'unread' addsnotSeen: { $in: [userId] }to the aggregation match; 'archived' addsnotSeen: { $nin: [userId] }. Default is 'unread' to keep the bell focused on actionable items. Refactored the match clauses into abaseMatcharray so the filter is appended cleanly; query shape and pagination are otherwise unchanged.notificationFilterref ('unread' by default), a "View Archive" / "View Unread" toggle in the dropdown head, aswitchNotificationFilter()handler that resets paging state and refetches, and anopenNotificationsDropdown()helper that the bell click handlers now use so each fresh dropdown open lands in Unread.markRead()andmarkAllRead()clear the read items from the local list while the Unread filter is active so the dropdown reflects the filter without an extra refetch. The "Mark all as read" button visibility now keys offnotifications.length(the list is already filtered to unread on this view) rather than the server-sidetotalNotificationcounter, which can lag and falsely hide the button.Out of scope (deferred per user instruction): goals 3 and 4 from the original spec — creator-prefs fire policy verification and email preference parity audit.
Pull Request Template Chooser
Please click the link that matches your contribution type to load the correct format.
Bug Fix
Use this for fixing broken logic or UI glitches.
New Feature
Use this for adding new functionality or components.
Refactor
Use this for code cleanup, performance tweaks, or technical debt.
General Summary
If you don't want to use a specific template, please provide a brief summary of your changes below.