Skip to content

Conversation

@Rakesh-18112006
Copy link

@Rakesh-18112006 Rakesh-18112006 commented Oct 17, 2025

Proposed change

Resolves #(put the issue number here)

Add the PR description here.

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 17, 2025

Summary by CodeRabbit

  • New Features

    • Added dedicated section components for organizing information: Activity, Contributors, Details, Health Metrics, Lists, Metrics, Modules, Repositories, Sponsors, and Summary sections.
    • Extracted Social Links functionality into a standalone component.
  • Refactor

    • Restructured detail page layout to use composition of modular section components.
  • Tests

    • Added test identifiers to improve test coverage.

Walkthrough

Refactors CardDetailsPage into multiple specialized section components, adds new TypeScript component types and standalone SocialLinks, introduces several new UI sections (Activity, Contributors, Sponsors, Health, Modules, Repositories, Metrics, Lists, Details, Header, Summary), and applies minor whitespace and test attribute tweaks.

Changes

Cohort / File(s) Summary
CardDetailsPage refactor
frontend/src/components/CardDetailsPage.tsx
Replaced monolithic inline rendering with composition of new section components; removed in-file SocialLinks helper and delegated rendering to extracted sections.
New section components
frontend/src/components/HeaderSection.tsx, frontend/src/components/SummarySection.tsx, frontend/src/components/DetailsSection.tsx, frontend/src/components/MetricsSection.tsx, frontend/src/components/ListsSection.tsx, frontend/src/components/ContributorsSection.tsx, frontend/src/components/ActivitySection.tsx, frontend/src/components/RepositoriesSection.tsx, frontend/src/components/ModulesSection.tsx, frontend/src/components/HealthSection.tsx, frontend/src/components/SponsorsSection.tsx
Added 11 new React components implementing discrete parts of the details page UI (header, summary, details, metrics, lists, contributors, activity, repositories, modules, health, sponsors).
Supporting types & SocialLinks
frontend/src/types/components.ts, frontend/src/components/SocialLinks.tsx
Introduced a new TypeScript module with multiple exported interfaces for component props and data shapes; extracted SocialLinks into its own component file.
Minor edits / tests
frontend/__tests__/e2e/components/Footer.spec.ts, frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx, frontend/src/components/AnchorTitle.tsx
Small formatting/whitespace changes in test and page file; added data-testid="anchor-title" to AnchorTitle's inner div.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • arkid15r
  • kasya
  • aramattamara

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive The PR description provided by the author consists entirely of template placeholders without any actual content. It contains the repository's contribution template with unfilled sections such as "Resolves #(put the issue number here)" and "Add the PR description here." While the PR itself is titled "refactor the cardDetailsPage" and the changeset demonstrates a significant refactoring of the CardDetailsPage component with multiple new subcomponents, the description text itself conveys zero meaningful information about what was changed or why. This falls into the category of being extremely vague and generic, as it provides no descriptive terms that communicate anything about the actual changeset. The author should provide a substantive description of the changes in the PR. The description should at minimum reference the specific issue number (issue #2414 based on the branch name), explain the refactoring objectives for CardDetailsPage, and mention the new subcomponents being introduced (such as HeaderSection, SummarySection, DetailsSection, etc.). Completing the checklist items and providing concrete details about the motivation and scope of changes would help reviewers understand the PR's intent.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "refactor the cardDetailsPage" directly and accurately reflects the primary change in the changeset. The raw summary confirms that CardDetailsPage.tsx was refactored by replacing its monolithic inline rendering with a composition of new public subcomponents (HeaderSection, SummarySection, DetailsSection, MetricsSection, etc.), which is exactly what the title conveys. The title is concise, specific, and clearly communicates the main objective of the changes.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • 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.

@sonarqubecloud
Copy link

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

🧹 Nitpick comments (14)
frontend/src/types/components.ts (2)

14-14: Replace any with proper Next.js router type.

The router property uses any, which eliminates type safety. Import and use AppRouterInstance from next/navigation.

Apply this diff:

