Skip to content

issue #215/added: toast messages#232

Open
manjeetsinghmeena wants to merge 16 commits intoiiitl:mainfrom
manjeetsinghmeena:feature-toast_notifications
Open

issue #215/added: toast messages#232
manjeetsinghmeena wants to merge 16 commits intoiiitl:mainfrom
manjeetsinghmeena:feature-toast_notifications

Conversation

@manjeetsinghmeena
Copy link
Copy Markdown

@manjeetsinghmeena manjeetsinghmeena commented Apr 11, 2026

Resolves #215

Description

Implement toast notification system in the project to show user feedback for actions like success, error, info, and warning messages. This resolves #215.

Toast notifications now display feedback for:

  • Success or failure on user sign up / login
  • Success or failure when uploading notes or question papers
  • Form validation errors
  • File upload errors

Changes Made

  • Created context/toast-provider.tsx - Toast context provider with useToast hook
  • Added keyframe animation slideIn to app/globals.css
  • Updated app/layout.jsx to wrap app with <ToastProvider>
  • Added toast notifications to app/auth/signin/page.tsx
  • Added toast notifications to app/upload-notes/page.tsx
  • Added toast notifications to app/upload-papers/page.tsx
  • Removed old inline error/success alerts and replaced with toasts

Live Demo

Screenshot 2026-04-12 025315

Checkout

  • I have read all the contributor guidelines for the repo.

Summary by CodeRabbit

  • New Features

    • App-wide toast notifications (success/error/info/warning) with auto-dismiss (~3s) and slide-in animation; available across pages via layout integration.
  • Bug Fixes / UX

    • Replaced inline alert banners with unified toasts for sign-in (including Google), note/paper uploads, and validation feedback.
    • Chat widget removed from the global layout.
  • Accessibility

    • Added aria labels and a descriptive title to form controls in Quick Reads.

Copilot AI review requested due to automatic review settings April 11, 2026 21:31
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 11, 2026

@manjeetsinghmeena is attempting to deploy a commit to the mrimmortal09's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a client-side toast system and Provider, replaces component-local inline alert banners in sign-in, notes upload, and papers upload with toast-based feedback, wraps the app subtree with ToastProvider in RootLayout, and appends a slideIn keyframe to global styles.

Changes

Cohort / File(s) Summary
Toast System (new)
context/toast-provider.tsx
New ToastProvider, useToast hook, ToastMessage/ToastType exports; manages toast list, addToast/removeToast, auto-dismiss (3000ms), viewport rendering and per-type visuals.
Authentication (Sign‑in)
app/auth/signin/page.tsx
Removed local error state and inline alert UI; replaced all error/info/success branches in handleSubmit and handleGoogleSignIn with addToast(...) calls; removed unused AlertCircle import.
Uploads — Notes
app/upload-notes/page.tsx
Removed error/success state and inline alerts; replaced validation, success, and catch flows with addToast(...); file upload POST and control flow preserved.
Uploads — Papers
app/upload-papers/page.tsx
Removed error/success state and inline alerts/icons; validation failures, size/type checks, success, and errors now call addToast(...); submission logic unchanged.
App Layout & Styles
app/layout.jsx, app/globals.css
Wrapped app subtree (Header, children, Footer, Analytics region) with <ToastProvider> in RootLayout; removed ChatWidget from this layout; appended @keyframes slideIn to globals.css.
Quick Reads accessibility
app/quick-reads/page.tsx
Added aria-label and title attributes to existing controls (no control flow changes).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Client as App UI
    participant Auth as Auth/API
    participant Upload as Upload/API
    participant Toast as ToastProvider

    User->>Client: submit credentials / click Google sign-in / submit file
    alt sign-in
        Client->>Auth: signIn(credentials) or signIn('google')
        Auth-->>Client: success or error
        Client->>Toast: addToast(title, description?, type)
        opt success
            Client->>User: navigate / refresh
        end
    else upload
        Client->>Upload: POST /api/notes or /api/papers
        Upload-->>Client: success or error
        Client->>Toast: addToast(title, description?, type)
    end
    Note right of Toast: Toasts render in viewport, auto-dismiss after 3000ms or dismissed manually
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

accepted-50

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning While toast notifications were added to signin, upload-notes, and upload-papers pages, the pull request does not address sign-up/registration feedback as required by issue #215. Update the sign-up page to integrate toast notifications for success/failure feedback to fully satisfy issue #215 requirements.
Out of Scope Changes check ⚠️ Warning The pull request includes out-of-scope changes: accessibility attributes added to app/quick-reads/page.tsx (aria-label and title attributes) are unrelated to the toast notification system scope. Remove the accessibility attribute changes from app/quick-reads/page.tsx or defer them to a separate pull request focused on accessibility improvements.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'issue #215/added: toast messages' clearly summarizes the main change—implementing toast notifications for user feedback as specified in issue #215.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/upload-notes/page.tsx (1)

21-21: ⚠️ Potential issue | 🟡 Minor

Remove unused AlertCircle import.

AlertCircle is imported but never used in the component. Remove it from the lucide-react import statement at line 21.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/upload-notes/page.tsx` at line 21, Remove the unused AlertCircle import
from the lucide-react import statement in the upload-notes page component:
locate the import line that includes AlertCircle and delete only the AlertCircle
identifier so the import only includes icons actually used in the component
(e.g., keep other symbols but remove AlertCircle).
app/upload-papers/page.tsx (1)

44-45: ⚠️ Potential issue | 🟡 Minor

success state is completely unused and should be removed.

The success state is set on line 196 but never read anywhere in the component. Since feedback is provided entirely through toast notifications, this variable serves no purpose and can be safely removed.

The error state, however, is read in the file change handler (line 111) to clear errors when a new file is selected. While it's not rendered in the JSX, keeping it allows users to start fresh when selecting a new file. You may keep this if that behavior is intentional, or remove it if you want to simplify further.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/upload-papers/page.tsx` around lines 44 - 45, Remove the unused success
state and its updater: delete the useState declaration for success and all
references to setSuccess (e.g., the call that sets success on submission). Keep
the error state/useState("error" and setError) if you want to preserve the
behavior in the file change handler that clears prior errors; otherwise remove
error and its usages as well. Ensure any toast-based success feedback remains
unchanged and run a quick search for "success" to remove leftover references
(e.g., calls to setSuccess or checks against success) and update imports/types
if needed.
🧹 Nitpick comments (6)
app/upload-notes/page.tsx (1)

46-47: Consider removing unused error and success state.

Same as in upload-papers/page.tsx — these state variables are set but no longer rendered after switching to toast notifications.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/upload-notes/page.tsx` around lines 46 - 47, The file declares unused
React state variables error, setError, success, and setSuccess via useState in
upload-notes/page.tsx; remove those declarations and any calls to setError or
setSuccess and any references to error/success, and also remove any now-unused
imports (e.g., useState) if they become unused, mirroring the cleanup already
done in upload-papers/page.tsx so the component relies solely on toast
notifications.
context/toast-provider.tsx (2)

31-33: Use substring instead of deprecated substr.

String.prototype.substr is deprecated. Use substring instead for future compatibility.

🔧 Proposed fix
-    const id = Math.random().toString(36).substr(2, 9)
+    const id = Math.random().toString(36).substring(2, 11)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@context/toast-provider.tsx` around lines 31 - 33, Replace the deprecated
String.prototype.substr call used when generating the toast id with substring to
ensure future compatibility: in the id generation line (where id is assigned via
Math.random().toString(36).substr(2, 9)) change to use
Math.random().toString(36).substring(2, 11) (or equivalent slice) so the
resulting id length remains the same; keep the surrounding logic that calls
setToasts([...]) and the setTimeout that calls removeToast(id) unchanged.

