Skip to content

Conversation

@omsherikar
Copy link
Collaborator

@omsherikar omsherikar commented Jan 23, 2026

Reverts #87

Summary by CodeRabbit

  • New Features

    • Added loading indicator displayed during session verification
    • Implemented automatic dashboard redirect after successful login and signup
  • Bug Fixes

    • Enhanced token validation and refresh mechanisms for more reliable authentication session management
  • Style

    • Refined dashboard interface with simplified dark theme, improved organization name display, and updated visual hierarchy

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 23, 2026 19:25
@vercel
Copy link

vercel bot commented Jan 23, 2026

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

Project Deployment Review Updated (UTC)
refactron Ready Ready Preview, Comment Jan 23, 2026 7:25pm

@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

This PR enhances the authentication system by refactoring token verification and refresh logic in the useAuth hook, adding loading state handling across auth components, implementing authentication-aware redirects in login/signup forms, and refining Dashboard styling with organization name formatting and simplified visual elements.

Changes

Cohort / File(s) Summary
Backend Submodule Update
backend
Submodule pointer updated from commit 6a4ff2f to 059ee5f; no code or behavior changes.
Auth Hook & Loading State
src/hooks/useAuth.tsx, src/components/AuthApp.tsx
useAuth now validates existing tokens via /api/auth/me, refreshes invalid tokens via /api/auth/refresh, and retries with improved error handling. AuthApp conditionally renders LoadingSpinner during session verification.
Auth Forms & Redirects
src/components/LoginForm.tsx, src/components/SignupForm.tsx
Both forms now integrate useAuth hook, add loading guards, implement authentication-aware redirects to /dashboard when authenticated, and replace OAuth spinner SVG with "Connecting..." text.
Dashboard UI & Styling
src/components/Dashboard.tsx
Introduces formatOrgName() helper to normalize organization names with fallback to "User's Organization". Removes Building2 icons from organization dropdown, updates main background from black to #0a0a0a, simplifies decorative glow elements, and refines button styling.

Sequence Diagrams

sequenceDiagram
    participant User
    participant AuthApp as AuthApp<br/>(Session Check)
    participant useAuth as useAuth Hook
    participant AuthAPI as Backend API
    participant Dashboard

    User->>AuthApp: Mount AuthApp
    AuthApp->>useAuth: Call useAuth()
    useAuth->>useAuth: Check localStorage<br/>for token
    
    alt Token exists
        useAuth->>AuthAPI: GET /api/auth/me<br/>(Validate token)
        alt Token Valid
            AuthAPI-->>useAuth: Return user data
            useAuth->>useAuth: setUser(data)<br/>setIsLoading(false)
        else Token Invalid (non-401)
            AuthAPI-->>useAuth: Error response
            useAuth->>useAuth: setIsLoading(false)
        else Token Expired (401)
            AuthAPI-->>useAuth: 401 Unauthorized
            useAuth->>AuthAPI: POST /api/auth/refresh
            AuthAPI-->>useAuth: Return new accessToken
            useAuth->>useAuth: Save new token
            useAuth->>AuthAPI: GET /api/auth/me<br/>(Retry)
            AuthAPI-->>useAuth: Return user data
            useAuth->>useAuth: setUser(data)<br/>setIsLoading(false)
        end
    else No Token
        useAuth->>AuthAPI: POST /api/auth/refresh
        alt Refresh Succeeds
            AuthAPI-->>useAuth: New accessToken
            useAuth->>useAuth: Save token, retry /api/auth/me
        else Refresh Fails
            AuthAPI-->>useAuth: Error
            useAuth->>useAuth: setIsLoading(false)
        end
    end
    
    AuthApp->>AuthApp: isLoading?<br/>Render LoadingSpinner : Routes
    useAuth-->>Dashboard: Provide user state
    Dashboard->>Dashboard: Render with user data
Loading
sequenceDiagram
    participant User
    participant LoginForm as LoginForm/<br/>SignupForm
    participant useAuth as useAuth Hook
    participant Dashboard

    User->>LoginForm: Navigate to /login
    LoginForm->>useAuth: Call useAuth()
    useAuth-->>LoginForm: Return isAuthenticated,<br/>loading
    
    alt isLoading === true
        LoginForm->>LoginForm: Render nothing<br/>(Early return)
    else isLoading === false
        alt isAuthenticated === true
            LoginForm->>LoginForm: Navigate to /dashboard<br/>(replace: true)
            LoginForm->>Dashboard: Redirect complete
        else isAuthenticated === false
            LoginForm->>LoginForm: Render login form
            User->>LoginForm: Enter credentials/<br/>Click OAuth button
            LoginForm->>useAuth: Call login() or oauth()
            useAuth-->>LoginForm: Update loading state
            LoginForm->>LoginForm: Show "Connecting..."<br/>text
        end
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Suggested Labels

type:refactor, type:feature

Poem

🐰 Token tales, a rabbit's delight,
Verification loops, refresh in flight,
Loading states spin, then dash away,
Auth flows true, come what may!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the PR's main action—a revert of a previous revert—restoring the original feature work on auth persistence, flash fix, and dashboard UI refinements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

@github-actions
Copy link

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions bot added type:refactor Code refactoring type:feature New feature labels Jan 23, 2026
Copy link
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

This PR reverts a previous revert, effectively re-introducing authentication persistence improvements, UI refinements, and fixes for authentication flash issues in the dashboard.

Changes:

  • Enhanced auth token verification and refresh logic to prevent unnecessary token clearing
  • Added authentication checks to redirect already-logged-in users away from login/signup pages
  • Refined Dashboard UI by removing visual effects and improving organization name display

Reviewed changes

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

Show a summary per file
File Description
src/hooks/useAuth.tsx Restructured token verification flow to check token validity before attempting refresh, preventing premature token clearing
src/components/SignupForm.tsx Added redirect logic for authenticated users and removed spinner SVG from Google OAuth button
src/components/LoginForm.tsx Added redirect logic for authenticated users, moved useAuth hook declaration, and removed spinner SVG from Google OAuth button
src/components/Dashboard.tsx Added organization name formatting function, removed unused Building2 icon, and simplified UI styling by removing glow effects
src/components/AuthApp.tsx Added loading state handling with LoadingSpinner component during session verification
backend Updated backend subproject commit reference

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

Comment on lines +44 to +46
const apiBaseUrl =
process.env.REACT_APP_API_BASE_URL || 'http://localhost:3001';
const token = localStorage.getItem('accessToken');
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The apiBaseUrl is defined at the start of the function but could be extracted to a constant at the module level or a configuration file to avoid repeated instantiation on every auth check and improve maintainability.

Copilot uses AI. Check for mistakes.

const formatOrgName = (name: string | null | undefined) => {
if (!name) return "User's Organization";
const capitalized = name.charAt(0).toUpperCase() + name.slice(1);
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The formatOrgName function assumes the organization name should always have "'s Organization" appended. However, if the name already contains possessive forms or is a full organization name (e.g., "Acme Corporation"), this will result in awkward formatting like "Acme corporation's Organization". Consider whether the organization name should be displayed as-is or clarify the expected input format.

Suggested change
const capitalized = name.charAt(0).toUpperCase() + name.slice(1);
const trimmed = name.trim();
if (!trimmed) return "User's Organization";
const lower = trimmed.toLowerCase();
const hasPossessive = /'s\b/.test(lower);
const hasOrgKeyword = /(inc|corp|corporation|llc|ltd|company|co\.)\b/.test(lower);
const isMultiWord = trimmed.includes(' ');
const capitalized =
trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
// If it already looks like an organization name or has a possessive, use as-is.
if (hasPossessive || hasOrgKeyword || isMultiWord) {
return capitalized;
}
// Otherwise, treat it as a personal name and append "'s Organization".

Copilot uses AI. Check for mistakes.
</svg>
<span>Connecting...</span>
</>
<span>Connecting...</span>
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

Removing the loading spinner SVG eliminates visual feedback during the OAuth connection process. Users may not understand that an action is in progress. Consider retaining a visual loading indicator for better user experience.

Suggested change
<span>Connecting...</span>
<span className="flex items-center gap-2">
<svg
className="animate-spin h-4 w-4 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
></path>
</svg>
<span>Connecting...</span>
</span>

Copilot uses AI. Check for mistakes.
</svg>
<span>Connecting...</span>
</>
<span>Connecting...</span>
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

Removing the loading spinner SVG eliminates visual feedback during the OAuth connection process. Users may not understand that an action is in progress. Consider retaining a visual loading indicator for better user experience.

Suggested change
<span>Connecting...</span>
<span className="flex items-center gap-2">
<svg
className="h-4 w-4 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
></path>
</svg>
<span>Connecting...</span>
</span>

Copilot uses AI. Check for mistakes.
Copy link

@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

🤖 Fix all issues with AI agents
In `@backend`:
- Line 1: The repo currently tracks "backend" as a gitlink submodule without a
.gitmodules entry, producing a malformed state; either remove the submodule
tracking by replacing the gitlink with real files (remove the gitlink via git rm
--cached backend, commit the actual backend directory contents, and add them as
normal tracked files) or properly configure it as a submodule (add a .gitmodules
entry for "backend" with the correct URL and path, ensure the referenced commit
exists in the remote, then run git submodule sync/update to fetch and commit the
submodule configuration); update CI/README if needed to document the chosen
approach.
🧹 Nitpick comments (2)
src/hooks/useAuth.tsx (1)

120-143: Race condition between setTimeout and background logout.

The logout clears local state after 800ms via setTimeout, but the backend logout runs concurrently. If the backend call completes quickly and the component unmounts or user navigates away, there's no cleanup of the timeout. This could cause state updates on unmounted components.

Consider returning a cleanup function or using useRef to track mounted state, though in practice React 18's automatic batching mitigates most issues here.

src/components/Dashboard.tsx (1)

62-68: Consider handling edge cases in formatOrgName.

The function capitalizes the first character and appends 's Organization. A few considerations:

  1. Names already capitalized work fine, but names starting with numbers or special characters may produce odd results (e.g., "123corp""123corp's Organization")
  2. Names ending in 's' will produce grammatically awkward output (e.g., "James""James's Organization" instead of "James' Organization")

If organization names can have varied formats, consider more robust handling.

♻️ Optional: Handle possessive edge case
 const formatOrgName = (name: string | null | undefined) => {
   if (!name) return "User's Organization";
   const capitalized = name.charAt(0).toUpperCase() + name.slice(1);
-  return `${capitalized}'s Organization`;
+  const possessive = capitalized.endsWith('s') ? "'" : "'s";
+  return `${capitalized}${possessive} Organization`;
 };

@@ -1 +1 @@
Subproject commit 6a4ff2f50a39ca9f9475c235c6cc01e9a16b485b
Subproject commit 059ee5f2b31ebe76ef171f3708e8a16b822a4f30
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the submodule update and show its commit summary
git submodule status
git -C backend log -1 --oneline
git -C backend show --stat 059ee5f2b31ebe76ef171f3708e8a16b822a4f30

Repository: Refactron-ai/Refactron_Website

Length of output: 422


🏁 Script executed:

#!/bin/bash
# Check .gitmodules content
if [ -f .gitmodules ]; then
  echo "=== .gitmodules content ==="
  cat .gitmodules
else
  echo ".gitmodules not found"
fi

# Check git ls-files status for backend
echo -e "\n=== Git status for backend ==="
git ls-files -s -- backend

# Check all files at root
echo -e "\n=== Root files ==="
git ls-files --stage | head -20

Repository: Refactron-ai/Refactron_Website

Length of output: 1748


Remove or properly configure the backend submodule.

The backend file is tracked as a submodule (git mode 160000) but there is no .gitmodules file to configure it. This creates a malformed repository state. Either remove the gitlink tracking for backend and commit it as regular files, or add a proper .gitmodules configuration with the submodule definition and ensure the referenced commit hash exists in the remote repository.

🤖 Prompt for AI Agents
In `@backend` at line 1, The repo currently tracks "backend" as a gitlink
submodule without a .gitmodules entry, producing a malformed state; either
remove the submodule tracking by replacing the gitlink with real files (remove
the gitlink via git rm --cached backend, commit the actual backend directory
contents, and add them as normal tracked files) or properly configure it as a
submodule (add a .gitmodules entry for "backend" with the correct URL and path,
ensure the referenced commit exists in the remote, then run git submodule
sync/update to fetch and commit the submodule configuration); update CI/README
if needed to document the chosen approach.

@omsherikar omsherikar merged commit 70e71f1 into main Jan 23, 2026
19 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature New feature type:refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants