Skip to content

Conversation

@eyad-hazem-elmorsy
Copy link
Contributor

@eyad-hazem-elmorsy eyad-hazem-elmorsy commented Jan 5, 2026

Proposed change

Resolves #3135

Checklist

  • Required: I read and followed the contributing guidelines
  • Required: I ran make check-test locally and all tests passed
  • I used AI for code, documentation, or tests in this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling to distinguish between data not found (404) and request failures (500) across detail pages, with clearer error messages displayed to users.
  • Tests

    • Enhanced test coverage for error scenarios across multiple detail pages, ensuring proper error message display and loading state management during API requests.

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

Walkthrough

Replaces local useState-based loading/data handling with Apollo useQuery’s loading and data across multiple pages and updates unit tests to explicitly mock loading; components derive entities from query data and add explicit 500/404 render branches; one type property made optional.

Changes

Cohort / File(s) Summary
Unit tests (page components)
frontend/__tests__/unit/pages/ChapterDetails.test.tsx, frontend/__tests__/unit/pages/OrganizationDetails.test.tsx, frontend/__tests__/unit/pages/ProjectDetails.test.tsx, frontend/__tests__/unit/pages/RepositoryDetails.test.tsx, frontend/__tests__/unit/pages/Snapshots.test.tsx, frontend/__tests__/unit/pages/CommitteeDetails.test.tsx, frontend/__tests__/unit/pages/ModuleDetails.test.tsx, frontend/__tests__/unit/pages/SnapshotDetails.test.tsx, frontend/__tests__/unit/pages/UserDetails.test.tsx
Updated useQuery mocks to include explicit loading values; split "not found" vs GraphQL error expectations and updated visible error messages (e.g., "Error loading …" vs "… not found").
Chapters & Committees
frontend/src/app/chapters/[chapterKey]/page.tsx, frontend/src/app/committees/[committeeKey]/page.tsx
Removed local isLoading and state syncing; derive entity data from data; use loading from useQuery; added explicit 500/404 render branches.
Community snapshots
frontend/src/app/community/snapshots/[id]/page.tsx, frontend/src/app/community/snapshots/page.tsx
Eliminated local snapshot/loading state; derive snapshot/snapshots from data; use query loading for spinner and add 500/404 guards.
Members
frontend/src/app/members/[memberKey]/page.tsx
Replaced multiple local state vars with direct destructuring from GraphQL data; use loading from query; added explicit 500/404 handling.
Organizations & repositories
frontend/src/app/organizations/[organizationKey]/page.tsx, frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx
Removed local state/useEffect syncing; read data and loading directly from query; updated render guards and normalized followersCount to string.
Mentorship (programs & modules)
frontend/src/app/mentorship/programs/[programKey]/page.tsx, frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx, frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx, frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx
Removed local loading/state population; derive program/module data from data and use query loading (aliased isLoading); removed URL-based refresh logic in program page; added 500/404 branches.
Projects & dashboard
frontend/src/app/projects/[projectKey]/page.tsx, frontend/src/app/projects/dashboard/page.tsx
Dropped local isLoading and state setters; derive project/topContributors from data; use query loading and explicit 500/404 guards.
Home page
frontend/src/app/page.tsx
Removed local data/isLoading syncing; use graphQLData and loading from useQuery directly; removed MainPageData type import.
Type changes
frontend/src/types/project.ts
RepositoryCardProps.subscribersCount changed from required number to optional number?.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • arkid15r
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning One out-of-scope change detected: frontend/src/types/project.ts makes subscribersCount optional, which is unrelated to the loading state refactoring objective. Remove the subscribersCount property modification from frontend/src/types/project.ts or address it in a separate PR focused on type adjustments.
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 (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main refactoring objective: replacing useState loading with useQuery's loading property.
Description check ✅ Passed The description references the linked issue (#3135) and confirms the PR resolves the loading state refactor requirements.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #3135: removes redundant useState loading state, uses useQuery.loading directly, applies refactor across all listed pages, and maintains app behavior and UI indicators.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 646799b and 2b136dc.

📒 Files selected for processing (7)
  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
  • frontend/__tests__/unit/pages/CommitteeDetails.test.tsx
  • frontend/__tests__/unit/pages/ModuleDetails.test.tsx
  • frontend/__tests__/unit/pages/ProjectDetails.test.tsx
  • frontend/__tests__/unit/pages/SnapshotDetails.test.tsx
  • frontend/__tests__/unit/pages/UserDetails.test.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/tests/unit/pages/ProjectDetails.test.tsx
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
📚 Learning: 2025-07-12T17:36:57.255Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/__tests__/unit/pages/createProgram.test.tsx:70-86
Timestamp: 2025-07-12T17:36:57.255Z
Learning: When testing React page components that use mocked form components, validation logic should be tested at the form component level, not the page level. Page-level tests should focus on authentication, role checking, submission handling, and navigation logic.

Applied to files:

  • frontend/__tests__/unit/pages/UserDetails.test.tsx
  • frontend/__tests__/unit/pages/ModuleDetails.test.tsx
  • frontend/__tests__/unit/pages/CommitteeDetails.test.tsx
  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
📚 Learning: 2025-11-17T16:47:05.578Z
Learnt from: anurag2787
Repo: OWASP/Nest PR: 2671
File: frontend/__tests__/unit/components/MultiSearch.test.tsx:427-427
Timestamp: 2025-11-17T16:47:05.578Z
Learning: In the frontend test files for the OWASP/Nest repository, `expect(true).toBe(true)` no-op assertions may be intentionally added as workarounds when ESLint rule jest/expect-expect doesn't detect expectations inside helper functions or waitFor callbacks. These can be resolved by configuring the ESLint rule's assertFunctionNames option to recognize custom assertion helpers instead of flagging them as redundant.

Applied to files:

  • frontend/__tests__/unit/pages/UserDetails.test.tsx
  • frontend/__tests__/unit/pages/CommitteeDetails.test.tsx
  • frontend/__tests__/unit/pages/SnapshotDetails.test.tsx
  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
📚 Learning: 2025-07-12T17:14:28.536Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/[programKey]/edit/page.tsx:90-128
Timestamp: 2025-07-12T17:14:28.536Z
Learning: Both ProgramForm (programCard.tsx) and ModuleForm (mainmoduleCard.tsx) components already implement HTML validation using the `required` attribute on form fields. The browser's native validation prevents form submission and displays error messages when required fields are empty, eliminating the need for additional JavaScript validation before GraphQL mutations.

Applied to files:

  • frontend/__tests__/unit/pages/ModuleDetails.test.tsx
📚 Learning: 2025-11-17T17:30:42.139Z
Learnt from: anurag2787
Repo: OWASP/Nest PR: 2671
File: frontend/__tests__/unit/components/MultiSearch.test.tsx:169-171
Timestamp: 2025-11-17T17:30:42.139Z
Learning: In the OWASP/Nest frontend tests (PR #2671 context), wrapper functions like `expectChaptersCountEqualsThree` that simply call another helper with a fixed parameter (e.g., `expectChaptersCountEquals(3)`) are intentionally used to avoid arrow function callbacks in `waitFor` calls. This pattern prevents adding nesting depth that would trigger rule typescript:S2004. Example: `await waitFor(expectChaptersCountEqualsThree)` avoids the extra nesting from `await waitFor(() => expectChaptersCountEquals(3))`.

Applied to files:

  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
🧬 Code graph analysis (2)
frontend/__tests__/unit/pages/ModuleDetails.test.tsx (1)
frontend/src/app/global-error.tsx (1)
  • handleAppError (67-91)
frontend/__tests__/unit/pages/ChapterDetails.test.tsx (1)
frontend/src/app/chapters/[chapterKey]/page.tsx (1)
  • ChapterDetailsPage (13-96)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend e2e tests
🔇 Additional comments (5)
frontend/__tests__/unit/pages/ModuleDetails.test.tsx (1)

56-102: LGTM! Excellent improvement to error handling test coverage.

The changes enhance test coverage by:

  1. Verifying both error handler invocation AND UI error message display (lines 56-69)
  2. Adding explicit tests for 404-like scenarios when data is null (lines 71-83)
  3. Covering the edge case where data exists but the module entity is null (lines 85-102)

The test structure is consistent, assertions are clear, and the mock data explicitly includes loading, error, and data states, which aligns well with the PR objective of using useQuery's native properties.

frontend/__tests__/unit/pages/SnapshotDetails.test.tsx (1)

82-114: LGTM! Clear separation of error vs not-found scenarios.

The changes properly distinguish between:

  • GraphQL errors (lines 82-101): Show "Error loading snapshot" and trigger toast notification
  • Missing data without error (lines 103-114): Show "Snapshot not found" (404-like scenario)

The explicit loading: false on line 86 makes the mock state clearer and aligns with the PR's goal of using useQuery's native loading property. The error messaging pattern is consistent across the test suite.

frontend/__tests__/unit/pages/ChapterDetails.test.tsx (1)

42-91: LGTM! Consistent error handling pattern across test scenarios.

The improvements include:

  1. Line 46: Explicit loading: true in the loading state mock makes the test intention clearer
  2. Lines 69-79: GraphQL error test properly expects "Error loading chapter" with explicit mock state (data: null, error, loading: false)
  3. Lines 81-91: New test for 404-like scenario (null data without error) displays "Chapter not found"

The test structure matches the pattern established in other detail page tests and properly validates the component's use of useQuery's native loading property.

frontend/__tests__/unit/pages/CommitteeDetails.test.tsx (1)

60-70: LGTM! Consistent error messaging alignment.

The changes maintain consistency across the test suite:

  1. Lines 60-70: More explicit test description and mock state (error: null, loading: false) for the 404-like scenario
  2. Line 120: Updated error message to "Error loading committee" to match the standardized error messaging pattern used across all detail page tests

The mock structure properly reflects useQuery's return shape and validates the component's error handling behavior.

Also applies to: 111-122

frontend/__tests__/unit/pages/UserDetails.test.tsx (1)

349-370: Error message is correct and matches component implementation.

The test properly expects "Error loading user" which matches what the component's ErrorDisplay renders when GraphQL fails. The explicit loading: false in the mock is appropriate for this error state and aligns with the PR's use of Apollo's loading property.


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
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

Fix all issues with AI Agents 🤖
In @frontend/src/components/CardDetailsPage.tsx:
- Line 14: The RepositoryCardProps type import and the explicit cast to
RepositoryCardProps[] are out of scope for this loading-state refactor—remove
the RepositoryCardProps import and undo the cast at the code that coerces the
repository list (the site where you wrote "as RepositoryCardProps[]"); instead
preserve the existing DetailsCardProps shape (Partial<RepositoryCardProps>[]) by
either keeping the repositories value uncast or casting it to
Partial<RepositoryCardProps>[] if a cast is necessary; leave any proper type
cleanup (removing Partial<> or changing prop types) to a separate PR.

In @frontend/src/types/card.ts:
- Line 69: The repositories property was relaxed to
Partial<RepositoryCardProps>[] but CardDetailsPage casts it back to
RepositoryCardProps[] (unsafe) and RepositoryCard expects required fields;
decide which model is true: if repository data is always complete, revert
repositories to RepositoryCardProps[] and remove the cast in CardDetailsPage,
ensuring types align; if data can be partial, keep
Partial<RepositoryCardProps>[], remove the cast in CardDetailsPage, and update
RepositoryCard (props and usages) to accept optional fields and guard against
missing values; avoid mixing both approaches in this PR—defer unrelated
type-only refactors to a separate change.
🧹 Nitpick comments (5)
frontend/src/app/members/[memberKey]/page.tsx (1)

105-113: Redundant !isLoading check.

Since the component already returns early on line 97 when isLoading is true, the !isLoading check here is always true and can be simplified.

🔎 Suggested simplification
-  if (!isLoading && user == null) {
+  if (user == null) {
frontend/__tests__/unit/pages/ChapterDetails.test.tsx (1)

31-36: Consider adding explicit loading: false for consistency.

The beforeEach mock doesn't include the loading property. While this works (undefined is falsy), adding loading: false explicitly would improve test clarity and consistency with the loading test case.

🔎 Suggested improvement
   beforeEach(() => {
     ;(useQuery as unknown as jest.Mock).mockReturnValue({
       data: mockChapterDetailsData,
       error: null,
+      loading: false,
     })
   })
frontend/src/app/page.tsx (1)

47-55: Loading refactor is correct, but alias is redundant.

The loading state refactoring is correctly implemented. However, the alias const data = graphQLData on line 55 adds unnecessary indirection. Consider using graphQLData directly throughout, or rename it in the destructuring.

🔎 Suggested simplification

Either rename in destructuring:

   const {
-    data: graphQLData,
+    data,
     error: graphQLRequestError,
     loading: isLoading,
   } = useQuery(GetMainPageDataDocument, {
     variables: { distinct: true },
   })
-
-  const data = graphQLData

Or use graphQLData directly throughout the component and remove line 55.

frontend/src/app/organizations/[organizationKey]/page.tsx (2)

24-28: Consider removing organizationKey from the dependency array.

The organizationKey is not used within the effect body. Since the query automatically re-runs when organizationKey changes, and graphQLRequestError will have a new reference if the query fails, including organizationKey in the dependencies is redundant.

🔎 Proposed refinement
  useEffect(() => {
    if (graphQLRequestError) {
      handleAppError(graphQLRequestError)
    }
-  }, [graphQLRequestError, organizationKey])
+  }, [graphQLRequestError])

73-73: String conversion appears defensive.

The String() conversion on followersCount seems unnecessary if the GraphQL schema returns a number and the display component handles numeric values. However, if this ensures type consistency for the label-value pairs in organizationDetails, it's acceptable defensive programming.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3e017d and 351aaaa.

📒 Files selected for processing (20)
  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx
  • frontend/__tests__/unit/pages/ProjectDetails.test.tsx
  • frontend/__tests__/unit/pages/RepositoryDetails.test.tsx
  • frontend/__tests__/unit/pages/Snapshots.test.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
  • frontend/src/app/community/snapshots/page.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/organizations/[organizationKey]/page.tsx
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx
  • frontend/src/app/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/app/projects/dashboard/page.tsx
  • frontend/src/components/CardDetailsPage.tsx
  • frontend/src/types/card.ts
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS is actively used in frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx for program editing functionality and cannot be removed. It serves a different purpose than GET_PROGRAM_ADMIN_DETAILS, providing comprehensive program information needed for editing.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/organizations/[organizationKey]/page.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
📚 Learning: 2025-07-12T17:14:28.536Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/[programKey]/edit/page.tsx:90-128
Timestamp: 2025-07-12T17:14:28.536Z
Learning: Both ProgramForm (programCard.tsx) and ModuleForm (mainmoduleCard.tsx) components already implement HTML validation using the `required` attribute on form fields. The browser's native validation prevents form submission and displays error messages when required fields are empty, eliminating the need for additional JavaScript validation before GraphQL mutations.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details. These queries cannot be removed or merged as they serve different use cases in the application.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-09-29T06:02:35.566Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/components/SingleModuleCard.tsx:54-54
Timestamp: 2025-09-29T06:02:35.566Z
Learning: In the Module type from types/mentorship.ts, the experienceLevel field is required (experienceLevel: ExperienceLevelEnum), not optional, so null/undefined checks are not needed when accessing this field.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-09-21T17:04:48.154Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
📚 Learning: 2025-07-13T07:31:06.511Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/components/ModuleCard.tsx:53-55
Timestamp: 2025-07-13T07:31:06.511Z
Learning: In Next.js 13+ app router, useRouter from 'next/navigation' does not provide asPath or query properties. Use useParams to extract route parameters and usePathname to get the current pathname instead.

Applied to files:

  • frontend/src/app/organizations/[organizationKey]/page.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
📚 Learning: 2025-07-13T11:29:25.245Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/page.tsx:59-61
Timestamp: 2025-07-13T11:29:25.245Z
Learning: In Next.js 13+ app router, components with the 'use client' directive run entirely on the client side and don't require window object existence checks or SSR hydration considerations. Direct access to window.location and other browser APIs is safe in client components.

Applied to files:

  • frontend/src/app/organizations/[organizationKey]/page.tsx
📚 Learning: 2025-07-12T17:36:57.255Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/__tests__/unit/pages/createProgram.test.tsx:70-86
Timestamp: 2025-07-12T17:36:57.255Z
Learning: When testing React page components that use mocked form components, validation logic should be tested at the form component level, not the page level. Page-level tests should focus on authentication, role checking, submission handling, and navigation logic.

Applied to files:

  • frontend/__tests__/unit/pages/ChapterDetails.test.tsx
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx
  • frontend/__tests__/unit/pages/ProjectDetails.test.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a safety check that ensures HealthMetrics component is only rendered when healthMetricsData exists and has at least one element: `healthMetricsData && healthMetricsData.length > 0`. This makes accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/app/projects/dashboard/page.tsx
📚 Learning: 2025-07-13T11:34:31.823Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/page.tsx:14-14
Timestamp: 2025-07-13T11:34:31.823Z
Learning: In the Next.js frontend mentorship application, there are two distinct types for authentication-related data: ExtendedSession for useSession hook (containing accessToken and user.login properties) and UserRolesData for useUserRoles hook (containing currentUserRoles.roles array). The correct access pattern for GitHub username is `(session as ExtendedSession)?.user?.login`.

Applied to files:

  • frontend/src/components/CardDetailsPage.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
🧬 Code graph analysis (14)
frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)
frontend/src/types/__generated__/moduleQueries.generated.ts (1)
  • GetProgramAdminsAndModulesDocument (41-41)
frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx (1)
frontend/src/types/__generated__/menteeQueries.generated.ts (1)
  • GetModuleMenteeDetailsDocument (14-14)
frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)
frontend/src/types/__generated__/moduleQueries.generated.ts (1)
  • GetProgramAdminsAndModulesDocument (41-41)
frontend/src/app/organizations/[organizationKey]/page.tsx (1)
frontend/src/types/__generated__/organizationQueries.generated.ts (1)
  • GetOrganizationDataDocument (19-19)
frontend/src/app/chapters/[chapterKey]/page.tsx (3)
frontend/src/types/__generated__/chapterQueries.generated.ts (1)
  • GetChapterDataDocument (19-19)
backend/apps/owasp/api/internal/queries/chapter.py (1)
  • chapter (14-19)
frontend/src/app/global-error.tsx (1)
  • handleAppError (67-91)
frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx (1)
frontend/src/types/__generated__/repositoryQueries.generated.ts (1)
  • GetRepositoryDataDocument (21-21)
frontend/src/app/projects/[projectKey]/page.tsx (1)
frontend/src/types/__generated__/projectQueries.generated.ts (1)
  • GetProjectDocument (36-36)
frontend/src/components/CardDetailsPage.tsx (2)
backend/apps/owasp/api/internal/nodes/project.py (1)
  • repositories (100-107)
frontend/src/types/project.ts (1)
  • RepositoryCardProps (56-67)
frontend/src/app/committees/[committeeKey]/page.tsx (1)
frontend/src/types/__generated__/committeeQueries.generated.ts (1)
  • GetCommitteeDataDocument (19-19)
frontend/src/app/page.tsx (1)
frontend/src/types/__generated__/homeQueries.generated.ts (1)
  • GetMainPageDataDocument (12-12)
frontend/src/app/community/snapshots/[id]/page.tsx (1)
frontend/src/types/__generated__/snapshotQueries.generated.ts (1)
  • GetSnapshotDetailsDocument (24-24)
frontend/src/types/card.ts (1)
frontend/src/types/project.ts (1)
  • RepositoryCardProps (56-67)
frontend/src/app/members/[memberKey]/page.tsx (1)
frontend/src/types/__generated__/userQueries.generated.ts (1)
  • GetUserDataDocument (27-27)
frontend/src/app/community/snapshots/page.tsx (1)
frontend/src/types/__generated__/snapshotQueries.generated.ts (1)
  • GetCommunitySnapshotsDocument (26-26)
🔇 Additional comments (22)
frontend/__tests__/unit/pages/RepositoryDetails.test.tsx (1)

44-57: LGTM! Loading state mock is now explicit.

The addition of loading: true to the mock correctly simulates Apollo Client's loading state, ensuring the loading spinner assertion validates the expected UI behavior.

frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (1)

181-201: LGTM! Error state mock is complete.

Adding loading: false to the error scenario mock correctly represents Apollo Client's behavior when a query fails—loading completes (false) and error is populated. This makes the test state explicit and robust.

frontend/__tests__/unit/pages/ProjectDetails.test.tsx (1)

57-70: LGTM! Loading state mock is explicit.

The addition of loading: true correctly simulates the initial loading phase, allowing the test to validate that the loading indicator renders as expected.

frontend/src/app/community/snapshots/page.tsx (1)

15-19: Successful refactor! Loading state now driven by Apollo Client.

The destructuring of loading: isLoading from useQuery correctly replaces the manual useState loading management, eliminating the need for setIsLoading(false) calls. The component now relies on Apollo Client's built-in loading state, which is more reliable and reduces complexity.

frontend/__tests__/unit/pages/Snapshots.test.tsx (1)

53-66: LGTM! Loading state test properly configured.

The explicit loading: true in the mock ensures the test accurately validates the loading skeleton rendering behavior, completing the test suite updates for this refactor.

frontend/src/app/committees/[committeeKey]/page.tsx (1)

22-28: LGTM! Clean refactor to use Apollo's loading state.

The destructuring of loading as isLoading from useQuery correctly replaces the previous manual loading state management. This simplifies the code by eliminating redundant state tracking while maintaining the same loading behavior for the UI.

frontend/src/app/community/snapshots/[id]/page.tsx (1)

24-30: LGTM! Consistent refactor pattern.

The loading state is now correctly sourced from Apollo's useQuery hook. This change eliminates manual loading state management and aligns with the refactor pattern used across other page components in this PR.

frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx (1)

24-30: LGTM! Loading state refactor applied correctly.

The component now uses Apollo's loading flag from useQuery instead of manual state management. This maintains the existing loading behavior while reducing complexity and potential bugs from manual state synchronization.

frontend/src/app/projects/dashboard/page.tsx (1)

29-33: LGTM! Consistent loading state management.

The refactor correctly replaces manual loading state with Apollo's built-in loading property. This change simplifies state management and aligns with Apollo Client best practices.

frontend/src/app/projects/[projectKey]/page.tsx (1)

22-28: LGTM! Well-executed refactor across all files.

This refactor successfully replaces manual loading state with Apollo's loading property from useQuery. The change is consistent across all modified files in this PR, improving maintainability and reducing the potential for loading-state-related bugs.

frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/mentees/[menteeKey]/page.tsx (1)

37-49: Refactoring looks correct.

The loading state is now properly derived from Apollo's useQuery hook. The fetchPolicy: 'cache-and-network' will show cached data immediately while refetching from the network in the background, which is appropriate for this use case.

frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)