123-128: Consider adding accessibility attributes to the dismiss button.

The dismiss button lacks an accessible label for screen readers.

♿ Proposed fix
         <button
           onClick={() => onRemove(id)}
-          className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 flex-shrink-0"
+          className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 flex-shrink-0"
+          aria-label="Dismiss notification"
         >
           <X className="w-4 h-4" />
         </button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@context/toast-provider.tsx` around lines 123 - 128, The dismiss button in
toast-provider.tsx (the <button> that calls onRemove(id) and renders the X icon)
lacks an accessible label; add an explicit accessible name and proper button
semantics by setting type="button" and an aria-label (e.g. "Dismiss
notification" or a dynamic label using the toast title/description if available)
and optionally a title attribute for tooltip support so screen readers and
keyboard users can identify the control.
app/globals.css (1)

81-90: Rename keyframes to kebab-case for consistency with Stylelint rules.

The keyframes name slideIn should follow kebab-case naming convention (slide-in) as flagged by Stylelint. This will require updating the animation reference in context/toast-provider.tsx line 102 as well.

🔧 Proposed fix

In app/globals.css:

-@keyframes slideIn {
+@keyframes slide-in {
   from {
     transform: translateX(100%);
     opacity: 0;
   }
   to {
     transform: translateX(0);
     opacity: 1;
   }
 }

In context/toast-provider.tsx (line 102):

       style={{
-        animation: 'slideIn 0.3s ease-in-out',
+        animation: 'slide-in 0.3s ease-in-out',
       }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/globals.css` around lines 81 - 90, Rename the keyframes identifier
slideIn to kebab-case slide-in in the CSS `@keyframes` declaration in globals.css
and update every usage to match; specifically update the animation reference in
context/toast-provider.tsx (where animation: slideIn is used around the toast
rendering at the cited location) to use slide-in so Stylelint passes and the
animation still applies.
app/auth/signin/page.tsx (1)

121-128: Redundant error feedback: both inline alert and toast are shown.

Unlike the upload pages where inline alerts were removed, this page still renders the inline error alert while also showing toast notifications for errors. This results in duplicate error feedback to users.