+import type { AppRouterInstance } from 'next/navigation'
 import { IconDefinition } from '@fortawesome/free-solid-svg-icons'
 import type { ReactElement } from 'react'

 export interface HeaderSectionProps {
   title: string
   type: string
   accessLevel: string
   status: string
   setStatus: (status: string) => void
   canUpdateStatus: boolean
   admins?: Array<{ login: string }>
   description: string
   userLogin?: string
-  router: any
+  router: AppRouterInstance
   isActive: boolean
   healthMetricsData: Array<{ score: number }>
 }

90-97: Consider making activity arrays optional.

The interface requires all activity arrays even when they might be empty or unavailable. Making them optional would provide more flexibility for consumers.

 export interface ActivitySectionProps {
   type: string
-  recentIssues: Issue[]
-  pullRequests: PullRequest[]
-  recentMilestones: Milestone[]
-  recentReleases: Release[]
+  recentIssues?: Issue[]
+  pullRequests?: PullRequest[]
+  recentMilestones?: Milestone[]
+  recentReleases?: Release[]
   showAvatar: boolean
 }
frontend/src/components/AnchorTitle.tsx (1)

46-50: LGTM! Consider documenting the data-anchor-title attribute.

The data-testid attribute improves testability. The data-anchor-title="true" attribute's purpose is unclear—if it's used for styling or DOM queries, consider adding a comment explaining its role.

frontend/src/components/SummarySection.tsx (1)

12-28: LGTM! Minor style note on trailing semicolon.

The conditional rendering logic is clean and appropriate. Note that line 28 has a trailing semicolon after the default export, which is inconsistent with typical ES module style (though not an error).

frontend/src/components/MetricsSection.tsx (1)

45-45: Style note: Trailing semicolon.

The trailing semicolon after the default export is inconsistent with typical ES module style (though not an error).

frontend/src/components/ListsSection.tsx (1)

56-56: Style note: Trailing semicolon.

The trailing semicolon after the default export is inconsistent with typical ES module style.

frontend/src/components/SocialLinks.tsx (1)

14-24: Consider using URL as key instead of array index.