20-29: LGTM!

The loading state refactoring is correctly implemented. The component now derives loading state directly from the useQuery hook while maintaining proper data population and error handling.

frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)

19-28: LGTM!

The loading state refactoring follows the same correct pattern as the public module details page.

frontend/src/app/members/[memberKey]/page.tsx (1)

37-43: LGTM!

The loading state refactoring is correctly implemented with appropriate skeleton loading UI.

frontend/src/app/chapters/[chapterKey]/page.tsx (2)

15-24: Clean refactoring approach.

This file takes a cleaner approach by deriving chapter and topContributors directly from the query data without intermediate state. This eliminates unnecessary re-renders from state updates.


45-57: Verify the type narrowing logic in your IDE or with npm run test:unit.

The control flow appears sound: after the early return on line 32 (if (isLoading)), isLoading is false. The check on line 36 (if (!chapter && !isLoading)) returns early, so TypeScript should narrow chapter to non-null for lines 45-57. Modern TypeScript (5.9.3) typically handles this correctly, but type errors may still occur depending on how the Apollo Client types are configured. Verify locally that npm run test:unit (which runs tsc --noEmit) passes without errors on this file.

frontend/__tests__/unit/pages/ChapterDetails.test.tsx (1)

42-53: LGTM!

The test correctly mocks loading: true to verify the loading spinner renders. This aligns with the component's new reliance on the useQuery loading flag.

frontend/src/app/page.tsx (1)

59-70: Error handling effect is correctly scoped.

The dependency array correctly only includes graphQLRequestError since this effect only handles error toasting and no longer manages loading state.

frontend/src/app/organizations/[organizationKey]/page.tsx (4)

16-22: LGTM! Clean migration to Apollo's built-in loading state.

The destructuring pattern is clear and the aliasing of loading to isLoading maintains consistency with the codebase. This successfully eliminates the need for separate useState management.


30-36: LGTM! Proper use of Apollo's loading state.

The loading check correctly uses the isLoading flag from useQuery and provides appropriate skeleton feedback during data fetch.


38-56: LGTM! Clean data extraction and error handling.

The destructuring pattern with nullish coalescing (graphQLData ?? {}) safely handles the case when data is undefined. The !organization check appropriately displays a 404 error when the organization doesn't exist, while handleAppError in the useEffect handles GraphQL/network errors via toast notifications.


110-124: LGTM! Props correctly wired to use GraphQL data directly.

The component now passes the destructured data directly to DetailsCard, successfully eliminating the intermediate state layer. This aligns perfectly with the refactor objectives.

recentMilestones?: Milestone[]
recentReleases?: Release[]
repositories?: RepositoryCardProps[]
repositories?: Partial<RepositoryCardProps>[]
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Type relaxation seems inconsistent with usage and out of scope.