Consider either:

  1. Removing the inline error alert (consistent with upload pages), or
  2. Removing the error toasts and keeping only the inline alert
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/auth/signin/page.tsx` around lines 121 - 128, The page currently shows
duplicate error feedback by rendering the inline alert block conditional on the
error variable (the {error && (...)} JSX that uses AlertCircle) while also
emitting toast notifications (e.g., calls to toast.error elsewhere); remove the
inline alert to match the upload pages—delete the {error && (...)} block (the
div containing AlertCircle and <span>{error}</span>) so errors are only reported
via toasts, or if you prefer inline alerts instead, remove the toast.error calls
and keep the {error && ...} block; pick one approach and apply it consistently.
app/upload-papers/page.tsx (1)

23-24: Remove unused imports CheckCircle and AlertCircle.

These icons are no longer used after removing the inline alert UI from the component.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/upload-papers/page.tsx` around lines 23 - 24, Remove the now-unused icon
imports from the component: delete CheckCircle and AlertCircle from the import
list where they are imported (symbols CheckCircle, AlertCircle) in the
upload-papers page component, and run the linter or TypeScript check to ensure
no other references remain; this cleans up unused imports and resolves related
warnings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@app/upload-notes/page.tsx`:
- Line 21: Remove the unused AlertCircle import from the lucide-react import
statement in the upload-notes page component: locate the import line that
includes AlertCircle and delete only the AlertCircle identifier so the import
only includes icons actually used in the component (e.g., keep other symbols but
remove AlertCircle).

In `@app/upload-papers/page.tsx`:
- Around line 44-45: Remove the unused success state and its updater: delete the
useState declaration for success and all references to setSuccess (e.g., the
call that sets success on submission). Keep the error state/useState("error" and
setError) if you want to preserve the behavior in the file change handler that
clears prior errors; otherwise remove error and its usages as well. Ensure any
toast-based success feedback remains unchanged and run a quick search for
"success" to remove leftover references (e.g., calls to setSuccess or checks
against success) and update imports/types if needed.

---

Nitpick comments:
In `@app/auth/signin/page.tsx`:
- Around line 121-128: The page currently shows duplicate error feedback by
rendering the inline alert block conditional on the error variable (the {error
&& (...)} JSX that uses AlertCircle) while also emitting toast notifications
(e.g., calls to toast.error elsewhere); remove the inline alert to match the
upload pages—delete the {error && (...)} block (the div containing AlertCircle
and <span>{error}</span>) so errors are only reported via toasts, or if you
prefer inline alerts instead, remove the toast.error calls and keep the {error
&& ...} block; pick one approach and apply it consistently.

In `@app/globals.css`:
- Around line 81-90: Rename the keyframes identifier slideIn to kebab-case
slide-in in the CSS `@keyframes` declaration in globals.css and update every usage
to match; specifically update the animation reference in
context/toast-provider.tsx (where animation: slideIn is used around the toast
rendering at the cited location) to use slide-in so Stylelint passes and the
animation still applies.

In `@app/upload-notes/page.tsx`:
- Around line 46-47: The file declares unused React state variables error,
setError, success, and setSuccess via useState in upload-notes/page.tsx; remove
those declarations and any calls to setError or setSuccess and any references to
error/success, and also remove any now-unused imports (e.g., useState) if they
become unused, mirroring the cleanup already done in upload-papers/page.tsx so
the component relies solely on toast notifications.

In `@app/upload-papers/page.tsx`:
- Around line 23-24: Remove the now-unused icon imports from the component:
delete CheckCircle and AlertCircle from the import list where they are imported
(symbols CheckCircle, AlertCircle) in the upload-papers page component, and run
the linter or TypeScript check to ensure no other references remain; this cleans
up unused imports and resolves related warnings.

In `@context/toast-provider.tsx`:
- Around line 31-33: Replace the deprecated String.prototype.substr call used
when generating the toast id with substring to ensure future compatibility: in
the id generation line (where id is assigned via
Math.random().toString(36).substr(2, 9)) change to use
Math.random().toString(36).substring(2, 11) (or equivalent slice) so the
resulting id length remains the same; keep the surrounding logic that calls
setToasts([...]) and the setTimeout that calls removeToast(id) unchanged.
- Around line 123-128: The dismiss button in toast-provider.tsx (the <button>
that calls onRemove(id) and renders the X icon) lacks an accessible label; add
an explicit accessible name and proper button semantics by setting type="button"
and an aria-label (e.g. "Dismiss notification" or a dynamic label using the
toast title/description if available) and optionally a title attribute for
tooltip support so screen readers and keyboard users can identify the control.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08372caa-1a96-43d3-8b82-db95ea943f80

📥 Commits

Reviewing files that changed from the base of the PR and between 10e2e8b and 59955a6.

📒 Files selected for processing (6)
  • app/auth/signin/page.tsx
  • app/globals.css
  • app/layout.jsx
  • app/upload-notes/page.tsx
  • app/upload-papers/page.tsx
  • context/toast-provider.tsx

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements a lightweight toast notification system and integrates it into key user flows to provide consistent feedback (validation, upload results, auth outcomes) across the app.

Changes:

  • Added a ToastProvider + useToast hook to manage and render toast notifications globally.
  • Wrapped the application layout with ToastProvider so toasts can be triggered from any client page.
  • Replaced several inline success/error alert UIs in upload flows with toast notifications, and added toast feedback to sign-in.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
context/toast-provider.tsx Introduces toast context/provider and UI rendering for notifications.
app/layout.jsx Wraps the app shell in ToastProvider to enable global toasts.
app/globals.css Adds slideIn keyframe animation used by toast items.
app/auth/signin/page.tsx Adds toast notifications for validation/auth outcomes and Google sign-in redirect.
app/upload-notes/page.tsx Adds toasts for validation/upload outcomes and removes inline alert rendering.
app/upload-papers/page.tsx Adds toasts for validation/upload outcomes and removes inline alert rendering.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +34
const addToast = (
title: string,
description?: string,
type: ToastType = 'info'
) => {
const id = Math.random().toString(36).substr(2, 9)
setToasts((prev) => [...prev, { id, title, description, type }])
setTimeout(() => removeToast(id), 3000)
}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

addToast generates IDs via Math.random().toString(36).substr(...), which can collide and uses deprecated substr. Prefer a stronger unique id (e.g., crypto.randomUUID() with a fallback) or an incrementing counter stored in a ref.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +38
export const ToastProvider = ({ children }: { children: ReactNode }) => {
const [toasts, setToasts] = useState<ToastMessage[]>([])

const addToast = (
title: string,
description?: string,
type: ToastType = 'info'
) => {
const id = Math.random().toString(36).substr(2, 9)
setToasts((prev) => [...prev, { id, title, description, type }])
setTimeout(() => removeToast(id), 3000)
}

const removeToast = (id: string) => {
setToasts((prev) => prev.filter((toast) => toast.id !== id))
}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

addToast schedules a setTimeout that isn't cleared on unmount. If the provider ever unmounts (or during fast refresh), this can trigger state updates on an unmounted component. Track timeout handles and clear them in an effect cleanup (or use a ref-based timer map per toast).

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +128
<button
onClick={() => onRemove(id)}
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 flex-shrink-0"
>
<X className="w-4 h-4" />
</button>
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

Toast UI is missing basic a11y hooks: the close icon button has no accessible name, and the viewport/items don't expose an aria-live region/appropriate role (e.g., status for info/success, alert for error). Add aria-label to the close button and an aria-live container (or per-toast roles) so screen readers announce notifications.

Copilot uses AI. Check for mistakes.
Comment thread app/upload-notes/page.tsx Outdated
Comment on lines +116 to +138
if (
!finalSubject ||
!formData.facultyName ||
!formData.year ||
!formData.semester ||
!formData.term ||
!formData.uploaded_file
) {
const msg = 'Please fill in all required fields'
setError(msg)
addToast('Validation Error', msg, 'error')
setIsLoading(false)
return
}

const allowedTypes = [
'application/pdf',
'image/png',
'image/jpeg',
'image/webp',
]
if (!allowedTypes.includes(formData.uploaded_file.type)) {
setError('Only PDF, PNG, JPG, JPEG, and WEBP files are allowed')
setIsLoading(false)
return
}
const maxSize = 25 * 1024 * 1024
if (formData.uploaded_file.size > maxSize) {
const msg = 'File size must be less than 25MB'
setError(msg)
addToast('File Too Large', msg, 'error')
setIsLoading(false)
return
}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

The validation early-returns inside the try block call setIsLoading(false) before returning, but the finally also always calls setIsLoading(false). This causes redundant state updates/renders; remove the pre-return setIsLoading(false) calls (or move validation before the try).

Copilot uses AI. Check for mistakes.
Comment thread app/upload-notes/page.tsx
Comment on lines 219 to 229
return (
<div className="w-full flex flex-col items-center justify-center">
<div className="w-full max-w-2xl px-5 mt-6 mb-10 space-y-6">
{/* Header */}
<div className="flex flex-col sm:flex-row sm:relative sm:justify-center items-center gap-3">
<h1 className="text-3xl font-semibold text-center">Upload a Note</h1>
</div>

{/* Alerts */}
{error && (
<div className="flex items-start gap-3 px-4 py-3 rounded-md border border-destructive/40 bg-destructive/10 text-destructive text-sm">
<AlertCircle className="w-4 h-4 mt-0.5 flex-shrink-0" />
<div>
<p className="font-medium">Upload failed</p>
<p className="text-xs mt-0.5 opacity-80">{error}</p>
</div>
<button
onClick={() => setError(null)}
className="ml-auto flex-shrink-0 opacity-70 hover:opacity-100"
>
</button>
</div>
)}
{success && (
<div className="flex items-start gap-3 px-4 py-3 rounded-md border border-green-500/40 bg-green-500/10 text-green-600 dark:text-green-400 text-sm">
<CheckCircle className="w-4 h-4 mt-0.5 flex-shrink-0" />
<p className="font-medium">{success}</p>
<button
onClick={() => setSuccess(null)}
className="ml-auto flex-shrink-0 opacity-70 hover:opacity-100"
>
</button>
</div>
)}

{/* Form */}
<form onSubmit={handleSubmit} className="space-y-5">
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

After removing the inline alert UI, AlertCircle imported from lucide-react is no longer used in this file. Please remove the unused import to satisfy the repo's ESLint rules.

Copilot uses AI. Check for mistakes.
Comment thread app/upload-papers/page.tsx Outdated
Comment on lines +124 to +146
if (
!finalSubject ||
!formData.year ||
!formData.semester ||
!formData.term ||
!formData.uploaded_file
) {
const msg = 'Please fill in all required fields'
setError(msg)
addToast('Validation Error', msg, 'error')
setIsLoading(false)
return
}

// Validate file size (25MB max)
const maxSize = 25 * 1024 * 1024 // 25MB in bytes
if (formData.uploaded_file.size > maxSize) {
setError('File size must be less than 25MB')
setIsLoading(false)
return
}
// Validate file size (25MB max)
const maxSize = 25 * 1024 * 1024 // 25MB in bytes
if (formData.uploaded_file.size > maxSize) {
const msg = 'File size must be less than 25MB'
setError(msg)
addToast('File Too Large', msg, 'error')
setIsLoading(false)
return
}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

Similar to upload-notes: inside handleSubmit, validation early-returns call setIsLoading(false) but the finally also calls setIsLoading(false) even when returning from try. Drop the redundant pre-return updates to avoid extra renders.

Copilot uses AI. Check for mistakes.
Comment on lines 258 to 262
<Card className="shadow-lg">
<CardContent>
{/* Error Message */}
{error && (
<div className="mb-6 p-4 bg-destructive/10 border border-destructive rounded-lg flex items-start gap-3">
<AlertCircle className="h-5 w-5 text-destructive mt-0.5" />
<div>
<h4 className="font-medium text-destructive">Error</h4>
<p className="text-sm text-destructive/90">{error}</p>
</div>
</div>
)}

{/* Success Message */}
{success && (
<div className="mb-6 p-4 bg-green-500/10 border border-green-500 rounded-lg flex items-start gap-3">
<CheckCircle className="h-5 w-5 text-green-500 mt-0.5" />
<div>
<h4 className="font-medium text-green-500">Success</h4>
<p className="text-sm text-green-500/90">{success}</p>
</div>
</div>
)}

<form onSubmit={handleSubmit} className="space-y-6">
{/* Subject Field */}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

The inline error/success alert blocks were removed, but the CheckCircle/AlertCircle icon imports used by those blocks are now unused in this file (the remaining file-selected indicator uses a literal ✓). Remove the unused icon imports to satisfy ESLint.

Copilot uses AI. Check for mistakes.
Comment thread app/auth/signin/page.tsx
Comment on lines 1 to 17
@@ -13,6 +13,7 @@ export default function SignIn() {
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
const router = useRouter()
const { addToast } = useToast()

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

PR description says inline alerts were replaced with toasts, but this page still renders an inline error banner ({error && ...}) in addition to showing toast errors. This can lead to duplicated messaging; either remove the inline banner or avoid triggering toasts for the same errors on this page.

Copilot uses AI. Check for mistakes.
Comment thread app/upload-notes/page.tsx Outdated
Comment on lines +178 to +196
if (!response.ok) throw new Error(data.message || 'Failed to upload note')

const successMsg = 'Note uploaded successfully!'
setSuccess(successMsg)
addToast('Upload Successful', successMsg, 'success')
setFormData({
facultyName: '',
content: '',
subject: '',
year: '',
semester: '',
term: '',
category: 'academic',
uploaded_file: null,
})
setCustomSubject('')
setIsNewSubject(false)
if (fileInputRef.current) fileInputRef.current.value = ''
} catch (err) {
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

setSuccess(successMsg) is called, but the success state is never read/rendered anywhere after the inline success alert was removed. This is dead state and will trigger no-unused-vars for the success variable; remove the success state/setter usage or reintroduce UI that consumes it.

Copilot uses AI. Check for mistakes.
Comment thread app/upload-papers/page.tsx Outdated
Comment on lines +194 to +210
// Success
const successMsg = 'Paper uploaded successfully!'
setSuccess(successMsg)
addToast('Upload Successful', successMsg, 'success')

// Reset form
setFormData({
facultyName: '',
content: '',
subject: '',
year: '',
semester: '',
term: '',
uploaded_file: null,
})
setCustomSubject('')
setIsNewSubject(false)
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

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

setSuccess(successMsg) is called, but the success state value is never read/rendered anywhere (the success banner was removed). This leaves dead state and will trigger no-unused-vars for the success variable; remove the success state/setter usage (and consider removing error state too if it's no longer shown).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/globals.css`:
- Around line 81-90: The keyframes name slideIn violates Stylelint's
keyframes-name-pattern; rename the keyframe to kebab-case (e.g., slide-in) in
app/globals.css and update the corresponding animation reference in
context/toast-provider.tsx (the animation usage around the toast component,
previously referencing "slideIn" at ~Line 102) to match the new name; also
search the repo for any other occurrences of "slideIn" and replace them to avoid
lint/ runtime mismatches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 11b64d4f-8a63-44eb-801e-5fbee142da65