Line 16 uses the array index as the key prop. If the urls array is reordered, React may not efficiently update the DOM. Since URLs should be unique, use the URL itself as the key.

         {urls.map((url, index) => (
           <a
-            key={index}
+            key={url}
             href={url}
             target="_blank"
             rel="noopener noreferrer"

The rel="noopener noreferrer" attributes correctly prevent security vulnerabilities with target="_blank".

frontend/src/components/ModulesSection.tsx (1)

8-13: Narrow type union for type prop (optional).

If this section only renders for programs, tighten the prop for compile‑time guarantees.

-interface ModulesSectionProps {
+interface ModulesSectionProps {
   modules?: Module[]
   accessLevel: string
   admins?: Contributor[]
-  type: string
+  type: 'program'
 }
frontend/src/components/SponsorsSection.tsx (2)

3-8: Strengthen typing of type.

Constrain to the allowed values for better DX and safety.

-interface SponsorsSectionProps {
+type AllowedType = 'chapter' | 'project' | 'repository'
+interface SponsorsSectionProps {
   entityKey?: string
   projectName?: string
   title?: string
-  type: string
+  type: AllowedType
 }

13-17: Provide a default title.

Avoid passing undefined title to SponsorCard.

-      title={projectName || title}
+      title={projectName ?? title ?? 'Sponsors'}
frontend/src/components/RepositoriesSection.tsx (1)

7-10: Strengthen typing of type.

Constrain to known entity kinds to catch mistakes at compile time.

-interface RepositoriesSectionProps {
-  repositories?: RepositoryCardProps[]
-  type: string
-}
+type EntityType = 'project' | 'user' | 'organization'
+interface RepositoriesSectionProps {
+  repositories?: RepositoryCardProps[]
+  type: EntityType
+}
frontend/src/components/DetailsSection.tsx (1)

31-41: Optional: keys by stable ids if available.

Using label as key can collide. If details items have stable ids, prefer them.

frontend/src/components/HeaderSection.tsx (1)

66-70: Clarify handling of undefined isActive.

isActive is optional, so when it's undefined, the condition !isActive evaluates to true, displaying the "Inactive" badge. If the intent is to show "Inactive" only when explicitly false, adjust the check:

-    {!isActive && (
+    {isActive === false && (
       <span className="ml-4 justify-center rounded bg-red-200 px-2 py-1 text-sm text-red-800">
         Inactive
       </span>
     )}

This ensures the badge appears only when isActive is explicitly set to false, not when it's undefined.

frontend/src/components/CardDetailsPage.tsx (1)

110-110: Remove trailing semicolon from export statement for consistency.

The codebase predominantly omits semicolons from export default statements (~20 files without vs. ~10 with). Line 110 in CardDetailsPage.tsx should match the project convention:

export default DetailsCard
📜 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 93d19eb and 407b9ac.

📒 Files selected for processing (17)
  • frontend/__tests__/e2e/components/Footer.spec.ts (1 hunks)
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1 hunks)
  • frontend/src/components/ActivitySection.tsx (1 hunks)
  • frontend/src/components/AnchorTitle.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (2 hunks)
  • frontend/src/components/ContributorsSection.tsx (1 hunks)
  • frontend/src/components/DetailsSection.tsx (1 hunks)
  • frontend/src/components/HeaderSection.tsx (1 hunks)
  • frontend/src/components/HealthSection.tsx (1 hunks)
  • frontend/src/components/ListsSection.tsx (1 hunks)
  • frontend/src/components/MetricsSection.tsx (1 hunks)
  • frontend/src/components/ModulesSection.tsx (1 hunks)
  • frontend/src/components/RepositoriesSection.tsx (1 hunks)
  • frontend/src/components/SocialLinks.tsx (1 hunks)
  • frontend/src/components/SponsorsSection.tsx (1 hunks)
  • frontend/src/components/SummarySection.tsx (1 hunks)
  • frontend/src/types/components.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
PR: OWASP/Nest#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 length check before rendering HealthMetrics: `healthMetricsData.length > 0`. This ensures that when HealthMetrics is rendered, the data array has at least one element, making accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/HealthSection.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
PR: OWASP/Nest#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/components/HealthSection.tsx
🧬 Code graph analysis (12)
frontend/src/components/MetricsSection.tsx (1)
frontend/src/types/components.ts (1)
  • MetricsSectionProps (31-39)
frontend/src/components/ActivitySection.tsx (1)
frontend/src/types/components.ts (5)
  • ActivitySectionProps (90-97)
  • Issue (63-69)
  • PullRequest (71-76)
  • Milestone (78-82)
  • Release (84-88)
frontend/src/components/SocialLinks.tsx (1)
frontend/src/utils/urlIconMappings.ts (1)
  • getSocialIcon (24-50)
frontend/src/components/ListsSection.tsx (1)
frontend/src/types/components.ts (1)
  • ListsSectionProps (41-47)
frontend/src/components/HealthSection.tsx (2)
frontend/src/types/healthMetrics.ts (1)
  • HealthMetricsProps (26-54)
frontend/src/utils/env.client.ts (1)
  • IS_PROJECT_HEALTH_ENABLED (7-8)
frontend/src/components/ModulesSection.tsx (1)
frontend/src/types/components.ts (1)
  • Contributor (49-54)
frontend/src/components/ContributorsSection.tsx (3)
frontend/src/types/components.ts (2)
  • ContributorsSectionProps (56-61)
  • Contributor (49-54)
backend/apps/mentorship/api/internal/nodes/program.py (1)
  • admins (32-34)
backend/apps/mentorship/api/internal/nodes/module.py (1)
  • mentors (29-31)
frontend/src/components/HeaderSection.tsx (4)
frontend/src/types/components.ts (2)
  • HeaderSectionProps (4-17)
  • Contributor (49-54)
frontend/src/types/healthMetrics.ts (1)
  • HealthMetricsProps (26-54)
frontend/src/utils/env.client.ts (1)
  • IS_PROJECT_HEALTH_ENABLED (7-8)
frontend/src/utils/scrollToAnchor.ts (1)
  • scrollToAnchor (1-21)
frontend/src/components/RepositoriesSection.tsx (1)
frontend/src/types/project.ts (1)
  • RepositoryCardProps (52-62)
frontend/src/components/DetailsSection.tsx (1)
frontend/src/types/components.ts (1)
  • DetailsSectionProps (24-29)
frontend/src/components/SummarySection.tsx (1)
frontend/src/types/components.ts (1)
  • SummarySectionProps (19-22)
frontend/src/components/CardDetailsPage.tsx (4)
backend/apps/mentorship/api/internal/nodes/program.py (1)
  • admins (32-34)
frontend/src/types/auth.ts (1)
  • ExtendedSession (8-20)
backend/apps/owasp/api/internal/nodes/project.py (3)
  • languages (73-75)
  • topics (110-112)
  • repositories (100-102)
backend/apps/mentorship/api/internal/nodes/module.py (1)
  • mentors (29-31)
🔇 Additional comments (16)
frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)

13-13: LGTM!

The added whitespace improves readability by separating imports from the component declaration.

frontend/__tests__/e2e/components/Footer.spec.ts (1)

41-41: LGTM!

The whitespace formatting adjustment has no impact on test behavior.

frontend/src/types/components.ts (5)

19-22: LGTM!

The interface clearly defines optional summary content with appropriate types.


24-29: LGTM!

The interface appropriately handles detail items, social links, and geolocation data. The inline geolocation type is acceptable for this use case.


41-47: LGTM!

The interface appropriately handles optional list arrays with proper typing.


49-61: LGTM!

The contributor types are well-structured with appropriate optional fields.


63-88: LGTM!

The activity-related interfaces are well-defined with appropriate required and optional fields.

frontend/src/components/MetricsSection.tsx (1)

7-18: LGTM! Note type inconsistency flagged separately.

The local type definitions are clean. As noted in the review of frontend/src/types/components.ts, ensure these align with the exported MetricsSectionProps interface.

frontend/src/components/ListsSection.tsx (2)

5-11: LGTM!

The interface appropriately defines optional list arrays with proper typing.


31-52: LGTM!

The optional chaining is correctly applied for tags and domains. The isDisabled={true} prop appropriately prevents interaction with these lists.

frontend/src/components/SocialLinks.tsx (1)

4-6: LGTM!

The interface is clean and appropriately typed.

frontend/src/components/SponsorsSection.tsx (1)

16-16: Confirm SponsorCard type mapping for repositories.

You map repository to 'project' for SponsorCard. Is SponsorCard intentionally limited to 'chapter' | 'project'? If it accepts 'repository', pass it through; otherwise a comment explaining the mapping helps future readers.

Would you confirm the accepted values of SponsorCard's type prop and update accordingly if it supports 'repository'?

frontend/src/components/HealthSection.tsx (1)

10-13: LGTM — safe, gated render matches prior pattern.

Renders only when feature flag is on, type is 'project', and data is non‑empty. Matches earlier safety checks around HealthMetrics.

Based on learnings

frontend/src/components/DetailsSection.tsx (1)

15-16: No reconciliation needed - types are correctly aligned.

The review comment conflates the GeoLocation type ({ lat: number; lng: number }) with the Chapter type itself. The Chapter type is a rich domain object with multiple fields including _geoloc?: GeoLocation and geoLocation?: GeoLocation. The DetailsSection component correctly types geolocationData as Chapter[], and ChapterMapWrapper correctly expects geoLocData: Chapter[]. All consumers—ChapterMapWrapper, ChapterMap, and all callers—consistently use Chapter[] with no mismatches.

Likely an incorrect or invalid review comment.

frontend/src/components/CardDetailsPage.tsx (1)

56-104: Excellent modularization!

The refactor successfully decomposes the monolithic rendering into specialized, focused section components. This composition approach significantly improves maintainability, testability, and readability. Each section has clear responsibilities and well-defined props interfaces.

However, ensure the duplicate type definitions in the section components (flagged in other comments) are addressed to maintain consistency across the codebase.

frontend/src/components/ActivitySection.tsx (1)

5-8: No action required—review comment is based on incorrect assumptions.

The script output reveals that types/components.ts and the individual type files export different types, not duplicates. For example, Issue in types/issue.ts includes fields like hint, labels, organizationName, repository, while Issue in types/components.ts defines only title, number, url, createdAt, updatedAt. These are structurally distinct types serving different purposes, so importing from individual files is appropriate and does not represent an inconsistency that requires refactoring.

Likely an incorrect or invalid review comment.

Comment on lines +10 to +17
interface ActivitySectionProps {
type: string
recentIssues?: Issue[]
pullRequests?: PullRequest[]
recentMilestones?: Milestone[]
recentReleases?: Release[]
showAvatar?: boolean
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove duplicate type definition.

ActivitySectionProps is defined locally but also exists in types/components.ts (per relevant snippets). The two definitions differ: the local version marks arrays as optional, while types/components.ts defines them as required. This duplication creates maintenance overhead and type inconsistency risk.

Remove the local interface and import from the shared types file:

+import type { ActivitySectionProps } from 'types/components'
 import type { Issue } from 'types/issue'
 import type { PullRequest } from 'types/pullRequest'
 import type { Milestone } from 'types/milestone'
 import type { Release } from 'types/release'

-interface ActivitySectionProps {
-  type: string
-  recentIssues?: Issue[]
-  pullRequests?: PullRequest[]
-  recentMilestones?: Milestone[]
-  recentReleases?: Release[]
-  showAvatar?: boolean
-}
📝 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
interface ActivitySectionProps {
type: string
recentIssues?: Issue[]
pullRequests?: PullRequest[]
recentMilestones?: Milestone[]
recentReleases?: Release[]
showAvatar?: boolean
}
import type { ActivitySectionProps } from 'types/components'
import type { Issue } from 'types/issue'
import type { PullRequest } from 'types/pullRequest'
import type { Milestone } from 'types/milestone'
import type { Release } from 'types/release'
🤖 Prompt for AI Agents
In frontend/src/components/ActivitySection.tsx around lines 10-17, remove the
local ActivitySectionProps interface declaration and instead import the shared
type from the central types file (e.g. import { ActivitySectionProps } from
'types/components' or the correct relative path); ensure the component uses that
imported type (or Partial<ActivitySectionProps> if you intentionally need
optional arrays) and update any local references so there are no
duplicate/conflicting definitions.

Comment on lines +28 to +52
{(type === 'project' ||
type === 'repository' ||
type === 'user' ||
type === 'organization') && (
<div className="grid-cols-2 gap-4 lg:grid">
<RecentIssues data={recentIssues} showAvatar={showAvatar} />
{type === 'user' ||
type === 'organization' ||
type === 'repository' ||
type === 'project' ? (
<Milestones data={recentMilestones} showAvatar={showAvatar} />
) : (
<RecentReleases data={recentReleases} showAvatar={showAvatar} showSingleColumn={true} />
)}
</div>
)}
{(type === 'project' ||
type === 'repository' ||
type === 'organization' ||
type === 'user') && (
<div className="grid-cols-2 gap-4 lg:grid">
<RecentPullRequests data={pullRequests} showAvatar={showAvatar} />
<RecentReleases data={recentReleases} showAvatar={showAvatar} showSingleColumn={true} />
</div>
)}
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

Fix redundant conditional logic and unreachable code.

The logic contains multiple critical issues:

  1. Redundant outer conditions: Lines 28-31 and 44-47 check identical type values ('project' || 'repository' || 'user' || 'organization'), so both blocks always render together or not at all.

  2. Unreachable else branch: Lines 34-37 check the same four types within the first outer block, making the condition always true. The else branch (lines 39-41) is dead code that can never execute.

This suggests the original intent was different conditional logic for different type combinations.

Clarify the intended rendering logic. If both grids should always display together for these types, simplify to:

-  <>
-    {(type === 'project' ||
-      type === 'repository' ||
-      type === 'user' ||
-      type === 'organization') && (
+  <>
+    {(type === 'project' || type === 'repository' || type === 'user' || type === 'organization') && (
+      <>
       <div className="grid-cols-2 gap-4 lg:grid">
         <RecentIssues data={recentIssues} showAvatar={showAvatar} />
-        {type === 'user' ||
-        type === 'organization' ||
-        type === 'repository' ||
-        type === 'project' ? (
-          <Milestones data={recentMilestones} showAvatar={showAvatar} />
-        ) : (
-          <RecentReleases data={recentReleases} showAvatar={showAvatar} showSingleColumn={true} />
-        )}
+        <Milestones data={recentMilestones} showAvatar={showAvatar} />
       </div>
-    )}
-    {(type === 'project' ||
-      type === 'repository' ||
-      type === 'organization' ||
-      type === 'user') && (
       <div className="grid-cols-2 gap-4 lg:grid">
         <RecentPullRequests data={pullRequests} showAvatar={showAvatar} />
         <RecentReleases data={recentReleases} showAvatar={showAvatar} showSingleColumn={true} />
       </div>
+      </>
     )}
   </>

If different types should show different content, please clarify the requirements.

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

🤖 Prompt for AI Agents
In frontend/src/components/ActivitySection.tsx around lines 28 to 52 there are
redundant identical outer conditions and an unreachable else branch; fix by
consolidating the logic: either (A) if the intent is to render both grids for
the same set of types, replace the duplicated outer checks with a single
conditional for (project|repository|user|organization) and render the two grid
divs (remove the inner else dead branch and always render Milestones in the
first grid), or (B) if the intent was conditional content per type, change the
inner condition to the correct subset (for example only user|organization should
render Milestones and the else should handle project|repository to render
RecentReleases) and keep one outer check that encloses the appropriate grids;
preserve existing component props like showSingleColumn when moving code.

Comment on lines +5 to +10
interface ContributorsSectionProps {
topContributors?: Contributor[]
mentors?: Contributor[]
admins?: Contributor[]
type: string
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove duplicate type definition.

ContributorsSectionProps is defined locally but also exists in types/components.ts. The definitions differ slightly: the local version uses topContributors?: Contributor[] while the shared version uses topContributors: Contributor[] | null. Maintain a single source of truth.

Import from the shared types file:

+import type { ContributorsSectionProps } from 'types/components'
 import { faUsers } from '@fortawesome/free-solid-svg-icons'
 import TopContributorsList from 'components/TopContributorsList'
 import type { Contributor } from 'types/contributor'

-interface ContributorsSectionProps {
-  topContributors?: Contributor[]
-  mentors?: Contributor[]
-  admins?: Contributor[]
-  type: string
-}

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

🤖 Prompt for AI Agents
In frontend/src/components/ContributorsSection.tsx around lines 5 to 10, remove
the duplicate local ContributorsSectionProps interface and instead import the
shared ContributorsSectionProps from frontend/src/types/components.ts; update
the component signature to use the imported type and adjust any code that
assumed optional arrays (e.g. treat topContributors as Contributor[] | null per
shared type, handle nulls or map defensively), and remove the now-unused local
type definition and any related imports to keep a single source of truth.

Comment on lines +12 to +16
details?: { label: string; value: string | JSX.Element }[]
socialLinks?: string[]
type: string
geolocationData?: Chapter[]
}
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

Don’t drop numeric values; align with shared type.

The local DetailsSectionProps narrows value to string | JSX.Element, excluding number. Shared types indicate value can be number. Keep numbers to avoid breaking callers and to support 0 values.

-interface DetailsSectionProps {
-  details?: { label: string; value: string | JSX.Element }[]
+interface DetailsSectionProps {
+  details?: { label: string; value: string | number | JSX.Element }[]
   socialLinks?: string[]
   type: string
-  geolocationData?: Chapter[]
+  geolocationData?: Chapter[]
 }

Alternatively, import and use the shared DetailsSectionProps from types/components.ts for a single source of truth, then adapt rendering accordingly. Based on relevant snippets.

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

🤖 Prompt for AI Agents
frontend/src/components/DetailsSection.tsx around lines 12 to 16: the local
DetailsSectionProps narrows the details.value type to string | JSX.Element which
excludes numeric values (e.g. 0) and conflicts with the shared type; update the
prop type to include number (string | number | JSX.Element) or import and use
the shared DetailsSectionProps from types/components.ts instead, then adjust any
render code to handle numbers (convert to string or render directly) so callers
that pass numeric values continue to work.

Comment on lines +38 to +40
<div key={detail.label} className="pb-1">
<strong>{detail.label}:</strong> {detail?.value || 'Unknown'}
</div>
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

0 should render as 0, not 'Unknown'.

Using || converts 0 to 'Unknown'. Use nullish coalescing instead.

-            <strong>{detail.label}:</strong> {detail?.value || 'Unknown'}
+            <strong>{detail.label}:</strong> {detail?.value ?? 'Unknown'}
📝 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
<div key={detail.label} className="pb-1">
<strong>{detail.label}:</strong> {detail?.value || 'Unknown'}
</div>
<div key={detail.label} className="pb-1">
<strong>{detail.label}:</strong> {detail?.value ?? 'Unknown'}
</div>
🤖 Prompt for AI Agents
In frontend/src/components/DetailsSection.tsx around lines 38 to 40, the
component uses || to fall back to 'Unknown', which treats 0 as falsy and renders
'Unknown'; change the fallback to use the nullish coalescing operator (??) so
that only null or undefined produce 'Unknown' (e.g., replace {detail?.value ||
'Unknown'} with {detail?.value ?? 'Unknown'}).

import SecondaryCard from 'components/SecondaryCard'
import AnchorTitle from 'components/AnchorTitle'
import ModuleCard from 'components/ModuleCard'
import { Contributor } from 'types/contributor'
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

Import Contributor as a type (and from the correct module).

Use a type‑only import to avoid emitting a runtime import. Also, per shared types, Contributor lives in types/components.ts.

-import { Contributor } from 'types/contributor'
+import type { Contributor } from 'types/components'

Adjust the path if your Contributor type is located elsewhere. Based on snippets in types/components.ts. [Based on learnings]

📝 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
import { Contributor } from 'types/contributor'
import type { Contributor } from 'types/components'
🤖 Prompt for AI Agents
In frontend/src/components/ModulesSection.tsx around line 5, the file currently
imports Contributor as a runtime value from 'types/contributor'; change it to a
type-only import from the shared types module (types/components) to avoid
emitting a runtime import. Replace the current import with a type-only import
that imports Contributor from 'types/components' (i.e., use the language's
type-only import form for Contributor and update the module path to
types/components).

Comment on lines +15 to +21
const ModulesSection = ({ modules, accessLevel, admins, type }: ModulesSectionProps) =>
type === 'program' &&
modules.length > 0 && (
<SecondaryCard
icon={faFolderOpen}
title={<AnchorTitle title={modules.length === 1 ? 'Module' : 'Modules'} />}
>
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 | 🔴 Critical

Fix crash when modules is undefined.

modules is optional, but modules.length is accessed unguarded. This will throw when modules is undefined.

Apply a safe default in the params:

-const ModulesSection = ({ modules, accessLevel, admins, type }: ModulesSectionProps) =>
+const ModulesSection = ({ modules = [], accessLevel, admins, type }: ModulesSectionProps) =>
   type === 'program' &&
-  modules.length > 0 && (
+  modules.length > 0 && (
📝 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 ModulesSection = ({ modules, accessLevel, admins, type }: ModulesSectionProps) =>
type === 'program' &&
modules.length > 0 && (
<SecondaryCard
icon={faFolderOpen}
title={<AnchorTitle title={modules.length === 1 ? 'Module' : 'Modules'} />}
>
const ModulesSection = ({ modules = [], accessLevel, admins, type }: ModulesSectionProps) =>
type === 'program' &&
modules.length > 0 && (
<SecondaryCard
icon={faFolderOpen}
title={<AnchorTitle title={modules.length === 1 ? 'Module' : 'Modules'} />}
>
🤖 Prompt for AI Agents
In frontend/src/components/ModulesSection.tsx around lines 15 to 21, the
component reads modules.length without guarding for an undefined modules prop;
make modules default to an empty array in the component parameters (e.g.,
modules = []) so the length check and rendering are safe, and update any related
type if needed to keep props consistent.

Comment on lines +12 to +17
const RepositoriesSection = ({ repositories, type }: RepositoriesSectionProps) =>
(type === 'project' || type === 'user' || type === 'organization') &&
repositories.length > 0 && (
<SecondaryCard icon={faFolderOpen} title={<AnchorTitle title="Repositories" />}>
<RepositoriesCard maxInitialDisplay={4} repositories={repositories} />
</SecondaryCard>
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 | 🔴 Critical

Fix crash when repositories is undefined; simplify type check.

repositories is optional but repositories.length is accessed. Also, the type check can be cleaner.

-const RepositoriesSection = ({ repositories, type }: RepositoriesSectionProps) =>
-  (type === 'project' || type === 'user' || type === 'organization') &&
-  repositories.length > 0 && (
+const RepositoriesSection = ({ repositories = [], type }: RepositoriesSectionProps) =>
+  ['project', 'user', 'organization'].includes(type) &&
+  repositories.length > 0 && (
🤖 Prompt for AI Agents
In frontend/src/components/RepositoriesSection.tsx around lines 12 to 17, the
component currently accesses repositories.length without guarding against
repositories being undefined and uses a verbose type check; update the logic to
first ensure repositories is defined (or default it to an empty array) before
checking length (e.g., use repositories && repositories.length > 0 or default
repositories = repositories || []), and replace the chained equality checks with
a cleaner inclusion check for type (e.g.,
['project','user','organization'].includes(type)); return null when the
conditions aren’t met.

Comment on lines +7 to +10
interface SummarySectionProps {
summary?: string | null
userSummary?: JSX.Element
}
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 inconsistency with exported interface.

The local interface declares summary?: string | null, but the exported SummarySectionProps in frontend/src/types/components.ts (line 20) declares summary?: string without null. This creates a type mismatch.

Choose one approach and align both declarations:

Option 1: Allow null in both places

# In types/components.ts
 export interface SummarySectionProps {
-  summary?: string
+  summary?: string | null
   userSummary?: ReactElement
 }

Option 2: Remove null from component (if summary is never null in practice)

# In SummarySection.tsx
 interface SummarySectionProps {
-  summary?: string | null
+  summary?: string
   userSummary?: JSX.Element
 }
📝 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
interface SummarySectionProps {
summary?: string | null
userSummary?: JSX.Element
}
interface SummarySectionProps {
summary?: string
userSummary?: JSX.Element
}
🤖 Prompt for AI Agents
In frontend/src/components/SummarySection.tsx around lines 7 to 10, the local
interface declares summary?: string | null while the exported
SummarySectionProps in frontend/src/types/components.ts (line 20) declares
summary?: string, causing a type mismatch; pick one approach and make them
consistent: either (Option 1) update the exported type in
frontend/src/types/components.ts to allow null (summary?: string | null) or
(Option 2) remove null from the component interface here (change to summary?:
string) if summary is never null at runtime; apply the chosen change to both
places, run typecheck, and update any call sites or tests that relied on null
accordingly.

Comment on lines +31 to +39
export interface MetricsSectionProps {
stats: Array<{
icon: IconDefinition
pluralizedName: string
unit: string
value: number
}>
type: string
}
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 mismatch with MetricsSection component.

This interface declares all stat fields as required, but MetricsSection.tsx defines Stats with optional pluralizedName? and unit? fields (lines 9-10). This inconsistency could cause type errors.

Align the types by making these fields optional:

 export interface MetricsSectionProps {
   stats: Array<{
     icon: IconDefinition
-    pluralizedName: string
-    unit: string
+    pluralizedName?: string
+    unit?: string
     value: number
   }>
   type: string
 }
📝 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
export interface MetricsSectionProps {
stats: Array<{
icon: IconDefinition
pluralizedName: string
unit: string
value: number
}>
type: string
}
export interface MetricsSectionProps {
stats: Array<{
icon: IconDefinition
pluralizedName?: string
unit?: string
value: number
}>
type: string
}
🤖 Prompt for AI Agents
In frontend/src/types/components.ts around lines 31 to 39, the
MetricsSectionProps.stats type declares pluralizedName and unit as required but
the MetricsSection component defines Stats with pluralizedName? and unit? as
optional; update the MetricsSectionProps.stats inner object to make
pluralizedName and unit optional (e.g., mark them optional in the type) so the
prop type aligns with the component definition and avoids type errors.

@kasya
Copy link
Collaborator

kasya commented Oct 17, 2025

@Rakesh-18112006 Hi! I'm sorry but this issue was not assigned to you. In the OWASP Nest project we do not allow creating PRs if you were not assigned.
I'm going to close this PR

@kasya kasya closed this Oct 17, 2025
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.

2 participants