Skip to content

Phase 5 frontend - #8

Merged
Aditya2550 merged 8 commits into
mainfrom
phase-5-frontend
Aug 8, 2026
Merged

Aditya2550 merged 8 commits into
mainfrom
phase-5-frontend

Conversation

@Aditya2550

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI lite review requested due to automatic review settings August 8, 2026 17:14
@Aditya2550
Aditya2550 merged commit f5b9884 into main Aug 8, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the app’s role-based navigation and introduces a real notifications flow (REST + websocket + toast UI), including backend support to mark notifications as read and to notify approvers when a new expense is submitted.

Changes:

  • Add finance/director role routing to manager/approval queue destinations.
  • Implement NotificationContext-driven notifications (initial REST load + realtime socket updates) and a toast stack with dismiss support.
  • Add backend endpoint to mark notifications read and emit notifications on expense submission.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/pages/LoginPage.jsx Adds finance/director role redirects during login and auth-state redirect.
frontend/src/features/notifications/services/notifications.api.js Adds REST API call to mark a notification as read.
frontend/src/features/notifications/hooks/useRealtimeNotifications.js Removes old realtime notifications hook in favor of context-based approach.
frontend/src/features/notifications/components/ToastStack.jsx Adds dismiss handler support for toast items.
frontend/src/features/notifications/components/NotificationBell.jsx Switches bell UI from mock data to NotificationContext data and read-state.
frontend/src/context/NotificationContext.jsx Introduces centralized notifications + toasts state, REST bootstrap, and websocket subscription.
frontend/src/components/layout/AppLayout.jsx Wires toast stack to context-provided toasts and dismiss action.
frontend/src/app/router.jsx Updates role home redirect logic for finance/director.
backend/src/modules/notifications/notifications.routes.js Adds PATCH route for marking notifications read.
backend/src/modules/notifications/notifications.model.js Adds model method to update is_read flag.
backend/src/modules/notifications/notifications.controller.js Implements mark-notification-read controller.
backend/src/modules/expenses/expenses.validator.js Allows receipt_url to be null (nullable) in request validation.
backend/src/modules/expenses/expenses.controller.js Emits notification to the first approver when an expense is created.
backend/src/app.js Adjusts middleware ordering for rate limiting.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 16 to +20
useEffect(() => {
if (!isAuthenticated) return;
if (!isAuthenticated) return;

const role = String(user?.role || "").toLowerCase();
if (role === "admin") navigate("/admin", { replace: true });
else if (role === "manager") navigate("/manager", { replace: true });
else navigate("/employee", { replace: true });
}, [isAuthenticated, user?.role, navigate]);
const role = String(user?.role || "").toLowerCase();
if (role === "admin") navigate("/admin", { replace: true });
Comment on lines +23 to +26
<button
onClick={() => onDismiss?.(toast.id)}
className="text-surface-400 hover:text-forest-600 transition-colors flex-shrink-0"
>
Comment on lines +101 to +109
const firstApprover = await getCurrentPendingApprover(expense.id, pool);
if (firstApprover) {
const note = await notificationsModel.create({
userId: firstApprover.id,
title: "New expense pending your approval",
body: `${submitter.name || "An employee"} submitted a new expense for review.`,
});
notifyUser(firstApprover.id, note.rows[0]);
}
Comment on lines +9 to +14
export const markNotificationRead = asyncHandler(async (req, res) => {
const result = await notificationsModel.markRead(req.params.id, req.user.id);
if (!result.rows[0])
return res.status(404).json({ message: "Notification not found" });
res.json({ notification: result.rows[0] });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants