-
-
Notifications
You must be signed in to change notification settings - Fork 285
refactor the cardDetailsPage #2440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Summary by CodeRabbit
WalkthroughRefactors 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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
|
There was a problem hiding this 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: Replaceanywith proper Next.js router type.The
routerproperty usesany, which eliminates type safety. Import and useAppRouterInstancefromnext/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-testidattribute improves testability. Thedata-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
urlsarray 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 withtarget="_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 undefinedisActive.
isActiveis optional, so when it'sundefined, the condition!isActiveevaluates totrue, displaying the "Inactive" badge. If the intent is to show "Inactive" only when explicitlyfalse, 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
isActiveis explicitly set tofalse, not when it'sundefined.frontend/src/components/CardDetailsPage.tsx (1)
110-110: Remove trailing semicolon from export statement for consistency.The codebase predominantly omits semicolons from
export defaultstatements (~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
📒 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 exportedMetricsSectionPropsinterface.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
tagsanddomains. TheisDisabled={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
GeoLocationtype ({ lat: number; lng: number }) with theChaptertype itself. TheChaptertype is a rich domain object with multiple fields including_geoloc?: GeoLocationandgeoLocation?: GeoLocation. TheDetailsSectioncomponent correctly typesgeolocationDataasChapter[], andChapterMapWrappercorrectly expectsgeoLocData: Chapter[]. All consumers—ChapterMapWrapper,ChapterMap, and all callers—consistently useChapter[]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.tsand the individual type files export different types, not duplicates. For example,Issueintypes/issue.tsincludes fields likehint,labels,organizationName,repository, whileIssueintypes/components.tsdefines onlytitle,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.
| interface ActivitySectionProps { | ||
| type: string | ||
| recentIssues?: Issue[] | ||
| pullRequests?: PullRequest[] | ||
| recentMilestones?: Milestone[] | ||
| recentReleases?: Release[] | ||
| showAvatar?: boolean | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| {(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> | ||
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix redundant conditional logic and unreachable code.
The logic contains multiple critical issues:
-
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. -
Unreachable else branch: Lines 34-37 check the same four types within the first outer block, making the condition always
true. Theelsebranch (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.
| interface ContributorsSectionProps { | ||
| topContributors?: Contributor[] | ||
| mentors?: Contributor[] | ||
| admins?: Contributor[] | ||
| type: string | ||
| } |
There was a problem hiding this comment.
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.
| details?: { label: string; value: string | JSX.Element }[] | ||
| socialLinks?: string[] | ||
| type: string | ||
| geolocationData?: Chapter[] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| <div key={detail.label} className="pb-1"> | ||
| <strong>{detail.label}:</strong> {detail?.value || 'Unknown'} | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| <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' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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).
| const ModulesSection = ({ modules, accessLevel, admins, type }: ModulesSectionProps) => | ||
| type === 'program' && | ||
| modules.length > 0 && ( | ||
| <SecondaryCard | ||
| icon={faFolderOpen} | ||
| title={<AnchorTitle title={modules.length === 1 ? 'Module' : 'Modules'} />} | ||
| > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| 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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| interface SummarySectionProps { | ||
| summary?: string | null | ||
| userSummary?: JSX.Element | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| export interface MetricsSectionProps { | ||
| stats: Array<{ | ||
| icon: IconDefinition | ||
| pluralizedName: string | ||
| unit: string | ||
| value: number | ||
| }> | ||
| type: string | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
|
@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. |



Proposed change
Resolves #(put the issue number here)
Add the PR description here.
Checklist
make check-testlocally; all checks and tests passed.