Notifications
Almost every cross-app event in Scholiphi fans out a notification: a teacher publishes a notice, a student submits homework, a parent gets a PTM invite. Notifications are delivered as push (via Firebase) when the recipient's device has registered, and stored as in-app records that show up in each app's Notifications page. Tapping a notification deep-links to the source feature.
At a glance
| Who can do this | All recipients (teachers, students, parents) — receive. Teachers and admins effectively trigger most events. |
| Where it lives | Teacher app /dashboard/notifications · Student app /dashboard/notifications · Parent app /notifications |
| Triggers | Homework, submissions, attendance, exam updates, notices/alerts, PTM, doubts, results, achievements, chat messages, coin/credit grants |
| Related features | Messages & Chat · Notice Board & Alerts · Homework · Doubts |
Trigger map
What fires a notification, to whom, and the in-app type it carries.
| Source event | Recipient | Type code | In-app category |
|---|---|---|---|
| Homework published | Student + Parent | homework | Homework / Submissions |
| Student submits homework | Teacher | submission | Submissions |
| Submission marked / reviewed | Student + Parent | submission / result | Submissions / Results |
| Notice / alert published | Targeted students + parents | announcement, urgent, holiday, event, notice | Announcements |
EXAM alert / new exam scheduled | Student + Parent | exam | Exams |
PTM / MEETING alert | Parent | ptm / meeting | Announcements |
RESULT alert / exam results released | Student + Parent | result | Results |
| Attendance marked (absent, late) | Parent | attendance | Attendance |
| Doubt answered by AI / teacher | Student | doubt | Doubts |
| New chat message | Other party | (chat) | Push only — does not appear in in-app list (chat has its own unread surface) |
| Coin / credit grant or request approved | Student | general | General |
| Achievement / badge earned | Student | general | General |
How it flows
Lifecycle
Step-by-step
1. Push registration
- On every authenticated app launch, the app calls the push registration endpoint with: FCM token, role (
teacher/student/parent/independent_student), and a stable device id. - Web disables push when
VITE_ENABLE_PUSH=false. - Logout clears the local push handler and disconnects the socket.
2. Receiving a push
- Foreground: in-app toast (sonner) and the Notifications list updates on next visit.
- Background / killed: native banner / lockscreen entry.
- Tap behavior: each notification carries a
data.url. Tapping routes via React Router (in-app) orwindow.location.hreffor absolute URLs. The handler is wired at app root so deep-links land correctly without bouncing through/.
3. The Notifications page
- Teacher:
/dashboard/notifications - Student:
/dashboard/notifications - Parent:
/notifications
All three pages share the same shape:
- Page size: 50 per fetch.
- Header shows total + unread count.
- Filter tabs (per app):
- Teacher:
All,Unread,Submissions,Attendance,Announcements. - Student:
All,Unread,Homework,Announcements. - Parent:
All,Unread. Filter is via theunreadOnlytoggle.
- Teacher:
- Sections: TODAY, YESTERDAY, OLDER.
- Cards show: type icon (color-coded by category), title, body preview, relative time, unread indicator (left bar).
- Empty state: large bell + "You're all caught up!"
4. Marking as read
- Tap a card → marks that one notification read (badge decrements) AND navigates to
data.url. - Parent app exposes a Mark all as read button (zeroes unread count, keeps cards in list).
- Teacher and student apps mark per-card on tap; bulk mark-read is parent-only today.
5. Type → icon mapping (parent app, illustrative)
| Type | Icon | Color |
|---|---|---|
EXAM / TEST | document | violet |
EVENT | calendar | blue |
PTM / MEETING | users | indigo |
HOMEWORK | book | pink |
SUBMISSION | clipboard-check | emerald |
URGENT | alert-triangle | red |
ATTENDANCE | user-check | sky |
HOLIDAY | palmtree | emerald |
RESULT | trophy | amber |
NOTICE | megaphone | orange |
DOUBT | message-circle-question | purple |
GENERAL | bell | grey |
Teacher and student apps use the same vocabulary with their own palette.
Edge cases & things to test
- Token rotation: uninstall and reinstall the app — the new FCM token must be re-registered on next login; the stale token must stop receiving (server-side cleanup / 410 handling).
- Multi-device: parent logged in on phone AND tablet — both should ring; reading on one should mark in-app read for both.
- Logout while pushes pending: log out — pushes should stop arriving; existing in-app rows for that user must NOT be shown to the next user on the device.
- Permission denied: user denies push permission — in-app notifications must still work; no client-side errors.
- Deep-link to deleted resource: tap a homework push whose homework was deleted — graceful 404 / toast, not a crash.
- Time grouping at midnight: a push received at 11:59 PM viewed at 12:01 AM — sectioning into TODAY/YESTERDAY/OLDER must match the open time, not the receive time.
- Mark-all-read while new pushes arrive: race — a push that arrives mid-request should remain unread.
- Notification fan-out scale: 60 students × 2 parents = 180 recipients on one alert publish — all must receive within ~30 seconds.
- Filter tab stickiness: switch to Submissions tab, navigate away, return — does the filter persist or reset?
- Chat push vs in-app list: chat notifications must appear as push but should NOT clutter the in-app notifications page (chat has its own unread surface in
/messages). - VITE_ENABLE_PUSH=false: confirm web build cleanly skips registration without errors in console.
- Parent multi-child: an attendance push for Child A — does the in-app card make it clear which child it concerns?
Related
- Messages & Chat — chat sends push but stays out of the in-app list
- Notice Board & Alerts — every alert publish fans out a push
- Homework — assign + review actions trigger notifications
- Attendance — absent / late marking triggers parent push
- Doubts — answering a doubt notifies the asker