Skip to content

Conversation

@Gupta-02
Copy link

@Gupta-02 Gupta-02 commented Sep 2, 2025

Enhnaced the site with more visibility and clear chanages

Summary by CodeRabbit

  • New Features

    • Added Resume Review, Mock Interview, and Community Q&A pages (protected).
    • User data provider with bookmarking, personalized widgets, leaderboard, badges, and streak displays.
  • Improvements

    • Tag-based filtering across Interview and Resources.
    • Simplified score trend chart and persistent widget state.
    • Schedule and join mock interviews; post community questions.
  • Accessibility

    • “Skip to main content” link and improved roles/labels for navigation, footer, charts, and menus.
  • Internationalization

    • App-wide translations with a language switcher (English/Hindi).

@vercel
Copy link

vercel bot commented Sep 2, 2025

@Gupta-02 is attempting to deploy a commit to the coderuzumaki's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Sep 2, 2025

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between adc65d3 and 85db7be.

📒 Files selected for processing (17)
  • client/src/components/Badges.jsx (1 hunks)
  • client/src/components/BookmarkButton.jsx (1 hunks)
  • client/src/components/Leaderboard.jsx (1 hunks)
  • client/src/components/StreakCounter.jsx (1 hunks)
  • client/src/components/TagFilter.jsx (1 hunks)
  • client/src/context/UserDataContext.jsx (1 hunks)
  • client/src/i18n.js (1 hunks)
  • client/src/locales/en.json (1 hunks)
  • client/src/locales/hi.json (1 hunks)
  • client/src/pages/CommunityQA.jsx (1 hunks)
  • client/src/pages/MockInterview.jsx (1 hunks)
  • client/src/pages/ResumeReview.jsx (1 hunks)
  • server/middleware/authRequired.js (1 hunks)
  • server/models/CommunityQuestionModel.js (1 hunks)
  • server/models/MockInterviewModel.js (1 hunks)
  • server/routes/communityQARoutes.js (1 hunks)
  • server/routes/mockInterviewRoutes.js (1 hunks)
 __________________________________
< Bazinga! You missed a semicolon. >
 ----------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ

Walkthrough

Introduces accessibility and i18n updates, adds user data context, expands dashboard with new widgets and data fetches, implements tag filtering and bookmarking in Interview and Resources, adds new protected routes/pages, updates server with new APIs, and extends User and Interview schemas. Minor chart and structural adjustments included.

Changes

Cohort / File(s) Summary
Accessibility enhancements
client/src/App.jsx, client/src/components/Footer.jsx
Adds skip link and main landmark; assigns role="contentinfo" and aria-label to footer; minor focus styling.
Header i18n and a11y
client/src/components/Header.jsx
Integrates react-i18next labels, adds language switcher, expands nav items (resources, mock-interview, community-qa, resume-review), and improves ARIA on header, menus, and controls.
Chart semantics cleanup
client/src/components/ScoreTrendChart.jsx
Uses semantic section with aria-labelledby; removes period toggle and score UI; adds accessible chart container; minor tooltip tweak.
Providers and i18n bootstrapping
client/src/main.jsx, client/src/App.jsx, client/src/components/Header.jsx, client/src/pages/Dashboard.jsx
Imports i18n side-effect; wraps RouterProvider with new UserDataProvider inside AuthProvider; components adopt t(...) for texts.
Dashboard expansion
client/src/pages/Dashboard.jsx
Adds gamification widgets (Badges, StreakCounter), leaderboard fetch, personalized widgets (mock interviews, activity, recommended resources), persistent local state, and i18n strings; retains charts and interview list.
Interview tag filtering and bookmarks
client/src/pages/Interview.jsx
Introduces TagFilter and BookmarkButton; filters questions by selected tags across difficulty/topics/company; integrates user bookmarks via UserDataContext; preserves submission and recording flows.
Resources filtering and bookmarks
client/src/pages/Resources.jsx
Adds TagFilter-based resource filtering and bookmarking tied to UserDataContext; renders filtered grid with bookmark overlays; keeps Featured section.
Routing additions (client and server)
client/src/routes.jsx, server/index.js
Adds protected routes for resume-review, mock-interview, community-qa; mounts new Express routes at /api/mock-interview and /api/community-qa.
Schema extensions
server/models/UserModel.js, server/models/InterviewModel.js
User: adds badges, streak, leaderboardPoints, bookmarks. Interview: enriches questions with difficulty, topics, company_tags, bookmarkedBy.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant D as Dashboard.jsx
  participant API as Server API
  participant C as UserDataContext

  U->>D: Navigate to Dashboard
  activate D
  D->>API: GET /api/interview
  D->>API: GET /api/report
  D->>API: GET /api/user/leaderboard?limit=5
  D->>API: GET /api/mock-interview?upcoming=1
  D->>API: GET /api/user/activity
  D->>API: GET /api/resources/recommended
  API-->>D: Interviews, Reports, Leaderboard, Widgets
  D->>C: Read userData (badges, streak)
  D-->>U: Render charts, summary, widgets, leaderboard
  deactivate D
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant I as Interview.jsx
  participant C as UserDataContext

  U->>I: Open Interview
  I->>I: Build tag set from questions (difficulty/topics/company)
  U->>I: Select/clear tags
  I->>I: Filter questions by selected tags
  I-->>U: Show filtered question {n} of {N}

  U->>I: Toggle bookmark
  I->>C: Update userData.bookmarks (local)
  Note right of I: Optional backend call placeholder
  I-->>U: Bookmark state updated