📥 Commits

Reviewing files that changed from the base of the PR and between 59955a6 and e6876e1.

📒 Files selected for processing (6)
  • app/auth/signin/page.tsx
  • app/globals.css
  • app/layout.jsx
  • app/upload-notes/page.tsx
  • app/upload-papers/page.tsx
  • context/toast-provider.tsx
✅ Files skipped from review due to trivial changes (2)
  • app/layout.jsx
  • app/auth/signin/page.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/upload-papers/page.tsx
  • app/upload-notes/page.tsx
  • context/toast-provider.tsx

Comment thread app/globals.css
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
app/upload-notes/page.tsx (1)

121-122: Remove redundant loading resets in early returns.

Line 121/130/144 calls setIsLoading(false) before return, but Line 199 already handles this in finally. Keeping only finally avoids repeated state updates.

Also applies to: 130-131, 144-145, 198-200

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/upload-notes/page.tsx` around lines 121 - 122, Remove the redundant
setIsLoading(false) calls that appear immediately before early returns inside
the upload handler function (the places that call setIsLoading(false) at lines
matching the early-return branches) and rely on the existing finally block to
reset loading; specifically, delete the pre-return invocations of
setIsLoading(false) in the upload handling function so only the finally block
performs the state reset, leaving other logic and returns unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/auth/signin/page.tsx`:
- Around line 29-32: Multiple error paths in sign-in emit duplicate toasts by
calling addToast twice (e.g., the 'Only IIITL email addresses are allowed'
block); replace the two calls with a single addToast invocation using the
intended signature (title, message, type) and remove the redundant addToast(msg)
call. Update the same pattern in the other error handlers referenced (the blocks
around the calls at the other indicated ranges) so each failure path emits one
clear toast, and ensure setLoading(false) remains after the single toast call.
- Around line 75-85: Move the setLoading(true) call out of the try block in
handleGoogleSignIn so it always runs before the async signIn('google', {
callbackUrl: '/' }) call, and add a finally block to the try/catch/finally that
calls setLoading(false) to guarantee loading resets regardless of success,
redirect, or unexpected error; keep the existing catch to show toasts on errors
and reference handleGoogleSignIn, setLoading, and signIn when making the
changes.

In `@app/upload-notes/page.tsx`:
- Around line 118-120: The code is triggering duplicate toasts by calling
addToast twice (e.g., addToast(msg) followed by addToast('Validation Error',
msg, 'error')); update each branch in page.tsx (the blocks around msg and
addToast calls at the shown diffs and the other affected ranges) to call
addToast only once, using the preferred signature (title, message, level) and
removing the redundant simple addToast(msg) invocation so each outcome emits a
single, full toast notification.

---

Nitpick comments:
In `@app/upload-notes/page.tsx`:
- Around line 121-122: Remove the redundant setIsLoading(false) calls that
appear immediately before early returns inside the upload handler function (the
places that call setIsLoading(false) at lines matching the early-return
branches) and rely on the existing finally block to reset loading; specifically,
delete the pre-return invocations of setIsLoading(false) in the upload handling
function so only the finally block performs the state reset, leaving other logic
and returns unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5075f203-1b73-451f-82f7-dc7b0ff917fe

📥 Commits

Reviewing files that changed from the base of the PR and between e6876e1 and 902d75a.

📒 Files selected for processing (3)
  • app/auth/signin/page.tsx
  • app/upload-notes/page.tsx
  • context/toast-provider.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • context/toast-provider.tsx

Comment thread app/auth/signin/page.tsx
Comment thread app/auth/signin/page.tsx
Comment thread app/upload-notes/page.tsx Outdated
@MrImmortal09
Copy link
Copy Markdown
Collaborator