Changing repositories to Partial<RepositoryCardProps>[] relaxes all field requirements, but in CardDetailsPage.tsx line 310, the data is immediately cast back to RepositoryCardProps[], suggesting the fields are actually required.

This creates an inconsistency: if the data can be partial, components should handle missing fields explicitly; if it's always complete, the Partial<> wrapper is unnecessary and the cast in CardDetailsPage is unsafe.

Additionally, this type change appears unrelated to the PR's stated objective of refactoring loading state management (replacing useState with useQuery.loading).

Consider one of these approaches:

  1. If data is always complete: Remove the Partial<> wrapper and the cast in CardDetailsPage
  2. If data can be partial: Keep Partial<>, remove the cast, and update RepositoryCard to handle optional fields

Based on learnings, consider deferring unrelated type adjustments to a separate PR to maintain focus on the loading state migration.

🤖 Prompt for AI Agents
In @frontend/src/types/card.ts around line 69, The repositories property was
relaxed to Partial<RepositoryCardProps>[] but CardDetailsPage casts it back to
RepositoryCardProps[] (unsafe) and RepositoryCard expects required fields;
decide which model is true: if repository data is always complete, revert
repositories to RepositoryCardProps[] and remove the cast in CardDetailsPage,
ensuring types align; if data can be partial, keep
Partial<RepositoryCardProps>[], remove the cast in CardDetailsPage, and update
RepositoryCard (props and usages) to accept optional fields and guard against
missing values; avoid mixing both approaches in this PR—defer unrelated
type-only refactors to a separate change.

ahmedxgouda
ahmedxgouda previously approved these changes Jan 5, 2026
Copy link
Collaborator

@ahmedxgouda ahmedxgouda left a comment

Choose a reason for hiding this comment

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

LGTM

I don't know why sonar is complaining.

@eyad-hazem-elmorsy eyad-hazem-elmorsy marked this pull request as ready for review January 5, 2026 18:17
Copy link
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

🧹 Nitpick comments (2)
frontend/src/app/committees/[committeeKey]/page.tsx (1)

18-27: LGTM! Clean refactor to Apollo's loading state.

The refactor correctly eliminates local useState for isLoading, committee, and topContributors, and derives all data directly from the useQuery result. This aligns perfectly with the PR objectives.

Optional: Use nullish coalescing for semantic precision

Consider using ?? instead of || for the default array on line 27:

-  const topContributors = data?.topContributors || []
+  const topContributors = data?.topContributors ?? []

While || works correctly for arrays (since empty arrays are truthy), ?? more precisely expresses "use default only if null/undefined."

frontend/src/app/members/[memberKey]/page.tsx (1)

25-38: LGTM! Consistent refactor pattern.

The refactor successfully eliminates local useState for user data and loading state, deriving all values directly from the useQuery result. The use of graphQLData as the variable name appropriately avoids collision with the existing data state used for heatmap data.

Optional: Consider nullish coalescing for default arrays

For semantic precision, consider using ?? instead of || on lines 34-38:

-  const issues = graphQLData?.recentIssues || []
-  const topRepositories = graphQLData?.topContributedRepositories || []
-  const milestones = graphQLData?.recentMilestones || []
-  const pullRequests = graphQLData?.recentPullRequests || []
-  const releases = graphQLData?.recentReleases || []
+  const issues = graphQLData?.recentIssues ?? []
+  const topRepositories = graphQLData?.topContributedRepositories ?? []
+  const milestones = graphQLData?.recentMilestones ?? []
+  const pullRequests = graphQLData?.recentPullRequests ?? []
+  const releases = graphQLData?.recentReleases ?? []

While both operators work correctly for arrays, ?? more precisely expresses "use default only if null/undefined."

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16f0957 and e31105c.

📒 Files selected for processing (6)
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/__tests__/unit/pages/createProgram.test.tsx:70-86
Timestamp: 2025-07-12T17:36:57.255Z
Learning: When testing React page components that use mocked form components, validation logic should be tested at the form component level, not the page level. Page-level tests should focus on authentication, role checking, submission handling, and navigation logic.
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS is actively used in frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx for program editing functionality and cannot be removed. It serves a different purpose than GET_PROGRAM_ADMIN_DETAILS, providing comprehensive program information needed for editing.

Applied to files:

  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-07-13T11:34:31.823Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/page.tsx:14-14
Timestamp: 2025-07-13T11:34:31.823Z
Learning: In the Next.js frontend mentorship application, there are two distinct types for authentication-related data: ExtendedSession for useSession hook (containing accessToken and user.login properties) and UserRolesData for useUserRoles hook (containing currentUserRoles.roles array). The correct access pattern for GitHub username is `(session as ExtendedSession)?.user?.login`.

Applied to files:

  • frontend/src/app/members/[memberKey]/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details. These queries cannot be removed or merged as they serve different use cases in the application.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-07-12T17:14:28.536Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/[programKey]/edit/page.tsx:90-128
Timestamp: 2025-07-12T17:14:28.536Z
Learning: Both ProgramForm (programCard.tsx) and ModuleForm (mainmoduleCard.tsx) components already implement HTML validation using the `required` attribute on form fields. The browser's native validation prevents form submission and displays error messages when required fields are empty, eliminating the need for additional JavaScript validation before GraphQL mutations.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-07-08T17:24:36.501Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: backend/apps/mentorship/graphql/mutations/program.py:41-44
Timestamp: 2025-07-08T17:24:36.501Z
Learning: In the mentorship program GraphQL mutations, date validation is handled at the GraphQL schema/node level in the input types (CreateProgramInput, UpdateProgramInput), preventing null values from reaching the mutation logic where date comparisons are performed.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-07-13T07:31:06.511Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/components/ModuleCard.tsx:53-55
Timestamp: 2025-07-13T07:31:06.511Z
Learning: In Next.js 13+ app router, useRouter from 'next/navigation' does not provide asPath or query properties. Use useParams to extract route parameters and usePathname to get the current pathname instead.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-07-13T11:29:25.245Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/page.tsx:59-61
Timestamp: 2025-07-13T11:29:25.245Z
Learning: In Next.js 13+ app router, components with the 'use client' directive run entirely on the client side and don't require window object existence checks or SSR hydration considerations. Direct access to window.location and other browser APIs is safe in client components.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-09-29T06:02:35.566Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/components/SingleModuleCard.tsx:54-54
Timestamp: 2025-09-29T06:02:35.566Z
Learning: In the Module type from types/mentorship.ts, the experienceLevel field is required (experienceLevel: ExperienceLevelEnum), not optional, so null/undefined checks are not needed when accessing this field.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
🧬 Code graph analysis (4)
frontend/src/app/members/[memberKey]/page.tsx (3)
backend/apps/owasp/models/project.py (1)
  • issues (186-192)
backend/apps/github/models/user.py (2)
  • issues (67-74)
  • releases (82-89)
frontend/src/app/global-error.tsx (1)
  • handleAppError (67-91)
frontend/src/app/mentorship/programs/[programKey]/page.tsx (1)
frontend/src/types/__generated__/programsQueries.generated.ts (1)
  • GetProgramAndModulesDocument (37-37)
frontend/src/app/committees/[committeeKey]/page.tsx (3)
frontend/src/types/__generated__/committeeQueries.generated.ts (1)
  • GetCommitteeDataDocument (19-19)
backend/apps/owasp/api/internal/queries/committee.py (1)
  • committee (14-28)
frontend/src/app/global-error.tsx (2)
  • handleAppError (67-91)
  • ErrorDisplay (28-52)
frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (5)
frontend/src/types/__generated__/moduleQueries.generated.ts (1)
  • GetProgramAdminsAndModulesDocument (41-41)
backend/apps/mentorship/api/internal/nodes/program.py (1)
  • admins (32-34)
frontend/src/app/global-error.tsx (2)
  • handleAppError (67-91)
  • ErrorDisplay (28-52)
frontend/src/utils/dateFormatter.ts (1)
  • formatDate (1-20)
frontend/src/components/ModuleCard.tsx (1)
  • getSimpleDuration (96-111)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (11)
frontend/src/app/committees/[committeeKey]/page.tsx (1)

39-47: Appropriate 404 check.

The condition !data || !committee correctly handles the case where the query completes but returns no data. This ensures the 404 error is shown only after loading completes and when the committee truly doesn't exist.

frontend/src/app/members/[memberKey]/page.tsx (1)

92-100: Correct 404 condition.

The check !graphQLData || !user properly handles the case where the query completes but returns no user data, ensuring the 404 error is displayed only after loading finishes and the user truly doesn't exist. This pattern is consistent with the refactor in committees/[committeeKey]/page.tsx.

frontend/src/app/mentorship/programs/[programKey]/page.tsx (3)

4-4: LGTM: Simplified imports and params extraction.

The refactor correctly uses useParams from Next.js navigation, and the removal of useSearchParams and useRouter aligns with eliminating manual refresh logic per the PR objectives.

Also applies to: 14-14


20-21: LGTM: Direct data access simplifies state management.

Deriving program and modules directly from the query result eliminates the need for local state and manual synchronization, aligning with the PR objectives.


23-33: LGTM: Loading and 404 logic flow is correct.

The component correctly shows a loading spinner while the query executes, then displays a 404 for missing programs. The condition (!data || !program) is explicit and handles cases where the query succeeds but returns null for the program.

frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (6)

6-6: LGTM: Removed unused useState import.

The removal of useState from the React import correctly reflects that loading state is now managed by Apollo's useQuery hook, aligning with the PR's refactoring objective.


17-26: LGTM: Correctly uses Apollo's loading state.

The refactor successfully replaces local useState loading management with Apollo's built-in loading property, aliased as isLoading. This simplifies the code and ensures loading state is always synchronized with the query state.


31-47: LGTM: Improved error handling.

The error handling correctly combines handleAppError (for toast notifications and Sentry logging) with ErrorDisplay (for UI rendering). This dual approach provides both immediate user feedback via toast and a full-page error state, which is appropriate for this detail page.


49-57: LGTM: 404 handling correctly checks query data.

The 404 check appropriately validates the presence of query data and the module. The condition !data || !programModule correctly identifies when the module doesn't exist, which is the intended behavior for this detail page.


59-80: LGTM: Data usage correctly references query results.

All module field references have been properly updated to use programModule (derived from Apollo query data) instead of local state. The field mappings align with the GraphQL query structure, and utility functions (formatDate, getSimpleDuration, capitalize) are appropriately applied.


28-29: No action needed. The DetailsCard component is designed to accept an optional admins prop (admins?: Contributor[] in its interface). All usages within the component safely handle undefined values using optional chaining (admins?.some(...)) or explicit null checks ({admins && admins.length > 0 && ...}). If data.getProgram is null, admins will be undefined, which is a valid state that the component handles correctly.

Likely an incorrect or invalid review comment.

coderabbitai[bot]
coderabbitai bot previously requested changes Jan 6, 2026
Copy link
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

Caution

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

⚠️ Outside diff range comments (1)
frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)

31-47: Add explicit GraphQL error handling before the 404 check.

Currently, network or GraphQL errors result in data being null/undefined, causing the condition at Line 39 to render a 404 "Module Not Found" page. This conflates transient network failures with actual missing modules. The pattern in frontend/src/app/mentorship/programs/[programKey]/page.tsx (lines 36-44) is better: it explicitly checks for error and renders a 500 error page before checking for 404.

🔎 Proposed fix to add explicit error handling
  useEffect(() => {
    if (error) {
      handleAppError(error)
    }
  }, [error])

  if (isLoading) return <LoadingSpinner />

+ if (error) {
+   return (
+     <ErrorDisplay
+       statusCode={500}
+       title="Error loading module"
+       message="An error occurred while loading the module data"
+     />
+   )
+ }
+
  if (!data || !programModule) {
    return (
      <ErrorDisplay
        statusCode={404}
        title="Module Not Found"
        message="Sorry, the module you're looking for doesn't exist."
      />
    )
  }
🤖 Fix all issues with AI Agents
In @frontend/src/app/projects/[projectKey]/page.tsx:
- Around line 30-34: The effect watching for GraphQL errors unnecessarily
includes projectKey in its dependency array, causing re-runs when projectKey
changes even if the error is stale; in the useEffect that calls
handleAppError(graphQLRequestError) remove projectKey from the dependencies so
the hook only depends on graphQLRequestError (i.e., change the dependency array
for the useEffect that references graphQLRequestError and handleAppError to
[graphQLRequestError]).
🧹 Nitpick comments (2)
frontend/src/app/mentorship/programs/[programKey]/page.tsx (1)

28-32: Remove programKey from the useEffect dependency array.

Including programKey is unnecessary because Apollo Client automatically re-executes the query when variables change, and graphQLRequestError will be reset by the new query. The dependency array should only include graphQLRequestError.

🔎 Proposed fix
  useEffect(() => {
    if (graphQLRequestError) {
      handleAppError(graphQLRequestError)
    }
-  }, [graphQLRequestError, programKey])
+  }, [graphQLRequestError])
frontend/src/app/chapters/[chapterKey]/page.tsx (1)

31-31: Consider removing chapterKey from the dependency array.

The effect body only references graphQLRequestError, so including chapterKey is unnecessary. When chapterKey changes, the query re-runs and any error state change will trigger the effect via graphQLRequestError anyway.

🔎 Simplified dependency array
-  }, [graphQLRequestError, chapterKey])
+  }, [graphQLRequestError])
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e31105c and 50ec924.

📒 Files selected for processing (7)
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/app/committees/[committeeKey]/page.tsx
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS is actively used in frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx for program editing functionality and cannot be removed. It serves a different purpose than GET_PROGRAM_ADMIN_DETAILS, providing comprehensive program information needed for editing.

Applied to files:

  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
📚 Learning: 2025-07-13T07:31:06.511Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/components/ModuleCard.tsx:53-55
Timestamp: 2025-07-13T07:31:06.511Z
Learning: In Next.js 13+ app router, useRouter from 'next/navigation' does not provide asPath or query properties. Use useParams to extract route parameters and usePathname to get the current pathname instead.

Applied to files:

  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details. These queries cannot be removed or merged as they serve different use cases in the application.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-09-29T06:02:35.566Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/components/SingleModuleCard.tsx:54-54
Timestamp: 2025-09-29T06:02:35.566Z
Learning: In the Module type from types/mentorship.ts, the experienceLevel field is required (experienceLevel: ExperienceLevelEnum), not optional, so null/undefined checks are not needed when accessing this field.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-07-12T17:14:28.536Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/[programKey]/edit/page.tsx:90-128
Timestamp: 2025-07-12T17:14:28.536Z
Learning: Both ProgramForm (programCard.tsx) and ModuleForm (mainmoduleCard.tsx) components already implement HTML validation using the `required` attribute on form fields. The browser's native validation prevents form submission and displays error messages when required fields are empty, eliminating the need for additional JavaScript validation before GraphQL mutations.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-09-21T17:04:48.154Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2178
File: frontend/src/app/snapshots/[id]/page.tsx:0-0
Timestamp: 2025-09-21T17:04:48.154Z
Learning: User rudransh-shrivastava confirmed that suggested type safety improvements during Apollo Client migration were no longer relevant, reinforcing their preference to keep migration PRs focused on core migration changes rather than additional improvements.

Applied to files:

  • frontend/src/app/members/[memberKey]/page.tsx
📚 Learning: 2025-07-13T11:34:31.823Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/page.tsx:14-14
Timestamp: 2025-07-13T11:34:31.823Z
Learning: In the Next.js frontend mentorship application, there are two distinct types for authentication-related data: ExtendedSession for useSession hook (containing accessToken and user.login properties) and UserRolesData for useUserRoles hook (containing currentUserRoles.roles array). The correct access pattern for GitHub username is `(session as ExtendedSession)?.user?.login`.

Applied to files:

  • frontend/src/app/members/[memberKey]/page.tsx
📚 Learning: 2025-07-08T17:24:36.501Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: backend/apps/mentorship/graphql/mutations/program.py:41-44
Timestamp: 2025-07-08T17:24:36.501Z
Learning: In the mentorship program GraphQL mutations, date validation is handled at the GraphQL schema/node level in the input types (CreateProgramInput, UpdateProgramInput), preventing null values from reaching the mutation logic where date comparisons are performed.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
📚 Learning: 2025-07-13T11:29:25.245Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/src/app/mentorship/programs/page.tsx:59-61
Timestamp: 2025-07-13T11:29:25.245Z
Learning: In Next.js 13+ app router, components with the 'use client' directive run entirely on the client side and don't require window object existence checks or SSR hydration considerations. Direct access to window.location and other browser APIs is safe in client components.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/community/snapshots/[id]/page.tsx
🧬 Code graph analysis (4)
frontend/src/app/chapters/[chapterKey]/page.tsx (3)
frontend/src/types/__generated__/chapterQueries.generated.ts (1)
  • GetChapterDataDocument (19-19)
backend/apps/owasp/api/internal/queries/chapter.py (1)
  • chapter (14-19)
frontend/src/app/global-error.tsx (2)
  • handleAppError (67-91)
  • ErrorDisplay (28-52)
frontend/src/app/mentorship/programs/[programKey]/page.tsx (2)
frontend/src/types/__generated__/programsQueries.generated.ts (1)
  • GetProgramAndModulesDocument (37-37)
frontend/src/app/global-error.tsx (2)
  • handleAppError (67-91)
  • ErrorDisplay (28-52)
frontend/src/app/community/snapshots/[id]/page.tsx (2)
backend/apps/owasp/api/internal/queries/snapshot.py (1)
  • snapshot (14-22)
frontend/src/app/global-error.tsx (2)
  • handleAppError (67-91)
  • ErrorDisplay (28-52)
frontend/src/app/projects/[projectKey]/page.tsx (2)
backend/apps/github/models/repository.py (1)
  • project (162-164)
frontend/src/app/global-error.tsx (2)
  • handleAppError (67-91)
  • ErrorDisplay (28-52)
🔇 Additional comments (12)
frontend/src/app/mentorship/programs/[programKey]/page.tsx (1)

36-44: LGTM! Previous error handling concern resolved.

The explicit check for graphQLRequestError properly distinguishes network/GraphQL errors (500) from actual missing programs (404), addressing the concern raised in previous reviews.

frontend/src/app/chapters/[chapterKey]/page.tsx (2)

16-25: LGTM! Clean refactor to Apollo-native loading state.

The refactor successfully eliminates manual state management by deriving chapter and topContributors directly from the query result and using Apollo's loading property. This simplifies the component and aligns with the PR objective.


37-55: LGTM! Robust error handling for both network errors and missing data.

The dual error handling approach (toast via handleAppError + persistent ErrorDisplay page) provides good UX. The 500/404 distinction is clear, and the !data || !chapter check correctly handles both TypeScript type narrowing and the backend's ability to return null for non-existent chapters.

frontend/src/app/projects/[projectKey]/page.tsx (2)

19-28: LGTM! Clean refactor to use useQuery loading and derived data.

The changes successfully eliminate local useState for loading and data management, deriving everything directly from the Apollo query. This aligns perfectly with the PR objectives and simplifies the component logic.


40-58: Well-structured error handling with 500 and 404 states.

The error handling pattern (toast notification via handleAppError + error page via ErrorDisplay) provides good UX, and the defensive checks for missing data ensure proper 404 handling. This approach is consistent with the pattern established across other pages in this PR.

frontend/src/app/members/[memberKey]/page.tsx (3)

25-38: LGTM! Clean refactor to use useQuery loading state.

The migration from local useState loading to Apollo's useQuery loading property is correctly implemented. Data extraction uses safe optional chaining with appropriate fallbacks, and the destructured isLoading flag properly tracks query state.


84-90: LGTM! Loading state correctly derived from useQuery.

The loading check properly uses isLoading from useQuery to control skeleton display, meeting the PR's objective of removing redundant useState loading tracking.


92-110: LGTM! Comprehensive error and 404 handling.

The error-handling flow correctly covers both failure cases:

  • 500 error: when graphQLRequestError is present
  • 404 error: when query succeeds but returns no data

The pattern of calling handleAppError in the effect (line 42) alongside rendering ErrorDisplay is standard—side effects for logging/telemetry happen separately from error UI rendering.

frontend/src/app/community/snapshots/[id]/page.tsx (4)

4-4: LGTM - useState correctly removed.

The removal of useState from imports aligns perfectly with the PR objective to eliminate local loading state management.


22-30: LGTM - Core refactor correctly implemented.

The refactor successfully replaces local useState loading management with Apollo's loading property. The destructuring pattern is clean, and deriving snapshot from data?.snapshot with optional chaining is the correct approach.


32-36: LGTM - Effect dependencies are correct.

The useEffect dependencies [graphQLRequestError, snapshotKey] are appropriate. When the route parameter changes, Apollo Client automatically refetches and clears the previous error state, so the effect will correctly handle errors for each new snapshot.


94-116: Verify double error handling UX and note scope expansion.

Two observations:

  1. Double error feedback: When graphQLRequestError occurs, the code shows both:

    • A toast notification via handleAppError (lines 33-34)
    • A full-page ErrorDisplay component (lines 98-106)

    This means users see both a dismissible toast AND a persistent error page. While this might be intentional (toast for immediate feedback, error page for stable state), please confirm this UX pattern is desired.

  2. Scope beyond PR objectives: The commit message notes "Add ErrorDisplay for network error" and explicit 500/404 error handling is being introduced. The PR description states the objective is to refactor loading state management with "app behavior and UI loading indicators unchanged except for using useQuery.loading", but adding ErrorDisplay components constitutes new error handling UI not mentioned in the PR description.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 8, 2026

Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

@eyad-hazem-elmorsy thanks for working on this! 👍🏼

I pushed some changes because with using both useQuery and useState many pages were showing a 404 error page for a second or so when loading the page.

@kasya kasya dismissed coderabbitai[bot]’s stale review January 8, 2026 04:55

Already addressed

@kasya kasya added this pull request to the merge queue Jan 8, 2026
Merged via the queue into OWASP:main with commit 5b7217a Jan 8, 2026
27 checks passed
@eyad-hazem-elmorsy eyad-hazem-elmorsy deleted the feature/refactor-usequery-loading branch January 8, 2026 07:22
@eyad-hazem-elmorsy eyad-hazem-elmorsy restored the feature/refactor-usequery-loading branch January 8, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor useQuery loading state usage across pages

3 participants