Loading
sequenceDiagram
  actor U as User
  participant H as Header.jsx
  participant R as Router
  participant P as Providers

  U->>H: Click new nav item (e.g., Mock Interview)
  H->>R: Navigate /mock-interview
  R->>P: ProtectedRoute check (AuthProvider)
  P-->>R: Authorized
  R-->>U: Render target page
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Poem

I thump my paws—new routes appear,
Tags bloom like clover, crisp and clear.
Charts now whisper, headings sing,
Bookmarks nest where users bring.
Badges gleam, the streaks take flight—
I hop through dashboards, day to night.
Carrot-commits? Ship it right! 🥕✨

Tip

Migrating from UI to YAML configuration.

Use the @coderabbitai configuration command in a PR comment to get a dump of all your UI settings in YAML format. You can then edit this YAML file and upload it to the root of your repository to configure CodeRabbit programmatically.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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: 12

Caution

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

⚠️ Outside diff range comments (3)
client/src/pages/Dashboard.jsx (1)

1-183: Critical: Fix malformed React component structure.

The Dashboard component definition is missing. The file has hooks and JSX return statement floating outside of a function component, which is invalid React code.

The component should be wrapped in a proper function declaration:

+export default function Dashboard() {
   const [interviews, setInterviews] = useState([]);
   const [summaryData, setSummaryData] = useState([]);
   const [chartData, setChartData] = useState([]);
   const [leaderboard, setLeaderboard] = useState([]);
   const { user } = useAuth();
   const { userData } = useUserData();
   // ... rest of the state declarations ...

   useEffect(() => {
      // ... existing useEffect code ...
   }, [user]);

   // ... other useEffect ...

   const { t } = useTranslation();
   
   return (
      <div className="min-h-screen bg-gray-50">
         {/* ... existing JSX ... */}
      </div>
   );
+}
client/src/pages/Interview.jsx (2)

1-331: Critical: Fix missing component wrapper.

Similar to the Dashboard component, this file is missing the function component declaration wrapper. The hooks and JSX are floating without a proper component definition.

Add the component wrapper:

+import { useState, useEffect } from "react";
+import { useParams, useNavigate } from "react-router-dom";
+import axios from "axios";
+import LoadingScreen from "../components/LoadingScreen";
+import Toast from "../components/Toast";
 import TagFilter from "../components/TagFilter";
 import BookmarkButton from "../components/BookmarkButton";
 import { useUserData } from "../context/UserDataContext";
 import { FaMicrophone, FaArrowRight } from "react-icons/fa";
+import { useAuth } from "../context/AuthContext";

 const SpeechRecognition =
    window.SpeechRecognition || window.webkitSpeechRecognition;
 const recognition = SpeechRecognition ? new SpeechRecognition() : null;

+export default function Interview() {
    const { interviewId } = useParams();
    // ... rest of the state and hooks ...
    
    // ... all the functions and effects ...
    
    return (
       <div className="min-h-screen bg-gray-50">
          {/* ... existing JSX ... */}
       </div>
    );
+}

155-163: Navigation logic doesn't account for filtered questions.

The navigation to the next question should consider the filtered questions array, not the original questions array.

-if (currentQuestionIndex < questions.length - 1) {
-   const nextIndex = currentQuestionIndex + 1;
-   setCurrentQuestionIndex(nextIndex);
+if (currentFilteredIndex < filteredQuestions.length - 1) {
+   const nextFilteredIndex = currentFilteredIndex + 1;
+   const nextQuestionIndex = filteredIndexes[nextFilteredIndex];
+   setCurrentQuestionIndex(nextQuestionIndex);
    setAnswer("");
-   speakQuestion(questions[nextIndex].question);
+   speakQuestion(questions[nextQuestionIndex].question);
} else {
    showToast("Interview Completed!", "success");
    navigate(`/interview/report/${interviewId}`);
}
🧹 Nitpick comments (17)
client/src/components/Footer.jsx (1)

7-7: Redundant landmark attributes on semantic footer

The native

element already exposes a contentinfo landmark. role="contentinfo" and aria-label="Footer" are unnecessary and may create duplicate landmarks for AT.

-    <footer className="bg-[#fafaf9] text-gray-900 border-t border-gray-100" role="contentinfo" aria-label="Footer">
+    <footer className="bg-[#fafaf9] text-gray-900 border-t border-gray-100">
server/models/UserModel.js (2)

32-39: Clamp counters to non-negative values

streak and leaderboardPoints should not go negative; add min: 0 (and index leaderboardPoints for leaderboard queries).

     streak: {
         type: Number,
-        default: 0,
+        default: 0,
+        min: 0,
     },
     leaderboardPoints: {
-        type: Number,
-        default: 0,
+        type: Number,
+        default: 0,
+        min: 0,
+        index: true,
     },

41-45: Bookmark ID consistency

bookmarks is [String] but elsewhere you use User._id (ObjectId) for ownership (see interview creation). Please confirm what IDs you store here (ObjectId vs external IDs). If these will reference Mongo docs, prefer ObjectId with { type: Schema.Types.ObjectId, ref: "" } or a discriminated shape like { kind, refId }.

client/src/components/ScoreTrendChart.jsx (3)

28-30: Default prop to avoid crashes when data is undefined

Prevents Recharts from choking on undefined.

-export default function ScoreTrendChart({
-   chartData
-}) {
+export default function ScoreTrendChart({ chartData = [] }) {

53-53: Avoid re-instantiating tooltip component each render

Pass the component reference instead of an element.

-                       <Tooltip content={<CustomTooltip />} wrapperStyle={{ outline: 'none' }} />
+                       <Tooltip content={CustomTooltip} wrapperStyle={{ outline: 'none' }} />

34-41: Improve chart accessibility with a programmatic description

Add a visually hidden description and associate via aria-describedby to give screen readers context.

            <div className="mb-6">
                <h3 id="score-trend-heading" className="text-lg font-semibold text-gray-900 mb-4">
                    Score Trend
                </h3>
+               <p id="score-trend-desc" className="sr-only">
+                   Line chart of interview scores over time (0–100). Use tooltip to hear date and score.
+               </p>
            </div>

-           <div className="h-64" role="img" aria-label="Line chart showing interview score trends over time">
+           <div className="h-64" role="img" aria-label="Line chart showing interview score trends over time" aria-describedby="score-trend-desc">
server/models/InterviewModel.js (2)

78-84: Normalize tag casing to reduce duplicates

Store topics/company_tags in lowercase and trimmed.

-                topics:
-                {
-                    type: [String],
-                    default: [],
-                },
-                company_tags: {
-                    type: [String],
-                    default: [],
-                },
+                topics: [
+                    { type: String, lowercase: true, trim: true }
+                ],
+                company_tags: [
+                    { type: String, lowercase: true, trim: true }
+                ],

86-88: Use ObjectId refs for bookmarked users (align with User model)

If you store Mongo user IDs, use ObjectId refs to enable lookups/joins and enforce type consistency.

-                bookmarkedBy: {
-                    type: [String], // user IDs who bookmarked
-                    default: [],
-                },
+                bookmarkedBy: [
+                    { type: mongoose.Schema.Types.ObjectId, ref: "User" }
+                ],

If you actually store Firebase UIDs, keep [String] but document it and mirror that in UserModel.bookmarks for consistency.

client/src/components/Header.jsx (2)

63-63: Consider providing English fallbacks for all translation keys.

While t('welcome', 'Home') correctly provides a fallback value, other translation calls like t('dashboard'), t('mockInterview'), etc., don't have fallback values. This could result in displaying translation keys instead of readable text if translations are missing.

Apply this pattern to all translation calls:

-      <Link to="/dashboard" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('dashboard')}</Link>
+      <Link to="/dashboard" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('dashboard', 'Dashboard')}</Link>
-        <Link to="/mock-interview" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('mockInterview')}</Link>
+        <Link to="/mock-interview" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('mockInterview', 'Mock Interview')}</Link>
-        <Link to="/community-qa" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('communityQA')}</Link>
+        <Link to="/community-qa" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('communityQA', 'Community Q&A')}</Link>
-        <Link to="/resume-review" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('resumeReview')}</Link>
+        <Link to="/resume-review" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('resumeReview', 'Resume Review')}</Link>
-        <Link to="/resources" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('resources')}</Link>
+        <Link to="/resources" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('resources', 'Resources')}</Link>
-                  <Link to="/login" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('login')}</Link>
+                  <Link to="/login" className="px-4 py-2 rounded transition-all duration-200 text-gray-700 hover:text-cyan-500 hover:bg-white/40 hover:scale-105">{t('login', 'Login')}</Link>
-                  <Link to="/signup" className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-md font-medium transition-colors">{t('signup')}</Link>
+                  <Link to="/signup" className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-md font-medium transition-colors">{t('signup', 'Sign Up')}</Link>

Also applies to: 69-69, 71-80, 122-123


114-119: Consider extracting language toggle logic to a reusable component.

The language toggle button code is duplicated between desktop and mobile views. Consider creating a reusable component to maintain DRY principles.

Create a separate component:

const LanguageToggle = ({ i18n }) => (
  <button
    onClick={() => i18n.changeLanguage(i18n.language === 'en' ? 'hi' : 'en')}
    className="px-3 py-1 rounded bg-gray-200 text-gray-700 hover:bg-gray-300"
    aria-label="Switch language"
  >
    {i18n.language === 'en' ? 'हिंदी' : 'EN'}
  </button>
);

Then use it in both places:

// Desktop view
<LanguageToggle i18n={i18n} />

// Mobile view
<LanguageToggle i18n={i18n} />

Also applies to: 172-177

client/src/pages/Interview.jsx (2)

205-205: Avoid creating new arrays on every render for tag generation.

The tags array is recreated on every render using complex operations. Consider memoizing this computation.

+import { useMemo } from "react";

+const allTags = useMemo(() => 
+   Array.from(new Set(
+      questions.flatMap(q => [
+         q.difficulty, 
+         ...(q.topics || []), 
+         ...(q.company_tags || [])
+      ]).filter(Boolean)
+   )),
+   [questions]
+);

 <TagFilter
-   tags={Array.from(new Set(questions.flatMap(q => [q.difficulty, ...(q.topics || []), ...(q.company_tags || [])]).filter(Boolean)))}
+   tags={allTags}
    selected={selectedTags}
    onChange={(tag) =>
       setSelectedTags((prev) =>
          prev.includes(tag)
             ? prev.filter((t) => t !== tag)
             : [...prev, tag]
       )
    }
 />

67-67: Consolidate tag filtering into a single includes check
The q.difficulty === tag comparison is valid—difficulty is stored as a string enum ("easy" | "medium" | "hard"). To simplify and improve readability, merge topics, company_tags, and difficulty into one array and call includes once:

const questionTags = [
  ...(q.topics || []),
  ...(q.company_tags || []),
  q.difficulty,
];
return questionTags.includes(tag);

This replaces three separate checks with a single, clear operation.

client/src/App.jsx (1)

24-31: Skip link: nice addition; trim extras.

<a> is focusable by default; tabIndex={0} is unnecessary. Everything else is solid.

-      <a
+      <a
         href="#main-content"
         className="sr-only focus:not-sr-only absolute left-2 top-2 z-50 bg-blue-700 text-white px-4 py-2 rounded focus:outline-none focus:ring-2 focus:ring-blue-400"
-        tabIndex={0}
       >
         Skip to main content
       </a>
client/src/pages/Resources.jsx (4)

5-9: Import useMemo for derived data to avoid recomputation.

You compute derived collections below; memoize them to prevent rework on each render.

-import { useUserData } from "../context/UserDataContext";
-import { useState } from "react";
+import { useUserData } from "../context/UserDataContext";
+import { useState, useMemo } from "react";

14-16: Memoize allTags.

This list is static given imported resources; memoize to avoid rebuilding the Set on every render.

-   const allTags = Array.from(new Set(resources.flatMap(r => [r.category, ...(r.topics || [])]).filter(Boolean)));
+   const allTags = useMemo(
+     () => Array.from(new Set(resources.flatMap(r => [r.category, ...(r.topics || [])]).filter(Boolean))),
+     [] // resources is a static import
+   );

18-21: Memoize filteredResources.

Prevents re-filtering when unrelated state changes.

-   const filteredResources = selectedTags.length
-	   ? resources.filter(r => selectedTags.every(tag => (r.topics || []).includes(tag) || r.category === tag))
-	   : resources;
+   const filteredResources = useMemo(() => {
+     return selectedTags.length
+       ? resources.filter(r =>
+           selectedTags.every(tag => (r.topics || []).includes(tag) || r.category === tag)
+         )
+       : resources;
+   }, [selectedTags]);

22-29: Make the bookmark updater resilient; consider persistence.

Guard against prev being falsy and normalize bookmarks. Optionally persist to API with optimistic update.

-   const handleBookmark = (id) => {
-	   setUserData((prev) => ({
-		   ...prev,
-		   bookmarks: prev.bookmarks?.includes(id)
-			   ? prev.bookmarks.filter((bid) => bid !== id)
-			   : [...(prev.bookmarks || []), id],
-	   }));
-   };
+   const handleBookmark = (id) => {
+     setUserData((prev) => {
+       const base = prev || {};
+       const list = Array.isArray(base.bookmarks) ? base.bookmarks : [];
+       const has = list.includes(id);
+       return { ...base, bookmarks: has ? list.filter(b => b !== id) : [...list, id] };
+     });
+     // Optional: optimistic persist here (try/catch + rollback on failure)
+   };

Is there an API endpoint wired for bookmarks? If yes, I can add an optimistic call with error handling.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7ce03a2 and adc65d3.

📒 Files selected for processing (12)
  • client/src/App.jsx (1 hunks)
  • client/src/components/Footer.jsx (1 hunks)
  • client/src/components/Header.jsx (5 hunks)
  • client/src/components/ScoreTrendChart.jsx (1 hunks)
  • client/src/main.jsx (1 hunks)
  • client/src/pages/Dashboard.jsx (1 hunks)
  • client/src/pages/Interview.jsx (4 hunks)
  • client/src/pages/Resources.jsx (2 hunks)
  • client/src/routes.jsx (2 hunks)
  • server/index.js (1 hunks)
  • server/models/InterviewModel.js (1 hunks)
  • server/models/UserModel.js (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
client/src/App.jsx (3)
client/src/components/ScrollToTop.jsx (1)
  • ScrollToTop (4-15)
client/src/pages/About.jsx (1)
  • About (19-286)
client/src/pages/Home.jsx (1)
  • Home (7-236)
client/src/main.jsx (1)
client/src/context/AuthContext.jsx (3)
  • AuthProvider (9-45)
  • AuthProvider (9-45)
  • useContext (7-7)
client/src/routes.jsx (1)
client/src/components/ProtectedRoute.jsx (1)
  • ProtectedRoute (5-8)
client/src/pages/Resources.jsx (4)
client/src/pages/Dashboard.jsx (1)
  • useUserData (19-19)
client/src/pages/Interview.jsx (2)
  • useUserData (25-25)
  • selectedTags (22-22)
client/src/data/resourcesData.js (1)
  • resources (1-100)
client/src/components/ResourceCard.jsx (1)
  • ResourceCard (22-88)
client/src/components/ScoreTrendChart.jsx (1)
client/src/pages/Dashboard.jsx (1)
  • chartData (16-16)
client/src/components/Header.jsx (2)
client/src/pages/Dashboard.jsx (1)
  • useTranslation (105-105)
client/src/context/AuthContext.jsx (2)
  • isLoggedIn (11-11)
  • user (10-10)
client/src/pages/Interview.jsx (4)
client/src/pages/Resources.jsx (2)
  • selectedTags (12-12)
  • useUserData (11-11)
client/src/context/AuthContext.jsx (3)
  • useAuth (7-7)
  • useAuth (7-7)
  • loading (12-12)
client/src/components/LoadingScreen.jsx (1)
  • LoadingScreen (1-32)
client/src/components/Toast.jsx (1)
  • Toast (6-55)
server/models/InterviewModel.js (2)
server/routes/interviewRoutes.js (2)
  • req (149-221)
  • req (29-141)
server/services/aiService.js (1)
  • prompt (44-161)
client/src/pages/Dashboard.jsx (7)
server/routes/interviewRoutes.js (4)
  • interviews (231-231)
  • user (48-48)
  • user (228-230)
  • report (165-165)
client/src/components/Header.jsx (2)
  • useAuth (10-10)
  • useTranslation (9-9)
client/src/pages/Interview.jsx (3)
  • useAuth (24-24)
  • useUserData (25-25)
  • token (228-228)
client/src/context/AuthContext.jsx (3)
  • useAuth (7-7)
  • useAuth (7-7)
  • user (10-10)
client/src/pages/Resources.jsx (1)
  • useUserData (11-11)
server/routes/reportRoutes.js (2)
  • user (26-26)
  • report (14-14)
client/src/components/InterviewList.jsx (1)
  • InterviewList (29-107)
🪛 Biome (2.1.2)
client/src/pages/Interview.jsx

[error] 11-11: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 12-12: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 13-13: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 14-14: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 15-15: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 16-16: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 17-17: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 22-22: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 23-23: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 24-24: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 25-25: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 26-26: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 41-41: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 59-59: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 178-178: Illegal return statement outside of a function

(parse)

client/src/pages/Dashboard.jsx

[error] 106-182: Illegal return statement outside of a function

(parse)


[error] 14-14: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 15-15: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 16-16: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 17-17: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 18-18: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 19-19: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 21-21: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 22-22: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 23-23: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 25-25: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 89-89: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)


[error] 105-105: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

🔇 Additional comments (5)
client/src/components/Header.jsx (2)

2-2: LGTM! Good implementation of i18n support.

The integration of React i18n using useTranslation hook is properly implemented following React best practices.

Also applies to: 9-9


86-86: Excellent accessibility improvements!

The accessibility enhancements are comprehensive and follow WCAG guidelines:

  • Proper ARIA labels and roles for navigation and menus
  • Correct usage of aria-expanded and aria-controls for interactive elements
  • Semantic role attributes for menu items

These changes significantly improve screen reader support and keyboard navigation.

Also applies to: 96-96, 104-106, 130-133, 146-146, 153-153, 157-157, 170-170, 181-182, 186-187

client/src/routes.jsx (1)

16-18: Imports for new pages look good.

No issues spotted with the new page imports.

client/src/main.jsx (1)

6-14: Provider composition LGTM.

Order (AuthProvider > UserDataProvider > RouterProvider) is correct, and i18n init is set up before render.

client/src/pages/Resources.jsx (1)

192-225: All-resources section and controls look good.

Clean layout; conditional bookmark control only when userData is present is sensible.

Comment on lines +34 to 36
<main id="main-content" className="flex-grow focus:outline-none">
<Outlet /> {/* This will render the current page */}
</main>
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Avoid nested

landmarks across pages.

Some pages (e.g., Home.jsx) already render a top-level <main>. Wrapping the <Outlet /> with <main> here risks multiple mains per document, which is an a11y violation. Prefer a single main landmark.

Option A (preferred): Replace page-level outer <main> with <div> on pages that render under App’s <main>.

Option B (stopgap within this file):

-      <main id="main-content" className="flex-grow focus:outline-none">
+      <div id="main-content" role="main" className="flex-grow focus:outline-none">
         <Outlet /> {/* This will render the current page */}
-      </main>
+      </div>

Run to find pages using <main>:


🏁 Script executed:

#!/bin/bash
rg -n -C2 '<main\b' client/src/pages

Length of output: 2336


Avoid nested <main> landmarks by removing page-level <main>

  • rg found page-level <main> in client/src/pages/{Interview.jsx:192, SignUp.jsx:241, Report.jsx:45, Dashboard.jsx:108, Login.jsx:196, Home.jsx:11}
  • Option A (preferred): replace each page-level <main> with a <div> under App’s single <main>
  • Option B (stopgap): in App.jsx change <main id="main-content"> to <div id="main-content" role="main">
🤖 Prompt for AI Agents
In client/src/App.jsx around lines 34 to 36, the app currently renders a
top-level <main> and Outlet pages also contain their own <main> elements causing
nested landmark conflict; to fix, follow the preferred Option A: update each
page file (client/src/pages/Interview.jsx, SignUp.jsx, Report.jsx,
Dashboard.jsx, Login.jsx, Home.jsx) to replace their page-level <main> elements
with <div> (keeping classes/ids/aria attributes intact), or if you need a
stopgap, change the App.jsx <main id="main-content"> to <div id="main-content"
role="main"> so there is only a single main landmark. Ensure IDs, focus
handling, and existing accessibility attributes are preserved after the change.

import Leaderboard from "../components/Leaderboard";
import { useAuth } from "../context/AuthContext";
import { useUserData } from "../context/UserDataContext";
import { useState as useLocalState, useEffect as useLocalEffect } from "react";
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove confusing React hook aliasing.

Creating aliases for React hooks (useState as useLocalState, useEffect as useLocalEffect) is unnecessary and confusing. It doesn't provide any functional benefit and makes the code harder to understand.

-import { useState as useLocalState, useEffect as useLocalEffect } from "react";
-   const [mockInterviews, setMockInterviews] = useLocalState([]);
-   const [recentActivity, setRecentActivity] = useLocalState([]);
-   const [recommendedResources, setRecommendedResources] = useLocalState([]);
+   const [mockInterviews, setMockInterviews] = useState([]);
+   const [recentActivity, setRecentActivity] = useState([]);
+   const [recommendedResources, setRecommendedResources] = useState([]);
-   useLocalEffect(() => {
+   useEffect(() => {

Also applies to: 21-23

🤖 Prompt for AI Agents
In client/src/pages/Dashboard.jsx around lines 12 (and also lines 21-23), the
React hooks are aliased (e.g., useState as useLocalState, useEffect as
useLocalEffect) which is confusing and unnecessary; update the import to import
hooks directly from "react" (e.g., import { useState, useEffect, ... } from
"react") and then rename any usages in this file back to the standard hook
names, removing the aliasing everywhere so the code uses the canonical React
hook identifiers.

Comment on lines +89 to +103
useLocalEffect(() => {
const fetchWidgets = async () => {
try {
const [mockRes, activityRes, resourceRes] = await Promise.all([
axios.get(`${import.meta.env.VITE_API_URL}/api/mock-interview?upcoming=1`),
axios.get(`${import.meta.env.VITE_API_URL}/api/user/activity`),
axios.get(`${import.meta.env.VITE_API_URL}/api/resources/recommended`),
]);
setMockInterviews(mockRes.data);
setRecentActivity(activityRes.data);
setRecommendedResources(resourceRes.data);
} catch {}
};
fetchWidgets();
}, []);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add authentication and error handling to widget API calls.

The personalized widget API calls lack authentication headers and proper error handling. The empty catch block silently swallows errors.

useEffect(() => {
   const fetchWidgets = async () => {
      try {
+        const token = user ? await user.getIdToken() : null;
+        if (!token) return;
+        
         const [mockRes, activityRes, resourceRes] = await Promise.all([
-           axios.get(`${import.meta.env.VITE_API_URL}/api/mock-interview?upcoming=1`),
-           axios.get(`${import.meta.env.VITE_API_URL}/api/user/activity`),
-           axios.get(`${import.meta.env.VITE_API_URL}/api/resources/recommended`),
+           axios.get(`${import.meta.env.VITE_API_URL}/api/mock-interview?upcoming=1`, {
+              headers: { Authorization: `Bearer ${token}` }
+           }),
+           axios.get(`${import.meta.env.VITE_API_URL}/api/user/activity`, {
+              headers: { Authorization: `Bearer ${token}` }
+           }),
+           axios.get(`${import.meta.env.VITE_API_URL}/api/resources/recommended`, {
+              headers: { Authorization: `Bearer ${token}` }
+           }),
         ]);
         setMockInterviews(mockRes.data);
         setRecentActivity(activityRes.data);
         setRecommendedResources(resourceRes.data);
-      } catch {}
+      } catch (error) {
+        console.error("Failed to fetch personalized widgets:", error);
+      }
   };
-  fetchWidgets();
-}, []);
+  if (user) {
+     fetchWidgets();
+  }
+}, [user]);

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (2.1.2)

[error] 89-89: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

🤖 Prompt for AI Agents
In client/src/pages/Dashboard.jsx around lines 89 to 103, the API calls in
fetchWidgets are missing authentication headers and silently swallow errors;
update the requests to include the proper Authorization header (e.g., Bearer
token obtained from your auth provider or localStorage/getAuthToken function)
for each axios.get, replace the empty catch with robust error handling that logs
the error, updates a component error state or shows a user-facing message, and
handles authentication failures (401) by triggering a token refresh or redirect
to login; ensure Promise.all still uses the same headers and surface errors
instead of ignoring them.

Comment on lines +115 to +117
{userData && <Badges badges={userData.badges} />}
{userData && <StreakCounter streak={userData.streak} />}
</div>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add defensive checks for userData properties.

The code accesses userData.badges and userData.streak without checking if these properties exist, which could cause runtime errors.

-{userData && <Badges badges={userData.badges} />}
-{userData && <StreakCounter streak={userData.streak} />}
+{userData?.badges && <Badges badges={userData.badges} />}
+{userData?.streak && <StreakCounter streak={userData.streak} />}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{userData && <Badges badges={userData.badges} />}
{userData && <StreakCounter streak={userData.streak} />}
</div>
{userData?.badges && <Badges badges={userData.badges} />}
{userData?.streak && <StreakCounter streak={userData.streak} />}
</div>
🤖 Prompt for AI Agents
In client/src/pages/Dashboard.jsx around lines 115 to 117, the code passes
userData.badges and userData.streak directly to child components which can throw
if userData is present but those properties are undefined; update the rendering
to defensively handle missing properties by either only rendering the children
when the specific properties exist or supplying safe defaults (e.g., badges ->
empty array, streak -> 0) using nullish/optional checks so the Badges and
StreakCounter always receive valid values.

Comment on lines +174 to +175
const currentFilteredIndex = filteredIndexes.indexOf(currentQuestionIndex);
const currentQuestion = questions[currentQuestionIndex];
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential index mismatch with filtered questions.

The currentFilteredIndex can be -1 when currentQuestionIndex is not in filteredIndexes, which would cause Question 0 of X to display and potentially break array access.

Add proper bounds checking:

 const filteredQuestions = filteredIndexes.map((i) => questions[i]);
 const currentFilteredIndex = filteredIndexes.indexOf(currentQuestionIndex);
+// Ensure we have a valid index
+const displayIndex = currentFilteredIndex >= 0 ? currentFilteredIndex : 0;
 const currentQuestion = questions[currentQuestionIndex];

And update the display:

-Question {currentFilteredIndex + 1} of {filteredQuestions.length}
+Question {displayIndex + 1} of {filteredQuestions.length}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const currentFilteredIndex = filteredIndexes.indexOf(currentQuestionIndex);
const currentQuestion = questions[currentQuestionIndex];
const filteredQuestions = filteredIndexes.map((i) => questions[i]);
const currentFilteredIndex = filteredIndexes.indexOf(currentQuestionIndex);
// Ensure we have a valid index
const displayIndex = currentFilteredIndex >= 0 ? currentFilteredIndex : 0;
const currentQuestion = questions[currentQuestionIndex];
Suggested change
const currentFilteredIndex = filteredIndexes.indexOf(currentQuestionIndex);
const currentQuestion = questions[currentQuestionIndex];
Question {displayIndex + 1} of {filteredQuestions.length}
🤖 Prompt for AI Agents
In client/src/pages/Interview.jsx around lines 174-175, the code assumes
currentQuestionIndex is present in filteredIndexes so currentFilteredIndex can
be -1 causing incorrect "Question 0 of X" and possible out-of-bounds access; add
a guard: check if currentFilteredIndex === -1 and if so avoid using it for the
user-facing position (e.g. set a safe fallback value or display a placeholder
like '-' or compute a closest index), and also validate currentQuestionIndex is
within questions.length before doing questions[currentQuestionIndex] to avoid
array access errors; update the UI display logic to use the guarded display
index or fallback when the question is not in filteredIndexes.

bookmarked={userData.bookmarks?.includes(currentQuestion._id)}
onClick={async () => {
try {
const token = await userData.firebase_user_id;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

userData.firebase_user_id is not a promise.

The code incorrectly awaits userData.firebase_user_id which appears to be a string property, not a promise.

-const token = await userData.firebase_user_id;
+// Get the actual auth token from the user object
+const { user } = useAuth();
+const token = await user.getIdToken();

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In client/src/pages/Interview.jsx around line 228, the code awaits
userData.firebase_user_id even though firebase_user_id is a plain string
property; remove the await and assign the value directly (const token =
userData.firebase_user_id) and add a simple null/undefined check (or fallback)
before using token to avoid runtime errors.

Comment on lines +32 to +35
{ path: "resources", element: <Resources /> },
{ path: "resume-review", element: <ProtectedRoute><ResumeReview /></ProtectedRoute> },
{ path: "mock-interview", element: <ProtectedRoute><MockInterview /></ProtectedRoute> },
{ path: "community-qa", element: <ProtectedRoute><CommunityQA /></ProtectedRoute> },
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

ProtectedRoute may redirect before auth finishes loading (flicker).

The current guard doesn’t consider the loading state from AuthProvider, so hard-refreshing a protected URL can momentarily redirect to /login. Consider updating ProtectedRoute to wait for loading === false before deciding.

Apply in client/src/components/ProtectedRoute.jsx:

-const ProtectedRoute = ({ children }) => {
-  const { user } = useAuth();
-  return user ? children : <Navigate to="/login" />;
-};
+const ProtectedRoute = ({ children }) => {
+  const { user, loading } = useAuth();
+  if (loading) {
+    return <div role="status" aria-live="polite" className="sr-only">Checking session…</div>;
+  }
+  return user ? children : <Navigate to="/login" replace />;
+};

To verify, log in, navigate to /resume-review, then hard-refresh the page and ensure there’s no flash redirect to /login.


🏁 Script executed:

#!/bin/bash
# Locate and inspect ProtectedRoute.jsx
echo "== ProtectedRoute Definition =="
rg -n "const ProtectedRoute" -g "*.jsx"

# Locate and inspect useAuth usage in ProtectedRoute
echo "== useAuth in ProtectedRoute =="
rg -n "useAuth" -C2 -g "*.jsx" | rg -A3 "ProtectedRoute"

# Find AuthProvider file
echo "== AuthProvider File =="
rg -l "AuthProvider" -g "*.jsx"

# Print first 200 lines of AuthProvider to check for loading state
echo "== AuthProvider Contents =="
sed -n '1,200p' "$(rg -l "AuthProvider" -g "*.jsx")"

Length of output: 1681


🏁 Script executed:

#!/bin/bash
# Inspect AuthContext to verify loading state availability
sed -n '1,200p' client/src/context/AuthContext.jsx

Length of output: 1228


Handle loading state in ProtectedRoute to prevent flicker.

In client/src/components/ProtectedRoute.jsx, include the loading flag from useAuth and delay redirect until it’s false:

 const ProtectedRoute = ({ children }) => {
-  const { user } = useAuth();
+  const { user, loading } = useAuth();
+  if (loading) {
+    return <div role="status" aria-live="polite" className="sr-only">Checking session…</div>;
+  }
-  return user ? children : <Navigate to="/login" />;
+  return user ? children : <Navigate to="/login" replace />;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{ path: "resources", element: <Resources /> },
{ path: "resume-review", element: <ProtectedRoute><ResumeReview /></ProtectedRoute> },
{ path: "mock-interview", element: <ProtectedRoute><MockInterview /></ProtectedRoute> },
{ path: "community-qa", element: <ProtectedRoute><CommunityQA /></ProtectedRoute> },
// client/src/components/ProtectedRoute.jsx
import React from 'react';
import { Navigate } from 'react-router-dom';
import useAuth from '../hooks/useAuth';
const ProtectedRoute = ({ children }) => {
const { user, loading } = useAuth();
if (loading) {
return (
<div role="status" aria-live="polite" className="sr-only">
Checking session…
</div>
);
}
return user ? children : <Navigate to="/login" replace />;
};
export default ProtectedRoute;
🤖 Prompt for AI Agents
In client/src/routes.jsx around lines 32 to 35, the ProtectedRoute components
can cause a UI flicker while auth state initializes; update
client/src/components/ProtectedRoute.jsx to read the loading flag from useAuth
and, when loading is true, render a placeholder (null or spinner) instead of
redirecting or rendering the child; only evaluate and perform the redirect when
loading is false (if no user, navigate to login), otherwise render children when
user exists. Ensure the hook import and types remain intact and avoid performing
navigation during the loading state.

@vercel
Copy link

vercel bot commented Sep 9, 2025

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

Project Deployment Preview Comments Updated (UTC)
prepedge_ai Error Error Sep 10, 2025 5:12pm

@Gupta-02
Copy link
Author

@CoderUzumaki hello man
I have made 2 commits please review and merge the changes made

@CoderUzumaki
Copy link
Owner

Hey @Gupta-02 ,

Thank you for your taking out time to contribute in our repository, We appreciate your effort. However few things are to be cleared first:

Please be expressive in your PR. Ensure that your PR follows the template shared by us in the repository.

Your PR lacks basic information, such as Details of Changes made by you, which makes it really difficult for us to review your code.

You haven't linked this PR to an issue, PRs will only be merged, if you have been assigned to a issue linked with this PR.

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