@manjeetsinghmeena resolve the merge conflicts.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
student-hub Ready Ready Preview, Comment Apr 12, 2026 10:44am

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/auth/signin/page.tsx`:
- Around line 29-30: Replace bare addToast(...) calls in the failure branches
with the same structured call pattern used for success/info so failures get an
explicit error variant; specifically change uses like addToast(msg) (the one
that sets const msg = 'Only IIITL email addresses are allowed' and the other
occurrences around the sign-in handler) to the structured form that includes
variant: 'error' (e.g., addToast({ title: msg, variant: 'error' })) so all auth
failure paths consistently render as error toasts.

In `@app/upload-papers/page.tsx`:
- Around line 129-130: The toasts use addToast(...) without specifying
type/severity so users don't get consistent cues; update all calls to addToast
in upload-papers/page.tsx (including the validation case where msg = 'Please
fill in all required fields', the other occurrences around the indicated ranges)
to pass an explicit type/level (e.g., { type: 'warning' } for validation, {
type: 'success' } for successful actions, and { type: 'error' } for upload
failures) so the UI shows correct severity; locate and update the addToast calls
and any helper wrapper around addToast to accept and forward a type field.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 10cd57a6-3e90-4651-a18b-763fbc7f8176

📥 Commits

Reviewing files that changed from the base of the PR and between 902d75a and 8514b44.

📒 Files selected for processing (3)
  • app/auth/signin/page.tsx
  • app/upload-notes/page.tsx
  • app/upload-papers/page.tsx
✅ Files skipped from review due to trivial changes (1)
  • app/upload-notes/page.tsx

Comment thread app/auth/signin/page.tsx
Comment thread app/upload-papers/page.tsx Outdated
@manjeetsinghmeena
Copy link
Copy Markdown
Author

@MrImmortal09 fixed all the issues you insisted to consider
please review

@MrImmortal09
Copy link
Copy Markdown
Collaborator

@coderabbitai full-review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

🧩 Analysis chain

The PR description image shows the StudentHub login page with a toast notification in the top-right corner displaying "Redirecting - Signing in with Google..." with a close (×) button, confirming the toast system is functional.

Let me examine the actual code changes to conduct a thorough review.


🏁 Script executed:

#!/bin/bash
echo "=== context/toast-provider.tsx ==="
cat context/toast-provider.tsx

echo ""
echo "=== app/globals.css (last 20 lines) ==="
tail -20 app/globals.css

echo ""
echo "=== app/layout.jsx ==="
cat app/layout.jsx

echo ""
echo "=== app/auth/signin/page.tsx ==="
cat app/auth/signin/page.tsx

echo ""
echo "=== app/upload-notes/page.tsx ==="
cat app/upload-notes/page.tsx

echo ""
echo "=== app/upload-papers/page.tsx ==="
cat app/upload-papers/page.tsx

Length of output: 48471


@MrImmortal09 Here is the full review of PR #232.


Review: Toast Notification System (PR #232)

The PR image shows the toast system working — an "info" toast appears in the top-right corner during Google sign-in. The implementation is generally solid, but there are several bugs and gaps that need to be addressed.


🔴 Bug: File Size Limit Mismatch — app/upload-papers/page.tsx

The validation constant enforces 10 MB, but the toast message incorrectly tells the user 25 MB:

// Line ~185: maxSize is 10MB
const maxSize = 10 * 1024 * 1024 // 10MB in bytes

// Line ~188: but the toast says 25MB ← BUG
addToast('File size must be less than 25MB')

The info card at the bottom of the page also says "Maximum file size: 10MB", confirming the toast message is wrong. Pick one limit and make it consistent across the code, toast message, and UI guidelines.


🔴 Bug: All Error Toasts Display as 'info' (Blue) — Multiple Files

addToast defaults to type = 'info', so every call without an explicit type shows a blue info toast, even for errors and successes. This completely defeats the purpose of having typed toast colors.

app/auth/signin/page.tsx:

// These should be 'error' type
addToast('Only IIITL email addresses are allowed')          // ← shows as blue info
addToast('Invalid email or password')                       // ← shows as blue info
addToast(result.error)                                      // ← shows as blue info
addToast(errorMessage)                                      // ← shows as blue info
addToast(msg) // Google sign-in failure                     // ← shows as blue info

app/upload-notes/page.tsx & app/upload-papers/page.tsx:

// Validation failures — should be 'error'
addToast('Please fill in all required fields')              // ← shows as blue info
addToast('File size must be less than 25MB')               // ← shows as blue info
addToast('Only PDF, PNG, JPG, JPEG, and WEBP files...')    // ← shows as blue info

// Upload success — should be 'success'
addToast('Note uploaded successfully!')                    // ← shows as blue info
addToast('Paper uploaded successfully!')                   // ← shows as blue info

Fix by always passing the type explicitly:

// Errors
addToast('Only IIITL email addresses are allowed', undefined, 'error')
// Success  
addToast('Note uploaded successfully!', undefined, 'success')

🟡 Dead Code: Unused error, success, and session State — app/upload-papers/page.tsx

The error and success states are still declared, reset in handleSubmit, and referenced in handleFileChange, but their values are never rendered in the JSX anymore. session from useSession is also destructured but never used.

// Still present but never rendered
const [error, setError] = useState<string | null>(null)
const [success, setSuccess] = useState<string | null>(null)
const { data: session, status } = useSession() // `session` unused

// handleFileChange still references the dead state
if (error) setError(null)

Remove all three.


🟡 Deprecated API: substrsubstringcontext/toast-provider.tsx

String.prototype.substr is deprecated. Replace with substring:

// Before
const id = Math.random().toString(36).substr(2, 9)

// After
const id = Math.random().toString(36).substring(2, 11)

🟡 Accessibility: Missing aria-live Region — context/toast-provider.tsx

The ToastViewport div has no aria-live attribute, so screen readers will not announce new toast notifications. Add the appropriate ARIA attributes:

<div
  role="region"
  aria-live="polite"
  aria-label="Notifications"
  className="fixed top-0 right-0 z-50 flex flex-col gap-2 p-4 pointer-events-none max-w-md"
>

Use aria-live="assertive" for error toasts if you want to prioritize critical announcements.


🟡 Incomplete: Sign-Up Page Not Covered

Issue #215 explicitly requires toast feedback for user sign-up, but no changes were made to the sign-up page. Only the sign-in page was updated. Please add toast notifications to the sign-up flow as well.


Summary

Severity Issue File
🔴 Bug File size limit mismatch (10MB code vs 25MB message) upload-papers/page.tsx
🔴 Bug All error/success toasts display as blue 'info' signin/page.tsx, upload-notes/page.tsx, upload-papers/page.tsx
🟡 Code Quality Dead error, success, session state upload-papers/page.tsx
🟡 Code Quality Deprecated substr toast-provider.tsx
🟡 Accessibility No aria-live on toast viewport toast-provider.tsx
🟡 Missing Feature Sign-up page toast notifications not implemented
✅ Actions performed

Full review triggered.

@MrImmortal09
Copy link
Copy Markdown
Collaborator

@manjeetsinghmeena fix
Bug: File Size Limit Mismatch — app/upload-papers/page.tsx
and
Bug: All Error Toasts Display as 'info' (Blue) — Multiple Files

from above coderabbit comments.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (3)
app/globals.css (1)

81-90: ⚠️ Potential issue | 🟡 Minor

Rename this keyframe to kebab-case to satisfy Stylelint.

Line 81 still uses slideIn, which violates the configured keyframes-name-pattern rule and can fail CI.

Proposed fix
-@keyframes slideIn {
+@keyframes slide-in {
   from {
     transform: translateX(100%);
     opacity: 0;
   }
   to {
     transform: translateX(0);
     opacity: 1;
   }
 }
-        animation: 'slideIn 0.3s ease-in-out',
+        animation: 'slide-in 0.3s ease-in-out',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/globals.css` around lines 81 - 90, The `@keyframes` name slideIn violates
the keyframes-name-pattern; rename the keyframe to kebab-case (e.g., slide-in)
and update all references (animation, animation-name, or shorthand usages) that
currently reference slideIn so they point to slide-in; ensure the `@keyframes`
declaration and any CSS/JS that uses the animation name (e.g., animation:
slideIn ...) are updated consistently.
app/auth/signin/page.tsx (1)

29-30: ⚠️ Potential issue | 🟠 Major

Use explicit error variants for all sign-in failure toasts.

These failure branches still call bare addToast(...), so they default to info styling instead of error severity.

Proposed fix
-      addToast(msg)
+      addToast('Validation Error', msg, 'warning')
@@
-          addToast(errorMsg)
+          addToast('Sign-in Failed', errorMsg, 'error')
         } else {
-          addToast(result.error)
+          addToast('Sign-in Failed', result.error, 'error')
         }
@@
-      addToast(errorMessage)
+      addToast('Sign-in Failed', errorMessage, 'error')
@@
-      addToast(msg)
+      addToast('Google Sign-in Failed', msg, 'error')

Also applies to: 49-53, 65-65, 77-78

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/auth/signin/page.tsx` around lines 29 - 30, The toast calls on sign-in
failure currently call addToast(msg) which yields default/info styling; update
each failure branch in app/auth/signin/page.tsx (the addToast usages around the
'msg' variable and the other branches at the later occurrences) to supply an
explicit error variant, e.g. call addToast(msg, { variant: 'error' }) or
addToast({ message: msg, variant: 'error' }) depending on the addToast API your
codebase uses so these toasts render as error severity; change all occurrences
that currently call addToast(...) without an error variant.
app/upload-papers/page.tsx (1)

129-130: ⚠️ Potential issue | 🟠 Major

Set explicit toast severity for validation, success, and failure outcomes.

These addToast(...) calls are still untyped, so they render as default info toasts and lose severity cues.

Proposed fix
-        addToast(msg)
+        addToast('Validation Error', msg, 'warning')
@@
-        addToast(msg)
+        addToast('File Too Large', msg, 'error')
@@
-        addToast(msg)
+        addToast('Invalid File Type', msg, 'error')
@@
-      addToast(successMsg)
+      addToast('Upload Successful', successMsg, 'success')
@@
-      addToast(errorMsg)
+      addToast('Upload Failed', errorMsg, 'error')

Also applies to: 138-139, 152-153, 190-191, 212-216

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/upload-papers/page.tsx` around lines 129 - 130, The addToast calls in
page.tsx are untyped and default to info; update every addToast invocation
(e.g., the validation msg 'Please fill in all required fields' and the other
toasts used for submit success/failure) to pass an explicit severity option so
the UI shows proper levels—use severity: 'error' for validation/failure toasts
and severity: 'success' for successful outcomes when calling addToast, and
ensure the same pattern is applied to all occurrences referenced in the review
(validation, success, and error branches).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/upload-notes/page.tsx`:
- Around line 118-119: Update all addToast calls in upload-notes/page.tsx to
pass an explicit toast type instead of relying on the default 'info': for
validation failures (e.g., where const msg = 'Please fill in all required
fields' and similar messages at the mentioned ranges) call addToast(msg, { type:
'error' }); for upload failures and exceptions use addToast(errorMessage, {
type: 'error' }); and for successful uploads (the success branch around lines
~171-172) call addToast(successMsg, { type: 'success' }); locate these calls by
searching for addToast(...) in the handlers (e.g., the validate/submit
functions) and update the second argument to include the appropriate type.

In `@app/upload-papers/page.tsx`:
- Around line 136-139: The validation enforces maxSize = 10 * 1024 * 1024 but
the toast text says "25MB"; update the message shown by addToast to match the
enforced limit (e.g., change the string to "File size must be less than 10MB")
so that formData.uploaded_file.size, maxSize and the user-facing message are
consistent.

In `@context/toast-provider.tsx`:
- Around line 100-105: The toast container divs in context/toast-provider.tsx
(the JSX elements using className={`${styles.bg} border ${styles.border}
rounded-lg shadow-lg p-4 pointer-events-auto`} and the other similar divs at the
referenced ranges) lack ARIA live-region attributes; add accessible live-region
semantics by adding role="status", aria-live="polite" and aria-atomic="true" to
these toast wrapper elements so screen readers will announce success/error
messages (for high-priority errors you can use aria-live="assertive" instead);
update the JSX for the divs in the ToastProvider component accordingly.
- Around line 31-33: The id generation uses the non-standard substr call; update
the id creation in the toast creation logic (where id is set before calling
setToasts in the toast provider) to use the standard String.prototype.slice
instead of substr (i.e., change Math.random().toString(36).substr(2, 9) to use
slice to produce the same 9-character substring), keeping the surrounding logic
that calls setToasts(...) and setTimeout(() => removeToast(id), 3000) unchanged.

---

Duplicate comments:
In `@app/auth/signin/page.tsx`:
- Around line 29-30: The toast calls on sign-in failure currently call
addToast(msg) which yields default/info styling; update each failure branch in
app/auth/signin/page.tsx (the addToast usages around the 'msg' variable and the
other branches at the later occurrences) to supply an explicit error variant,
e.g. call addToast(msg, { variant: 'error' }) or addToast({ message: msg,
variant: 'error' }) depending on the addToast API your codebase uses so these
toasts render as error severity; change all occurrences that currently call
addToast(...) without an error variant.

In `@app/globals.css`:
- Around line 81-90: The `@keyframes` name slideIn violates the
keyframes-name-pattern; rename the keyframe to kebab-case (e.g., slide-in) and
update all references (animation, animation-name, or shorthand usages) that
currently reference slideIn so they point to slide-in; ensure the `@keyframes`
declaration and any CSS/JS that uses the animation name (e.g., animation:
slideIn ...) are updated consistently.

In `@app/upload-papers/page.tsx`:
- Around line 129-130: The addToast calls in page.tsx are untyped and default to
info; update every addToast invocation (e.g., the validation msg 'Please fill in
all required fields' and the other toasts used for submit success/failure) to
pass an explicit severity option so the UI shows proper levels—use severity:
'error' for validation/failure toasts and severity: 'success' for successful
outcomes when calling addToast, and ensure the same pattern is applied to all
occurrences referenced in the review (validation, success, and error branches).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e5e42a5b-5fb9-4fe5-9016-3af9243d5041

📥 Commits

Reviewing files that changed from the base of the PR and between 3d72ed1 and 2af1d0a.

📒 Files selected for processing (6)
  • app/auth/signin/page.tsx
  • app/globals.css
  • app/layout.jsx
  • app/upload-notes/page.tsx
  • app/upload-papers/page.tsx
  • context/toast-provider.tsx

Comment thread app/upload-notes/page.tsx Outdated
Comment thread app/upload-papers/page.tsx Outdated
Comment thread context/toast-provider.tsx
Comment thread context/toast-provider.tsx
@MrImmortal09
Copy link
Copy Markdown
Collaborator

@coderabbitai full-review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

🧩 Analysis chain

The PR description image shows the StudentHub login page with a toast notification in the top-right corner displaying "Redirecting - Signing in with Google..." with a close button, confirming the toast system is visually functional.

Let me examine the current state of the code to conduct a thorough review.


🏁 Script executed:

#!/bin/bash
echo "=== context/toast-provider.tsx ==="
cat context/toast-provider.tsx

echo ""
echo "=== app/upload-papers/page.tsx ==="
cat app/upload-papers/page.tsx

echo ""
echo "=== app/auth/signin/page.tsx ==="
cat app/auth/signin/page.tsx

echo ""
echo "=== app/upload-notes/page.tsx ==="
cat app/upload-notes/page.tsx

echo ""
echo "=== Sign-up page (find it first) ==="
fd -t f "page" --search-path app/auth | head -20

echo ""
echo "=== app/auth/signup directory ==="
find app/auth -name "page*" 2>/dev/null

Length of output: 47401


🏁 Script executed:

#!/bin/bash
echo "=== app/auth/signup/page.tsx ==="
cat app/auth/signup/page.tsx

Length of output: 16645


@MrImmortal09 Here is the full review of PR #232 reflecting the latest changes.


Review: Toast Notification System — Updated (PR #232)

The PR description image confirms the toast UI is working — the info toast in the top-right correctly shows "Redirecting / Signing in with Google..." with the dismiss button.


✅ Fixed from Previous Review

Issue Status
File size mismatch (10MB vs 25MB) in upload-papers ✅ Resolved — code, toast, and UI all say 10MB now
Dead error/success state in upload-papers ✅ Removed
Success/info toasts in signin/page.tsx ✅ Correctly typed ('success', 'info')

🔴 New Critical Bug: Duplicate useSession() in app/upload-notes/page.tsx

useSession() is called twice, declaring status twice in the same scope — this is a TypeScript compile error:

// Line ~9 — first call
const { status } = useSession()
const { addToast } = useToast()
// Line ~11 — second call, re-declares `status` ← COMPILE ERROR
const { data: session, status } = useSession()

Fix by merging into a single call:

const { data: session, status } = useSession()
const { addToast } = useToast()

🔴 Bug: Toast Type Argument Still Wrong in upload-notes and upload-papers

The addToast signature is:

addToast(title: string, description?: string, type?: ToastType)

But the calls in both upload pages pass the type string as the second argument (description), not the third:

// WRONG — 'error' is the description, type defaults to 'info'
addToast('Please fill in all required fields', 'error')
addToast('File size must be less than 10MB', 'error')
addToast('Note uploaded successfully!', 'success')

// CORRECT — pass undefined for description, then the type
addToast('Please fill in all required fields', undefined, 'error')
addToast('File size must be less than 10MB', undefined, 'error')
addToast('Note uploaded successfully!', undefined, 'success')

This affects all addToast calls in both app/upload-notes/page.tsx and app/upload-papers/page.tsx — they all still render as blue info toasts.


🔴 Bug: Error Toasts in app/auth/signin/page.tsx Still Default to 'info'

These five calls still have no explicit type and show as blue:

// All should be: addToast(msg, undefined, 'error')
addToast(msg)              // IIITL email validation
addToast(errorMsg)         // 'Invalid email or password'
addToast(result.error)     // other credential errors
addToast(errorMessage)     // catch block
addToast(msg)              // Google sign-in failure

🟡 Remaining from Previous Review (Unchanged)

Deprecated substrcontext/toast-provider.tsx:

// Before (deprecated)
const id = Math.random().toString(36).substr(2, 9)
// After
const id = Math.random().toString(36).substring(2, 11)

Missing aria-livecontext/toast-provider.tsx:

// ToastViewport div should be:
<div
  role="region"
  aria-live="polite"
  aria-label="Notifications"
  className="fixed top-0 right-0 z-50 flex flex-col gap-2 p-4 pointer-events-none max-w-md"
>

Sign-up page (app/auth/signup/page.tsx) — Not Updated:
The sign-up page still uses setError() and renders an inline <AlertCircle> banner. Issue #215 requires sign-up feedback via toasts too. All setError(...) calls and the error JSX block should be replaced with addToast(..., undefined, 'error').


Updated Summary

Severity Issue File Status
🔴 New Duplicate useSession() — compile error upload-notes/page.tsx ❌ Not fixed
🔴 Bug 'error'/'success' passed as description, not type upload-notes/page.tsx, upload-papers/page.tsx ❌ Not fixed
🔴 Bug Error toasts in signin show as blue 'info' signin/page.tsx ❌ Not fixed
✅ Fixed File size mismatch (10MB) upload-papers/page.tsx ✅ Fixed
✅ Fixed Dead error/success state upload-papers/page.tsx ✅ Fixed
🟡 Deprecated substr toast-provider.tsx ❌ Not fixed
🟡 No aria-live on toast viewport toast-provider.tsx ❌ Not fixed
🟡 Sign-up page not updated with toasts signup/page.tsx ❌ Not fixed
✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (3)
context/toast-provider.tsx (2)

31-31: ⚠️ Potential issue | 🟡 Minor

Replace deprecated substr here.

String.prototype.substr is legacy/deprecated. slice(2, 11) gives the same 9-character suffix without relying on Annex B behavior.

Suggested fix
-    const id = Math.random().toString(36).substr(2, 9)
+    const id = Math.random().toString(36).slice(2, 11)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@context/toast-provider.tsx` at line 31, The id generation uses the deprecated
String.prototype.substr; update the expression that assigns id (const id =
Math.random().toString(36).substr(2, 9)) to use String.prototype.slice instead
so it returns the same 9-character suffix (i.e., replace the substr call with
slice(2, 11)); ensure the variable name id and surrounding logic in the
toast-provider component (where id is generated) remains unchanged.

100-127: ⚠️ Potential issue | 🟠 Major

Expose the toast viewport as a live region.

These toasts now carry login and upload feedback, but the rendered markup still has no live-region semantics. Screen-reader users will not reliably hear new notifications, and the close button still lacks an accessible name.

Suggested fix
     <div
       style={{
         animation: 'slideIn 0.3s ease-in-out',
       }}
+      role={type === 'error' ? 'alert' : 'status'}
+      aria-live={type === 'error' ? 'assertive' : 'polite'}
+      aria-atomic="true"
       className={`${styles.bg} border ${styles.border} rounded-lg shadow-lg p-4 pointer-events-auto`}
     >
@@
         <button
           onClick={() => onRemove(id)}
           className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 flex-shrink-0"
           title="Close notification"
+          aria-label="Close notification"
         >
@@
-    <div className="fixed top-0 right-0 z-50 flex flex-col gap-2 p-4 pointer-events-none max-w-md">
+    <div
+      className="fixed top-0 right-0 z-50 flex flex-col gap-2 p-4 pointer-events-none max-w-md"
+      aria-label="Notifications"
+      aria-relevant="additions text"
+    >

Also applies to: 143-154

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@context/toast-provider.tsx` around lines 100 - 127, The toast markup needs
live-region semantics and an accessible name for the close button: update the
toast viewport/container (the element rendering the list of toasts in
toast-provider.tsx) to include aria-live="polite" (or "assertive" if immediate),
role="status" (or "log" depending on verbosity), and aria-atomic="true" so
screen readers announce new notifications (apply same change to the other
viewport instance around lines 143-154), and give the close button (the button
with onClick={() => onRemove(id)}) a programmatic accessible name via aria-label
(e.g., aria-label={`Close notification: ${title}`} or a localized equivalent) so
assistive tech can identify it; ensure these attributes are added alongside
existing className/props (refer to the container element that uses styles.bg and
the close button using onRemove and id).
app/globals.css (1)

81-90: ⚠️ Potential issue | 🟡 Minor

Rename this keyframe to kebab-case.

slideIn still violates the configured keyframes-name-pattern, so lint will keep failing until both this declaration and the animation: 'slideIn ...' reference in context/toast-provider.tsx are renamed consistently.

Suggested fix
-@keyframes slideIn {
+@keyframes slide-in {
   from {
     transform: translateX(100%);
     opacity: 0;
   }
   to {
     transform: translateX(0);
     opacity: 1;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/globals.css` around lines 81 - 90, The keyframe declaration named slideIn
violates the keyframes-name-pattern; rename the keyframe to kebab-case (e.g.,
slide-in) in the `@keyframes` block and update the corresponding animation usage
in context/toast-provider.tsx where animation: 'slideIn ...' is referenced so
both declaration (slideIn) and reference are changed consistently to the
kebab-case name (slide-in).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/layout.jsx`:
- Around line 29-34: The layout removed the shared ChatWidget from the component
tree when wrapping with ToastProvider; restore the ChatWidget JSX so it is
mounted on every page by adding the <ChatWidget /> element back into the
ToastProvider wrapper (alongside Header, {children}, Footer, Analytics) in
app/layout.jsx; keep the existing import of ChatWidget and place the element in
the same shared layout location so the widget is rendered on every page.

In `@app/quick-reads/page.tsx`:
- Around line 880-883: The icon-only close button that calls
setIsStagingOpen(false) needs an explicit accessible name—add an aria-label (for
example aria-label="Close staged changes panel") to the <button> alongside the
existing title so screen readers can identify its purpose; locate the button
using the setIsStagingOpen handler in page.tsx and add the aria-label attribute.

In `@app/upload-notes/page.tsx`:
- Around line 31-33: There's a duplicate destructuring of useSession(): remove
the first "const { status } = useSession()" and rely on the combined
destructuring "const { data: session, status } = useSession()"; ensure any code
referencing status or session uses those variables from the combined declaration
(update references if they were pointed at the removed binding), and keep the
existing "const { addToast } = useToast()" untouched.

In `@context/toast-provider.tsx`:
- Around line 17-18: The addToast signature is positional (addToast(title:
string, description?: string, type?: ToastType)) causing calls like
addToast(msg, 'error') to bind 'error' to description; change addToast to accept
a single options object (e.g., addToast({ title: string, description?: string,
type?: ToastType })) and keep removeToast unchanged; update the ToastProvider
implementation and its consumers (references to addToast in
app/upload-notes/page.tsx, app/upload-papers/page.tsx, app/auth/signin/page.tsx)
to call addToast({ title: ..., description: ..., type: 'error' | 'info' | ... })
so types are explicit and positional mistakes are eliminated.

---

Duplicate comments:
In `@app/globals.css`:
- Around line 81-90: The keyframe declaration named slideIn violates the
keyframes-name-pattern; rename the keyframe to kebab-case (e.g., slide-in) in
the `@keyframes` block and update the corresponding animation usage in
context/toast-provider.tsx where animation: 'slideIn ...' is referenced so both
declaration (slideIn) and reference are changed consistently to the kebab-case
name (slide-in).

In `@context/toast-provider.tsx`:
- Line 31: The id generation uses the deprecated String.prototype.substr; update
the expression that assigns id (const id = Math.random().toString(36).substr(2,
9)) to use String.prototype.slice instead so it returns the same 9-character
suffix (i.e., replace the substr call with slice(2, 11)); ensure the variable
name id and surrounding logic in the toast-provider component (where id is
generated) remains unchanged.
- Around line 100-127: The toast markup needs live-region semantics and an
accessible name for the close button: update the toast viewport/container (the
element rendering the list of toasts in toast-provider.tsx) to include
aria-live="polite" (or "assertive" if immediate), role="status" (or "log"
depending on verbosity), and aria-atomic="true" so screen readers announce new
notifications (apply same change to the other viewport instance around lines
143-154), and give the close button (the button with onClick={() =>
onRemove(id)}) a programmatic accessible name via aria-label (e.g.,
aria-label={`Close notification: ${title}`} or a localized equivalent) so
assistive tech can identify it; ensure these attributes are added alongside
existing className/props (refer to the container element that uses styles.bg and
the close button using onRemove and id).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6c2c360e-3109-483a-8656-eb92de43ecda

📥 Commits

Reviewing files that changed from the base of the PR and between 00e129c and 33f0511.

📒 Files selected for processing (7)
  • app/auth/signin/page.tsx
  • app/globals.css
  • app/layout.jsx
  • app/quick-reads/page.tsx
  • app/upload-notes/page.tsx
  • app/upload-papers/page.tsx
  • context/toast-provider.tsx

Comment thread app/layout.jsx
Comment thread app/quick-reads/page.tsx
Comment thread app/upload-notes/page.tsx Outdated
Comment on lines +17 to +18
addToast: (title: string, description?: string, type?: ToastType) => void
removeToast: (id: string) => void
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current misuses of the positional addToast API in the changed callers.
rg -nP "addToast\(\s*[^,]+,\s*'(?:success|error|info|warning)'\s*\)" \
  app/upload-notes/page.tsx app/upload-papers/page.tsx

rg -nP "addToast\(\s*[^,()]+\s*\)" app/auth/signin/page.tsx

Repository: iiitl/student-hub

Length of output: 798


🏁 Script executed:

cat -n context/toast-provider.tsx | head -50

Repository: iiitl/student-hub

Length of output: 1805


The addToast API parameter order causes incorrect toast types at its call sites.

With the signature (title: string, description?: string, type?: ToastType), calls like addToast(msg, 'error') compile but produce an info toast with the description literally set to "error". This misuse is already present in app/upload-notes/page.tsx and app/upload-papers/page.tsx, while bare calls in app/auth/signin/page.tsx silently default to 'info'. Switch to an options object pattern to prevent this positional binding error and update all call sites accordingly.

Suggested API shape
+interface AddToastOptions {
+  title: string
+  description?: string
+  type?: ToastType
+}
+
 interface ToastContextType {
   toasts: ToastMessage[]
-  addToast: (title: string, description?: string, type?: ToastType) => void
+  addToast: (options: AddToastOptions) => void
   removeToast: (id: string) => void
 }
@@
-  const addToast = (
-    title: string,
-    description?: string,
-    type: ToastType = 'info'
-  ) => {
+  const addToast = ({
+    title,
+    description,
+    type = 'info',
+  }: AddToastOptions) => {
     const id = Math.random().toString(36).substr(2, 9)
     setToasts((prev) => [...prev, { id, title, description, type }])
     setTimeout(() => removeToast(id), 3000)
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@context/toast-provider.tsx` around lines 17 - 18, The addToast signature is
positional (addToast(title: string, description?: string, type?: ToastType))
causing calls like addToast(msg, 'error') to bind 'error' to description; change
addToast to accept a single options object (e.g., addToast({ title: string,
description?: string, type?: ToastType })) and keep removeToast unchanged;
update the ToastProvider implementation and its consumers (references to
addToast in app/upload-notes/page.tsx, app/upload-papers/page.tsx,
app/auth/signin/page.tsx) to call addToast({ title: ..., description: ..., type:
'error' | 'info' | ... }) so types are explicit and positional mistakes are
eliminated.

manjeetsinghmeena and others added 3 commits April 12, 2026 19:49
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@MrImmortal09 MrImmortal09 left a comment

Choose a reason for hiding this comment

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

@manjeetsinghmeena fix the lint issue.

run pnpm run lint

then

pnpm run build

make sure both commands don't throw any error

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.

[feat]: Add toast notifications in the project

3 participants