Skip to content

Restructured and Unified Frontend Types/Interfaces#1568

Merged
arkid15r merged 21 commits intoOWASP:mainfrom
abhayymishraa:feat/types-fix
Jun 13, 2025
Merged

Restructured and Unified Frontend Types/Interfaces#1568
arkid15r merged 21 commits intoOWASP:mainfrom
abhayymishraa:feat/types-fix

Conversation

@abhayymishraa
Copy link
Contributor

Resolves #1477

  • introduced feature to return camelcase instead of snakecase
  • fixed page types
    • project
    • contribute

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 8, 2025

Summary by CodeRabbit

  • New Features
    • Data returned from search endpoints now uses camelCase property names, improving consistency across the app.
  • Refactor
    • All frontend types and mock data updated to use camelCase naming, replacing previous snake_case and Algolia-specific variants.
    • Unified and simplified type definitions for contributors, chapters, committees, organizations, projects, issues, releases, milestones, and pull requests.
    • Improved type-only imports and declaration styles for better maintainability and clarity.
  • Bug Fixes
    • Ensured consistent property naming in all user-facing data and UI components.
  • Tests
    • Added tests to verify correct conversion from snake_case to camelCase.
  • Chores
    • Removed unused utility files and legacy code related to previous naming conventions.

Summary by CodeRabbit

  • New Features

    • Improved consistency across the app by standardizing all data property names to camelCase format.
    • Unified data types for chapters, committees, organizations, projects, users, and contributors, simplifying data handling and display.
    • Enhanced search and filtering features with updated property naming and type consistency.
  • Refactor

    • Replaced multiple similar type declarations with single unified types for better maintainability.
    • Updated all frontend components, utilities, and mock data to use the new camelCase naming convention and unified types.
  • Style

    • Adopted type-only imports throughout the frontend for improved code clarity and build optimization.
  • Bug Fixes

    • Ensured search results and user-facing data display consistent, camelCase property names.
  • Chores

    • Removed unused utility files and redundant type declarations.
    • Updated test data to match new naming conventions.

Walkthrough

This change standardizes and unifies the frontend type and interface definitions, converting interfaces to type aliases, consolidating duplicate types, adopting camelCase naming conventions, and centralizing type declarations. It also updates all usages, imports, and related mock/test data to match the new type structure and naming conventions. Some backend adjustments support frontend data shape expectations.

Changes

Files/Groups Change Summary
frontend/src/types/*.ts (types, interfaces) Converted interfaces to type aliases, unified and centralized types, renamed properties to camelCase, removed duplicates, and updated imports to use type-only imports.
frontend/src/app/**/*.tsx, frontend/src/components/**/*.tsx Updated type imports and annotations to new unified types, adjusted property names to camelCase, and replaced component names/types as needed.
frontend/src/utils/utility.ts Merged and refactored utility functions to use new types and camelCase keys.
frontend/src/server/fetchAlgoliaData.ts, frontend/src/types/algolia.ts Updated types and removed redundant mapping logic to match new frontend expectations.
frontend/__tests__/unit/data/*.ts Updated mock data property names to camelCase to align with new type definitions.
backend/apps/core/api/algolia.py, backend/apps/core/utils/index.py Added recursive camelCase conversion utilities and applied them to Algolia search results to match frontend expectations.
frontend/src/server/utility.ts, frontend/src/utils/logger.ts Deleted redundant utility and logger files made obsolete by the new type/data handling approach.

Assessment against linked issues

Objective (issue #) Addressed Explanation
Standardize usage of type vs interface, with clear conventions (#1477)
Remove duplicate/near-identical types and centralize type declarations (#1477)
Convert all property names to camelCase and unify with API schema expectations (#1477)
Update all usages, imports, and mock/test data to match new types (#1477)
Remove mismatches and redundant mapping logic between backend/frontend (#1477)

Assessment against linked issues: Out-of-scope changes

Code Change (file_path) Explanation
None found

Possibly related PRs

Suggested reviewers

  • kasya
  • arkid15r

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 972626c and 0376bf6.

📒 Files selected for processing (2)
  • backend/apps/common/utils.py (1 hunks)
  • backend/tests/apps/common/utils_test.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/apps/common/utils.py
  • backend/tests/apps/common/utils_test.py
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (javascript-typescript)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch feat/types-fix
  • Post Copyable Unit Tests in 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Nitpick comments (5)
backend/apps/core/utils/index.py (1)

165-181: Improve type annotations and add error handling.

The core logic is correct, but the function could benefit from more precise type annotations and error handling.

-def deep_camelize(obj) -> dict | list:
+def deep_camelize(obj) -> any:
     """Deep camelize.
 
     Args:
-        obj: The object to camelize.
+        obj: The object to camelize (dict, list, or any other type).
 
     Returns:
-        The camelize object.
+        The camelized object with the same structure but camelCase keys.
 
     """
+    if obj is None:
+        return None
+    
     if isinstance(obj, dict):
         return {
             camelize(key.removeprefix("idx_")): deep_camelize(value) for key, value in obj.items()
         }
     if isinstance(obj, list):
         return [deep_camelize(item) for item in obj]
     return obj
frontend/src/types/contributor.ts (1)

1-6: Remove commented-out code.

The commented-out type definition should be removed rather than left in the codebase.

-// export type TopContributors = {
-//   avatarUrl: string
-//   contributionsCount: number
-//   login: string
-//   name: string
-// }
frontend/src/types/issue.ts (1)

1-5: Consider converting IssuesDataType to camelCase for consistency.

The IssuesDataType interface still uses snake_case properties (open_issues_count, total_pages) while IssueType has been converted to camelCase. Consider updating this interface for consistency.

 export interface IssuesDataType {
   issues: IssueType[]
-  open_issues_count: number
-  total_pages: number
+  openIssuesCount: number
+  totalPages: number
 }
frontend/src/types/chapter.ts (1)

27-55: Consider removing commented code after transition.

The commented-out interfaces may be useful during the transition period, but consider removing them once the refactoring is fully complete to keep the codebase clean.

frontend/src/types/project.ts (1)

90-136: Consider removing commented legacy code.

The large blocks of commented code represent the old interface structure and may serve as temporary reference during migration, but they should be removed once the transition is complete to avoid code bloat.

Consider creating a follow-up task to remove these commented interfaces after confirming all consuming code has been successfully migrated to use the new unified types.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b0757a and 83b78fa.

⛔ Files ignored due to path filters (1)
  • backend/poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • backend/apps/core/api/algolia.py (2 hunks)
  • backend/apps/core/utils/index.py (2 hunks)
  • backend/pyproject.toml (1 hunks)
  • frontend/src/app/contribute/page.tsx (2 hunks)
  • frontend/src/app/projects/page.tsx (4 hunks)
  • frontend/src/components/ChapterMap.tsx (5 hunks)
  • frontend/src/components/ChapterMapWrapper.tsx (1 hunks)
  • frontend/src/server/fetchAlgoliaData.ts (1 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/contributor.ts (1 hunks)
  • frontend/src/types/issue.ts (1 hunks)
  • frontend/src/types/project.ts (3 hunks)
  • frontend/src/utils/utility.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
backend/apps/core/api/algolia.py (1)
backend/apps/core/utils/index.py (1)
  • deep_camelize (165-181)
frontend/src/components/ChapterMapWrapper.tsx (1)
frontend/src/types/chapter.ts (1)
  • ChapterType (9-25)
frontend/src/app/projects/page.tsx (3)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (29-139)
frontend/src/types/project.ts (1)
  • ProjectBase (59-79)
frontend/src/utils/data.ts (1)
  • level (111-132)
frontend/src/components/ChapterMap.tsx (2)
frontend/src/types/chapter.ts (1)
  • ChapterType (9-25)
backend/apps/owasp/graphql/queries/chapter.py (1)
  • chapter (14-19)
frontend/src/utils/utility.ts (5)
frontend/src/types/project.ts (2)
  • ProjectBase (59-79)
  • ProjectTypeGraphql (81-88)
frontend/src/types/issue.ts (1)
  • IssueType (7-19)
frontend/src/types/committee.ts (1)
  • CommitteeTypeAlgolia (3-19)
frontend/src/types/icon.ts (1)
  • IconType (1-3)
frontend/src/utils/data.ts (2)
  • Icons (66-107)
  • IconKeys (109-109)
frontend/src/types/project.ts (1)
frontend/src/types/contributor.ts (1)
  • TopContributorsType (8-15)
🪛 Biome (1.9.4)
frontend/src/app/projects/page.tsx

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (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 (23)
backend/pyproject.toml (1)

54-54:

Details

✅ Verification successful

Verify the pyhumps dependency version and security.

The pyhumps dependency is added to support camelCase transformation. Please ensure this version is current and has no known security vulnerabilities.


🌐 Web query:

What is the latest version of pyhumps Python package and are there any known security vulnerabilities in version 3.8.0?

💡 Result:

The latest version of the pyhumps Python package is 3.8.0, released on October 21, 2022. (pypi.org) As of now, there are no known security vulnerabilities associated with this version. (data.safetycli.com)

It's important to note that the pyhumps package is distinct from the similarly named humps package. The humps package has a version 0.2.2, which is outdated and may lack recent updates or security patches. (github.com)

Therefore, if you're looking for a package to convert strings between different cases in Python, pyhumps version 3.8.0 is the recommended choice.

Citations:


pyhumps dependency version verified

We’ve confirmed that pyhumps 3.8.0 (released October 21, 2022) is the latest available version and has no known security vulnerabilities. This dependency is safe and appropriate to include.

backend/apps/core/api/algolia.py (2)

17-17: LGTM: Clean import of the camelCase utility.

The import of deep_camelize aligns with the PR objective to provide camelCase data formatting.


61-65: LGTM: Proper application of camelCase transformation.

The deep_camelize function is correctly applied to the search hits before returning them. This ensures consistent camelCase formatting for frontend consumption while maintaining the existing API structure.

frontend/src/server/fetchAlgoliaData.ts (1)

47-47:

Details

✅ Verification successful

LGTM: Simplified data handling with backend transformation.

Good simplification! The frontend now receives camelCase data directly from the backend, eliminating the need for client-side transformation.

Let me verify the removed imports are no longer used anywhere:


🏁 Script executed:

#!/bin/bash
# Description: Verify that removeIdxPrefix and IndexedObject are no longer used in the codebase
# Expected: No references to these should be found

echo "Checking for remaining usage of removeIdxPrefix..."
rg "removeIdxPrefix" --type ts --type tsx

echo "Checking for remaining usage of IndexedObject..."
rg "IndexedObject" --type ts --type tsx

Length of output: 355


🏁 Script executed:

#!/bin/bash
# Re-run searches without unsupported type flags to verify removal of imports

echo "Searching for removeIdxPrefix usage..."
rg -g '*.ts' -g '*.tsx' 'removeIdxPrefix'

echo "Searching for IndexedObject usage..."
rg -g '*.ts' -g '*.tsx' 'IndexedObject'

Length of output: 644


LGTM: Removed unused imports

Verified that removeIdxPrefix and IndexedObject are no longer referenced in fetchAlgoliaData.ts. Returning hits directly is safe now that the backend provides camelCase data, and no local calls or type usages remain.

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

3-3:

Details

✅ Verification successful

LGTM: Good type unification with ChapterType.

The switch to a unified ChapterType[] simplifies the component interface and aligns with the PR's goal of restructuring frontend types. The ChapterType interface includes both _geoloc and geoLocation properties, ensuring compatibility with different data sources.

Let me verify that ChapterMap can handle the unified ChapterType:

Also applies to: 8-8


🏁 Script executed:

#!/bin/bash
# Description: Check how ChapterMap component handles the geoLocData prop
# Expected: Should be compatible with ChapterType interface

echo "Checking ChapterMap component implementation..."
rg -A 10 -B 5 "geoLocData.*ChapterType" --type ts --type tsx

echo "Checking for any geolocation property usage..."
rg "_geoloc|geoLocation" frontend/src/components/ChapterMap.tsx

Length of output: 752


I’d like to confirm the exact props in ChapterMapWrapper and the full shape of ChapterType before wrapping up:

This will verify that ChapterType includes both _geoloc and geoLocation and that the wrapper passes props correctly.


🏁 Script executed:

#!/bin/bash
# Inspect ChapterMapWrapper usage
echo ">> ChapterMapWrapper geoLocData prop and ChapterMap invocation:"
rg -n "geoLocData" -n frontend/src/components/ChapterMapWrapper.tsx
rg -A5 -B5 "ChapterMap" -n frontend/src/components/ChapterMapWrapper.tsx

# Locate and display ChapterType definition
echo ">> Locating ChapterType definition..."
FILE=$(rg -l "export (interface|type) ChapterType" -n . | head -n1)
echo "Found in: $FILE"
echo "--- Definition snippet ---"
sed -n '1,50p' "$FILE"

Length of output: 2160


Approve unified ChapterType usage in ChapterMapWrapper

The geoLocData: ChapterType[] prop is passed directly to ChapterMap, and the ChapterType definition in frontend/src/types/chapter.ts includes both _geoloc and geoLocation fields. In ChapterMap, all location accesses correctly fall back between _geoloc and geoLocation. No breaking changes detected.

• ChapterMapWrapper (lines 7–13) simply forwards props to ChapterMap
• ChapterType in types/chapter.ts defines optional _geoloc and geoLocation
• ChapterMap uses both properties for latitude/longitude without errors

Everything is compatible—no further changes required.

frontend/src/app/contribute/page.tsx (2)

31-31: LGTM! Correct camelCase conversion for filter parameters.

The conversion from snake_case to camelCase is consistent with the updated IssueType interface.


52-53:

Details

✅ Verification successful

Verify prop name consistency between projectUrl and projectLink.

There's a potential inconsistency: the issue property is projectUrl but the Card component prop is projectLink. Ensure this mapping is correct.


🏁 Script executed:

#!/bin/bash
# Description: Verify the Card component prop names to ensure correct mapping

# Search for Card component definition and its props interface
ast-grep --pattern $'interface $_ {
  $$$
  projectLink$$$
  $$$
}' 

# Also search for any usage of projectUrl vs projectLink
rg -A 3 -B 3 "projectLink|projectUrl" frontend/src/components/Card

Length of output: 206


I couldn’t locate the Card component or its props via the previous search. Let’s pinpoint where Card is defined and confirm its prop names:


🏁 Script executed:

#!/bin/bash
# 1. Find the Card component file
rg -l "export (function|const) Card" -g "*.tsx"

# 2. Search for any occurrences of projectLink
rg -n "projectLink" -g "*.tsx"

# 3. Search for any occurrences of projectUrl
rg -n "projectUrl" -g "*.tsx"

Length of output: 394


Prop mapping is correct: issue.projectUrlprojectLink.
The Card component’s props include projectLink (used for its href), and the page passes issue.projectUrl into that prop as intended. No changes required.

backend/apps/core/utils/index.py (1)

8-8: LGTM! Import correctly added for camelCase functionality.

The camelize import from humps library is properly added to support the new camelCase transformation feature.

frontend/src/types/contributor.ts (1)

8-15: LGTM! Type unification with consistent camelCase naming.

The renaming from TopContributorsTypeGraphql to TopContributorsType and the addition of optional project fields support the type unification effort. The camelCase naming is consistent throughout.

frontend/src/types/issue.ts (1)

8-19: LGTM! Correct camelCase conversion for IssueType interface.

All property name conversions from snake_case to camelCase are correct and consistent. The type definitions remain unchanged, ensuring compatibility.

frontend/src/app/projects/page.tsx (4)

5-5: LGTM: Type import updated correctly.

The import change from ProjectTypeAlgolia to ProjectBase aligns with the type unification effort described in the PR objectives.


25-25: LGTM: Type annotations updated consistently.

The generic type parameter and function parameter both correctly use the new unified ProjectBase type.

Also applies to: 33-33


34-34: LGTM: Property names converted to camelCase.

The property names have been correctly updated from snake_case to camelCase (forks_countforksCount, stars_countstarsCount, contributors_countcontributorsCount, top_contributorstopContributors).

Also applies to: 54-54


50-50:

Details

❓ Verification inconclusive

Verify the key property change.

The React list key was changed from project.objectID to project.key. Ensure that the key property is stable and unique for each project to maintain proper React list rendering behavior.


🏁 Script executed:

#!/bin/bash
# Description: Verify that the key property exists and is unique in the ProjectBase type
ast-grep --pattern 'interface ProjectBase {
  $$$
  key: $_
  $$$
}'

Length of output: 1196


I’d like to confirm where and how project.key is populated to ensure it truly is unique and stable at render time. Let’s inspect the top of frontend/src/app/projects/page.tsx to see the data fetch and mapping logic:


🏁 Script executed:

#!/bin/bash
# Show the fetch/mapping and usage of `key` in page.tsx
sed -n '1,200p' frontend/src/app/projects/page.tsx

Length of output: 2512


Confirm project.key Uniqueness and Stability

We’ve verified that ProjectBase includes a key: string field (used for URLs and list keys) and that page.tsx now consistently uses project.key. Before merge, please ensure:

  • The key value is derived from a stable, unique identifier (e.g. a slug or backend‐generated ID).
  • No two projects can share the same key at indexing or ingest time.

This will guarantee React’s list rendering remains correct.

frontend/src/components/ChapterMap.tsx (3)

3-4: LGTM: Type unification and simplified imports.

The changes correctly adopt the unified ChapterType[] type and remove the unused useMemo import, simplifying the component.

Also applies to: 16-16


51-51: LGTM: Robust coordinate access pattern.

The coordinate access pattern using chapter._geoloc?.lat || chapter.geoLocation?.lat provides good fallback handling for both Algolia (_geoloc) and GraphQL (geoLocation) data sources. This ensures compatibility during the transition period.

Also applies to: 64-66, 83-103


103-103: LGTM: Dependency array correctly updated.

The useEffect dependency array now correctly depends on geoLocData directly instead of the removed intermediate chapters variable.

frontend/src/types/chapter.ts (1)

5-5: LGTM: Type unification with robust geolocation handling.

The new unified ChapterType interface correctly consolidates the previous separate types and uses camelCase naming. The optional _geoloc and geoLocation properties provide good backward compatibility for both Algolia and GraphQL data sources.

Also applies to: 9-25

frontend/src/utils/utility.ts (2)

10-10: LGTM: Type imports and aliases updated consistently.

The imports and type aliases have been correctly updated to use the unified ProjectBase and ProjectTypeGraphql types, removing references to the deprecated types.

Also applies to: 19-19, 37-37


24-28: LGTM: Improved property names and type casting.

The property names have been correctly updated to camelCase ('created_at''createdAt'), and the type casting has been improved to use as unknown as number for safer type assertions.

Also applies to: 43-46

frontend/src/types/project.ts (3)

1-1: LGTM: Import consolidation looks good.

The import has been properly updated to use the unified TopContributorsType instead of separate Algolia and GraphQL variants, which aligns with the type unification goals.


6-6: LGTM: ProjectDataType updated correctly.

The projects field has been properly updated to use ProjectBase[] instead of the removed ProjectTypeAlgolia[], maintaining type safety while using the new unified interface.


59-79: LGTM: Well-structured base interface with consistent camelCase naming.

The ProjectBase interface successfully consolidates common project fields and maintains consistent camelCase naming throughout. The field types are appropriate and the structure is logical.

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

🔭 Outside diff range comments (1)
frontend/src/types/user.ts (1)

3-18: ⚠️ Potential issue

Remove the deprecated user type to avoid confusion.

This old snake_case user type conflicts with the new camelCase UserBase and User types, potentially causing confusion and bugs. Since the PR aims to unify naming conventions to camelCase, this legacy type should be removed.

-export type user = {
-  avatar_url: string
-  bio: string
-  company: string
-  contributions_count: number
-  created_at: number
-  email: string
-  followers_count: number
-  following_count: number
-  key: string
-  location: string
-  login: string
-  name: string
-  objectID: string
-  public_repositories_count: number
-}
🧹 Nitpick comments (1)
frontend/src/app/chapters/page.tsx (1)

103-103: Apply optional chaining for cleaner code.

The static analysis suggestion is valid. The chapters && check can be simplified using optional chaining.

-      {chapters && chapters.filter((chapter) => chapter.isActive).map(renderChapterCard)}
+      {chapters?.filter((chapter) => chapter.isActive).map(renderChapterCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83b78fa and a483358.

📒 Files selected for processing (9)
  • frontend/src/app/chapters/page.tsx (6 hunks)
  • frontend/src/app/committees/page.tsx (3 hunks)
  • frontend/src/app/members/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (3 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/committee.ts (1 hunks)
  • frontend/src/types/organization.ts (1 hunks)
  • frontend/src/types/user.ts (1 hunks)
  • frontend/src/utils/utility.ts (3 hunks)
✅ Files skipped from review due to trivial changes (4)
  • frontend/src/app/members/page.tsx
  • frontend/src/types/organization.ts
  • frontend/src/app/organizations/page.tsx
  • frontend/src/types/committee.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/utils/utility.ts
  • frontend/src/types/chapter.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/app/chapters/page.tsx (5)
frontend/src/types/chapter.ts (1)
  • ChapterType (9-25)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (29-139)
frontend/src/types/algolia.ts (1)
  • AlgoliaResponseType (1-4)
frontend/src/server/fetchAlgoliaData.ts (1)
  • fetchAlgoliaData (6-59)
frontend/src/utils/utility.ts (2)
  • getFilteredIcons (22-35)
  • handleSocialUrls (55-63)
frontend/src/types/user.ts (1)
backend/apps/github/models/user.py (1)
  • User (14-129)
🪛 Biome (1.9.4)
frontend/src/app/chapters/page.tsx

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (10)
frontend/src/app/chapters/page.tsx (3)

8-8: LGTM: Clean type import update.

The import has been correctly updated to use the unified ChapterType interface instead of the previous type, aligning with the restructuring objectives.


15-15: LGTM: Consistent type usage across state and hooks.

All type annotations have been properly updated to use the unified ChapterType, ensuring type consistency across state management, hook generics, and data fetching.

Also applies to: 24-24, 37-37


49-52: LGTM: Property names correctly updated to camelCase.

All property accesses have been properly converted from snake_case to camelCase format (updatedAt, relatedUrls, topContributors), matching the new ChapterType interface definition.

Also applies to: 71-71

frontend/src/types/user.ts (1)

42-61: Excellent design with the generic UserBase interface!

The introduction of UserBase<T> with a generic type parameter for createdAt is a clean approach that allows flexibility for different timestamp formats (number vs string). The camelCase naming convention aligns well with the PR objectives.

frontend/src/app/committees/page.tsx (6)

5-5: LGTM: Type import updated correctly.

The import change from CommitteeTypeAlgolia to CommitteeBase aligns with the type unification objectives.


19-19: LGTM: Type parameter updated consistently.

The generic type parameter correctly reflects the new CommitteeBase type.


24-24: LGTM: Function parameter type updated consistently.

The parameter type correctly uses the new CommitteeBase type for proper type safety.


27-27:

Details

✅ Verification successful

Verify utility function compatibility with camelCase URLs.

The property access change to committee.relatedUrls is consistent with the camelCase naming convention. Ensure that the handleSocialUrls utility function has been updated to handle the new camelCase property structure.


🏁 Script executed:

#!/bin/bash
# Description: Verify that handleSocialUrls utility function handles camelCase property names
# Expected: Function should work with camelCase properties

# Search for handleSocialUrls function implementation
ast-grep --pattern 'function handleSocialUrls($$$) {
  $$$
}'

# Also search for const/export declarations
ast-grep --pattern 'const handleSocialUrls = $$$'
ast-grep --pattern 'export $_ handleSocialUrls = $$$'

Length of output: 787


Utility function signature is compatible with camelCase property access

The handleSocialUrls utility accepts the URLs array directly (its internal parameter name doesn’t affect how you pass committee.relatedUrls), so calling

handleSocialUrls(committee.relatedUrls)

works correctly without any further changes.


25-25:

Details

✅ Verification successful

Verify utility function compatibility with camelCase.

The params array now uses camelCase property names, which is consistent with the refactoring goals. Ensure that the getFilteredIcons utility function has been updated to handle camelCase property names.


🏁 Script executed:

#!/bin/bash
# Description: Verify that getFilteredIcons utility function handles camelCase property names
# Expected: Function should work with camelCase properties like 'updatedAt'

# Search for getFilteredIcons function implementation
ast-grep --pattern 'function getFilteredIcons($$$) {
  $$$
}'

# Also search for const/export declarations
ast-grep --pattern 'const getFilteredIcons = $$$'
ast-grep --pattern 'export $_ getFilteredIcons = $$$'

Length of output: 1158


getFilteredIcons supports camelCase properties

The implementation in frontend/src/utils/utility.ts (lines 22–35) uses dynamic bracket notation (project[key as keyof projectType]) and checks against the Icons map, so passing 'updatedAt' in camelCase works correctly. No changes required.


45-45:

Details

✅ Verification successful

Verify Card component compatibility with camelCase props.

The property access change to committee.topContributors is consistent with the camelCase naming convention. Ensure that the Card component's topContributors prop is properly typed and handled.


🏁 Script executed:

#!/bin/bash
# Description: Verify that Card component handles topContributors prop correctly
# Expected: Component should accept and properly use topContributors prop

# Search for Card component definition and topContributors prop usage
ast-grep --pattern 'interface $_ {
  $$$
  topContributors: $$$
  $$$
}'

# Search for Card component implementation
ast-grep --pattern 'const Card = $$$'
ast-grep --pattern 'function Card($$$) {
  $$$
}'

Length of output: 11969


🏁 Script executed:

#!/bin/bash
# Verify that CardProps includes topContributors
rg "CardProps" -n frontend/src/components/Card.tsx

Length of output: 113


🏁 Script executed:

#!/bin/bash
# Locate CardProps definition to verify topContributors inclusion
rg "export interface CardProps" -n frontend/src/types/card.ts

Length of output: 95


🏁 Script executed:

#!/bin/bash
# Check CardProps definition for topContributors
rg -n "topContributors" frontend/src/types/card.ts

Length of output: 185


Card component topContributors prop is correctly handled

  • The CardProps interface in frontend/src/types/card.ts defines topContributors?: TopContributorsTypeGraphql[] | TopContributorsTypeAlgolia[].
  • The Card component destructures and renders topContributors as expected.

No further changes required.

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

🔭 Outside diff range comments (1)
frontend/src/components/ContributorAvatar.tsx (1)

12-21: ⚠️ Potential issue

Fix type guard logic inconsistency.

The type guard function checks for snake_case properties ('avatar_url' and 'contributions_count') but the actual TopContributorsType uses camelCase properties (avatarUrl and contributionsCount). This will cause the function to always return false, breaking the component's conditional logic.

 const isAlgoliaContributor = (
   contributor: TopContributorsType
 ): contributor is TopContributorsType => {
   return (
     typeof contributor === 'object' &&
     contributor !== null &&
-    'avatar_url' in contributor &&
-    'contributions_count' in contributor
+    'avatarUrl' in contributor &&
+    'contributionsCount' in contributor
   )
 }
♻️ Duplicate comments (1)
frontend/src/types/project.ts (1)

77-77: ⚠️ Potential issue

Remove redundant field definition.

The topContributors field is redundant since ProjectType extends ProjectBase, which already defines this field on line 66.

 export interface ProjectType extends ProjectBase {
   recentIssues: ProjectIssuesType[]
   recentPullRequests: ProjectPullRequestsType[]
   recentReleases: ProjectReleaseType[]
   repositories: RepositoryCardProps[]
-  topContributors: TopContributorsType[]
   recentMilestones: ProjectMilestonesType[]
 }
🧹 Nitpick comments (1)
frontend/src/components/ContributorAvatar.tsx (1)

26-40: Consider simplifying the logic since types are now unified.

Since all contributors now use the unified TopContributorsType, the type guard checks and explicit casting seem unnecessary. The component could be simplified to directly access properties without conditional logic.

Consider this simplified approach:

-  const isAlgolia = isAlgoliaContributor(contributor)
-
-  const avatarUrl = isAlgolia
-    ? contributor.avatarUrl
-    : (contributor as TopContributorsType).avatarUrl
-
-  const contributionsCount = isAlgolia
-    ? contributor.contributionsCount
-    : (contributor as TopContributorsType).contributionsCount
+  const { avatarUrl, contributionsCount, login, name, projectName } = contributor

   const { login, name } = contributor
   const displayName = name || login

-  const repositoryInfo =
-    !isAlgolia && (contributor as TopContributorsType).projectName
-      ? ` in ${(contributor as TopContributorsType).projectName}`
-      : ''
+  const repositoryInfo = projectName ? ` in ${projectName}` : ''

However, if the distinction between Algolia and GraphQL contributors is still meaningful for the avatar URL formatting (&s=60 parameter), please clarify the intended logic.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c1d4b1 and 1e3be20.

📒 Files selected for processing (21)
  • frontend/src/app/chapters/[chapterKey]/page.tsx (2 hunks)
  • frontend/src/app/members/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (3 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (2 hunks)
  • frontend/src/app/snapshots/[id]/page.tsx (3 hunks)
  • frontend/src/components/CardDetailsPage.tsx (3 hunks)
  • frontend/src/components/ContributorAvatar.tsx (2 hunks)
  • frontend/src/components/MultiSearch.tsx (5 hunks)
  • frontend/src/components/TopContributors.tsx (2 hunks)
  • frontend/src/components/UserCard.tsx (2 hunks)
  • frontend/src/server/utility.ts (0 hunks)
  • frontend/src/types/card.ts (5 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/committee.ts (1 hunks)
  • frontend/src/types/contributor.ts (1 hunks)
  • frontend/src/types/home.ts (1 hunks)
  • frontend/src/types/project.ts (6 hunks)
  • frontend/src/types/search.ts (2 hunks)
  • frontend/src/types/snapshot.ts (2 hunks)
  • frontend/src/utils/logger.ts (0 hunks)
  • frontend/src/utils/utility.ts (2 hunks)
💤 Files with no reviewable changes (2)
  • frontend/src/utils/logger.ts
  • frontend/src/server/utility.ts
✅ Files skipped from review due to trivial changes (7)
  • frontend/src/types/home.ts
  • frontend/src/components/UserCard.tsx
  • frontend/src/types/snapshot.ts
  • frontend/src/components/MultiSearch.tsx
  • frontend/src/types/search.ts
  • frontend/src/types/card.ts
  • frontend/src/components/TopContributors.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
  • frontend/src/types/contributor.ts
  • frontend/src/app/members/page.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/organizations/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/app/snapshots/[id]/page.tsx
  • frontend/src/types/committee.ts
  • frontend/src/utils/utility.ts
  • frontend/src/types/chapter.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/components/ContributorAvatar.tsx (1)
frontend/src/types/contributor.ts (1)
  • TopContributorsType (1-8)
frontend/src/types/project.ts (2)
frontend/src/types/contributor.ts (1)
  • TopContributorsType (1-8)
backend/apps/owasp/models/project.py (1)
  • ProjectType (47-63)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (5)
frontend/src/types/project.ts (2)

3-8: Good unification with the new Author type.

The introduction of the reusable Author type effectively consolidates author structures across multiple interfaces, improving consistency and maintainability.


50-70: Well-structured base interface for project types.

The ProjectBase interface provides a clean foundation with standardized camelCase naming and comprehensive project properties. The inheritance pattern with ProjectType extending ProjectBase promotes good code organization.

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

30-30: LGTM: Consistent camelCase conversion.

The parameter rename from is_active to isActive aligns with the PR objective of standardizing frontend naming conventions to camelCase.


55-55: LGTM: Correct usage of renamed parameter.

The conditional check correctly uses the renamed isActive parameter, maintaining the same logic for displaying the "Inactive" badge.


126-126:

Details

✅ Verification successful

Verify type consistency for geolocation data.

The change from wrapping geolocationData in an array to passing it directly suggests the type changed from a single item to an array. Please ensure that:

  1. The geolocationData parameter is now typed as ChapterType[]
  2. The ChapterMapWrapper component properly handles this array type
  3. All callers of this component pass the correct array type

🏁 Script executed:

#!/bin/bash
# Verify the type definitions and usage are consistent
echo "Checking DetailsCardProps interface definition:"
rg -A 10 "interface DetailsCardProps" --type ts --type tsx

echo -e "\nChecking ChapterMapWrapper component props:"
rg -A 5 "geoLocData.*:" --type ts --type tsx

echo -e "\nChecking how DetailsCard is called with geolocationData:"
rg -A 3 -B 3 "geolocationData.*=" --type ts --type tsx

Length of output: 585


I’ll broaden the search to eliminate the file-type filters and locate the relevant definitions and usages across all .ts/.tsx files.


🏁 Script executed:

#!/bin/bash
# Search for DetailsCardProps interface definition
echo "=== DetailsCardProps ==="
rg -A10 "interface DetailsCardProps" -g "*.ts" -g "*.tsx"

# Search for ChapterMapWrapper component and its prop types
echo "=== ChapterMapWrapper ==="
rg -A10 "ChapterMapWrapper" -g "*.ts" -g "*.tsx"

# Search for geoLocData usages in JSX/TSX
echo "=== geoLocData ==="
rg -A5 "geoLocData" -g "*.ts" -g "*.tsx"

# Search for geolocationData usages (calls and definitions)
echo "=== geolocationData ==="
rg -A5 "geolocationData" -g "*.ts" -g "*.tsx"

Length of output: 16264


Type consistency for geolocationData confirmed.

The DetailsCardProps interface defines
geolocationData?: ChapterType[]
and ChapterMapWrapper expects geoLocData: ChapterType[]. In CardDetailsPage.tsx we only render the wrapper when geolocationData is non-null (and thus an array), and all callers supply ChapterType[] ([chapter], geoLocData, snapshot.newChapters). No mismatches detected.

@abhayymishraa abhayymishraa marked this pull request as ready for review June 8, 2025 22:15
Copy link
Contributor

@aramattamara aramattamara left a comment

Choose a reason for hiding this comment

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

Thanks for working on this. I left some comments, please take a look

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

It doesn't look like you addressed the main concerns described in the issue:

  • inconsistent usage of type vs interface
  • duplicate or near-identical types

I partially updated naming by removing Type suffix from names. Please do the same for the rest of types/interfaces.

Please also handle the bot's comment (either implement or mark as resolved).

strawberry-graphql = {extras = ["django"], version = "^0.270.1"}
thefuzz = "^0.22.1"
strawberry-graphql-django = "^0.59.1"
pyhumps = "^3.8.0"
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not the best option here. While I strongly believe in code reuse it's just not worth it to install a new package for string conversion. Please add a new method with tests similar to what we have here.

Moreover, the package hasn't been updated for a while.

response = client.search(search_method_params={"requests": [search_params]})
search_result = response.results[0].to_dict()

cleaned_search_result = deep_camelize(search_result["hits"])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please don't introduce variables used just once.

RepositoryCardProps,
} from 'types/project'
import type { ItemCardPullRequests, UserDetailsProps } from 'types/user'
import type { ItemCardPullRequests, UserDetails } from 'types/user'
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we update all type import w/ import type?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we want to keep GitHub related types in user types file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, i mean it's the page i think we can change it to member or should i creatre it like githubUser , but from my pov User is fine

Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here -- a lot of GitHub related entity types tied to Project... prefix.
How is it different from just Issue vs ProjectIssuesType (why plural name btw?)

login: string
name: string
}
author: Author
Copy link
Collaborator

Choose a reason for hiding this comment

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

How is this type different from types::user::Release?

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

🔭 Outside diff range comments (2)
frontend/src/app/chapters/page.tsx (2)

29-46: 🛠️ Refactor suggestion

Add error handling & abort-on-unmount to avoid unhandled promise rejections

fetchAlgoliaData is awaited without a try / catch, so any network or parsing error will bubble up to the browser console and potentially leave the component in an inconsistent state.
Additionally, if currentPage changes quickly (or the component unmounts) the setGeoLocData call from an outdated request can land after a newer one, causing visual flicker or React “state update on unmounted component” warnings.

   useEffect(() => {
-    const fetchData = async () => {
-      const searchParams = {
-        indexName: 'chapters',
-        query: '',
-        currentPage,
-        hitsPerPage: currentPage === 1 ? 1000 : 25,
-      }
-      const data: AlgoliaResponse<Chapter> = await fetchAlgoliaData(
-        searchParams.indexName,
-        searchParams.query,
-        searchParams.currentPage,
-        searchParams.hitsPerPage
-      )
-      setGeoLocData(data.hits)
-    }
-    fetchData()
+    const abortController = new AbortController()
+    const fetchData = async () => {
+      try {
+        const searchParams = {
+          indexName: 'chapters',
+          query: '',
+          currentPage,
+          hitsPerPage: currentPage === 1 ? 1000 : 25,
+        }
+        const data: AlgoliaResponse<Chapter> = await fetchAlgoliaData(
+          searchParams.indexName,
+          searchParams.query,
+          searchParams.currentPage,
+          searchParams.hitsPerPage,
+          abortController.signal      // pass signal if fetchAlgoliaData supports it
+        )
+        setGeoLocData(data.hits)
+      } catch (err) {
+        if (err.name !== 'AbortError') {
+          /* eslint-disable-next-line no-console */
+          console.error('Failed to fetch chapter geo data', err)
+        }
+      }
+    }
+    fetchData()
+    return () => abortController.abort()
   }, [currentPage])

This guards against race conditions and makes the component resilient to failed requests.


58-62: ⚠️ Potential issue

Bug: onclick key & trailing space will break the button icon

  1. The Card component (and common React conventions) expect the handler to be named onClick, not onclick. Using the wrong case will silently drop the callback.
  2. The icon string has a trailing space, which prevents Font Awesome from matching the class name.
-  const submitButton = {
-    label: 'View Details',
-    icon: <FontAwesomeIconWrapper icon="fa-solid fa-right-to-bracket " />,
-    onclick: handleButtonClick,
-  }
+  const submitButton = {
+    label: 'View Details',
+    icon: <FontAwesomeIconWrapper icon="fa-solid fa-right-to-bracket" />,
+    onClick: handleButtonClick,
+  }

Please ensure the Card props also use the corrected onClick key.

🧹 Nitpick comments (1)
frontend/src/app/chapters/page.tsx (1)

103-103: Prefer optional chaining for cleaner null-safety

Static analysis is right: chapters can be undefined until the first search returns. Optional chaining removes the need for the && short-circuit and is more idiomatic.

-      {chapters && chapters.filter((chapter) => chapter.isActive).map(renderChapterCard)}
+      {chapters?.filter((chapter) => chapter.isActive).map(renderChapterCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9a5d68 and f033e95.

⛔ Files ignored due to path filters (1)
  • backend/poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (29)
  • backend/apps/core/api/algolia.py (2 hunks)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/app/chapters/[chapterKey]/page.tsx (2 hunks)
  • frontend/src/app/chapters/page.tsx (6 hunks)
  • frontend/src/app/committees/[committeeKey]/page.tsx (1 hunks)
  • frontend/src/app/committees/page.tsx (3 hunks)
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx (1 hunks)
  • frontend/src/app/page.tsx (5 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (2 hunks)
  • frontend/src/app/snapshots/[id]/page.tsx (3 hunks)
  • frontend/src/components/CardDetailsPage.tsx (4 hunks)
  • frontend/src/components/ChapterMap.tsx (5 hunks)
  • frontend/src/components/ChapterMapWrapper.tsx (1 hunks)
  • frontend/src/components/ContributorAvatar.tsx (2 hunks)
  • frontend/src/components/ItemCardList.tsx (2 hunks)
  • frontend/src/components/MultiSearch.tsx (5 hunks)
  • frontend/src/components/TopContributorsList.tsx (2 hunks)
  • frontend/src/server/fetchAlgoliaData.ts (3 hunks)
  • frontend/src/types/algolia.ts (1 hunks)
  • frontend/src/types/card.ts (5 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/committee.ts (1 hunks)
  • frontend/src/types/contributor.ts (1 hunks)
  • frontend/src/types/home.ts (1 hunks)
  • frontend/src/types/project.ts (4 hunks)
  • frontend/src/types/search.ts (2 hunks)
  • frontend/src/types/snapshot.ts (2 hunks)
  • frontend/src/types/user.ts (1 hunks)
  • frontend/src/utils/utility.ts (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • frontend/src/components/TopContributorsList.tsx
  • frontend/src/components/ItemCardList.tsx
🚧 Files skipped from review as they are similar to previous changes (26)
  • frontend/src/app/about/page.tsx
  • frontend/src/types/home.ts
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx
  • frontend/src/types/contributor.ts
  • backend/apps/core/api/algolia.py
  • frontend/src/server/fetchAlgoliaData.ts
  • frontend/src/types/snapshot.ts
  • frontend/src/app/page.tsx
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/committees/page.tsx
  • frontend/src/app/snapshots/[id]/page.tsx
  • frontend/src/components/ChapterMapWrapper.tsx
  • frontend/src/types/committee.ts
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/components/CardDetailsPage.tsx
  • frontend/src/types/user.ts
  • frontend/src/types/search.ts
  • frontend/src/components/MultiSearch.tsx
  • frontend/src/components/ContributorAvatar.tsx
  • frontend/src/components/ChapterMap.tsx
  • frontend/src/types/card.ts
  • frontend/src/utils/utility.ts
  • frontend/src/types/algolia.ts
  • frontend/src/types/chapter.ts
  • frontend/src/types/project.ts
🧰 Additional context used
🪛 Biome (1.9.4)
frontend/src/app/chapters/page.tsx

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (javascript-typescript)

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

🔭 Outside diff range comments (6)
frontend/src/components/RepositoriesCard.tsx (2)

17-33: ⚠️ Potential issue

repositories can now be undefined – component will crash at runtime

RepositoriesCardProps.repositories was made optional in the new type definition, but the component still dereferences it immediately (slice, length, map).
If a caller omits the prop the page will throw before React can show an error boundary.

Suggested minimal fix:

-const RepositoriesCard: React.FC<RepositoriesCardProps> = ({ repositories }) => {
+const RepositoriesCard: React.FC<RepositoriesCardProps> = ({ repositories = [] }) => {

Optionally short-circuit the render for an empty list:

if (!repositories.length) return null

Protecting against undefined keeps the component aligned with the updated type contract.

Also applies to: 29-33


25-27: 🛠️ Refactor suggestion

Use a stable key instead of the array index

Using the array index (key={index}) prevents React from accurately tracking list items after re-ordering or filtering and can lead to subtle UI bugs. The repository object already exposes a unique identifier (repository.key), so prefer that:

- {displayedRepositories.map((repository, index) => {
-   return <RepositoryItem key={index} details={repository} />
- })}
+ {displayedRepositories.map((repository) => (
+   <RepositoryItem key={repository.key} details={repository} />
+ ))}

This is a low-effort improvement that increases render stability.

frontend/src/components/RecentReleases.tsx (3)

40-42: 🛠️ Refactor suggestion

Use a stable, domain-specific key instead of the loop index

index is re-created on every re-render, defeating React’s key-based diffing and risking subtle UI bugs. Prefer a property that is guaranteed unique and stable, e.g. item.tagName or item.url.

-          {data.map((item, index) => (
-            <div key={index} className="mb-4 w-full …">
+          {data.map((item) => (
+            <div key={item.tagName ?? item.url} className="mb-4 w-full …">

57-63: ⚠️ Potential issue

Empty string passed to Image.src can crash Next 13+

next/image throws when src is an empty string. Provide a fallback placeholder or render the <Image> conditionally.

- <Image … src={item?.author?.avatarUrl || ''} … />
+ {item?.author?.avatarUrl && (
+   <Image … src={item.author.avatarUrl} … />
+ )}

85-94: 🛠️ Refactor suggestion

Guard against undefined path segments

If organizationName is undefined the URL becomes /organizations/undefined/repositories/ which breaks navigation.

-onClick={() =>
-  router.push(
-    `/organizations/${item?.organizationName}/repositories/${item.repositoryName || ''}`
-  )
-}
+onClick={() => {
+  if (item.organizationName && item.repositoryName) {
+    router.push(
+      `/organizations/${item.organizationName}/repositories/${item.repositoryName}`
+    )
+  }
+}}
backend/apps/core/utils/index.py (1)

183-194: ⚠️ Potential issue

camelize does not actually produce camelCase

"idx_created_at""Createdat" instead of "createdAt". Consider splitting on '_', lower-casing the first token, capitalising the rest, and then joining.

-def camelize(key: str) -> str:
-    """Camelize a string."""
-    return key.replace("_", "").title()
+import re
+
+def camelize(key: str) -> str:
+    """Convert snake_case to camelCase (e.g., created_at → createdAt)."""
+    parts = re.sub(r"[_\s]+", "_", key).split("_")
+    return parts[0].lower() + "".join(word.title() for word in parts[1:])
♻️ Duplicate comments (1)
frontend/src/app/projects/page.tsx (1)

81-81: Duplicate: optional chaining still missing
Same issue previously raised – please apply the change.

-      {projects && projects.filter((project) => project.isActive).map(renderProjectCard)}
+      {projects?.filter((project) => project.isActive).map(renderProjectCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧹 Nitpick comments (5)
frontend/src/components/SortBy.tsx (1)

5-5: Consistent use of import type

Nice catch converting this to a type-only import; keeps emitted JS lean and matches the rest of the refactor.
You might consider grouping all import type statements together (e.g., after runtime imports) for readability, but that’s optional.

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

8-14: Consider renaming Snapshots to singular Snapshot for clarity

Throughout the file Snapshots is used as the type of a single element (Snapshots[], function arg, etc.). A plural name for a singular entity is counter-intuitive and can trip up new contributors.

-import type { Snapshots } from 'types/snapshot'
+import type { Snapshot } from 'types/snapshot'

-const [snapshots, setSnapshots] = useState<Snapshots[] | null>(null)
+const [snapshots, setSnapshots] = useState<Snapshot[] | null>(null)

-const handleButtonClick = (snapshot: Snapshots) => {
+const handleButtonClick = (snapshot: Snapshot) => {

-const renderSnapshotCard = (snapshot: Snapshots) => {
+const renderSnapshotCard = (snapshot: Snapshot) => {

-            snapshots.map((snapshot: Snapshots) => (
+            snapshots.map((snapshot: Snapshot) => (

Refactor now or add a TODO before this naming pattern spreads further.

Also applies to: 38-43, 71-73

backend/apps/core/utils/index.py (1)

164-180: deep_camelize return annotation is inaccurate

The function may return primitives (e.g. str, int) when the input is not a dict/list. Update the annotation or wrap in typing.Any.

-def deep_camelize(obj) -> dict | list:
+from typing import Any
+
+def deep_camelize(obj: Any) -> Any:
frontend/src/app/chapters/page.tsx (1)

103-103: Apply optional chaining to silence undefined checks

Static analysis flagged this; optional chaining is safer and reads better.

-      {chapters && chapters.filter((chapter) => chapter.isActive).map(renderChapterCard)}
+      {chapters?.filter((chapter) => chapter.isActive).map(renderChapterCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

40-45: Inconsistent local variable naming

SubmitButton here starts with an upper-case letter whereas the same pattern in ChaptersPage uses submitButton. Consistent camelCase for variables prevents confusion with React components.

-  const SubmitButton = {
+  const submitButton = {-    <Card
-      button={SubmitButton}
+    <Card
+      button={submitButton}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f033e95 and d7f2a8c.

⛔ Files ignored due to path filters (1)
  • backend/poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (61)
  • backend/apps/core/utils/index.py (1 hunks)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/app/chapters/[chapterKey]/page.tsx (2 hunks)
  • frontend/src/app/chapters/page.tsx (6 hunks)
  • frontend/src/app/committees/[committeeKey]/page.tsx (1 hunks)
  • frontend/src/app/contribute/page.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (1 hunks)
  • frontend/src/app/members/page.tsx (2 hunks)
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (3 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (2 hunks)
  • frontend/src/app/projects/page.tsx (4 hunks)
  • frontend/src/app/snapshots/[id]/page.tsx (3 hunks)
  • frontend/src/app/snapshots/page.tsx (1 hunks)
  • frontend/src/components/Card.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (5 hunks)
  • frontend/src/components/ChapterMap.tsx (5 hunks)
  • frontend/src/components/ChapterMapWrapper.tsx (1 hunks)
  • frontend/src/components/ContributorAvatar.tsx (2 hunks)
  • frontend/src/components/DisplayIcon.tsx (1 hunks)
  • frontend/src/components/Footer.tsx (1 hunks)
  • frontend/src/components/InfoBlock.tsx (1 hunks)
  • frontend/src/components/ItemCardList.tsx (2 hunks)
  • frontend/src/components/LeadersList.tsx (1 hunks)
  • frontend/src/components/LogoCarousel.tsx (1 hunks)
  • frontend/src/components/Milestones.tsx (1 hunks)
  • frontend/src/components/Modal.tsx (1 hunks)
  • frontend/src/components/MultiSearch.tsx (5 hunks)
  • frontend/src/components/NavButton.tsx (1 hunks)
  • frontend/src/components/NavDropDown.tsx (1 hunks)
  • frontend/src/components/RecentIssues.tsx (1 hunks)
  • frontend/src/components/RecentPullRequests.tsx (1 hunks)
  • frontend/src/components/RecentReleases.tsx (1 hunks)
  • frontend/src/components/RepositoriesCard.tsx (1 hunks)
  • frontend/src/components/SnapshotCard.tsx (1 hunks)
  • frontend/src/components/SortBy.tsx (1 hunks)
  • frontend/src/components/TopContributorsList.tsx (2 hunks)
  • frontend/src/components/UserCard.tsx (3 hunks)
  • frontend/src/components/skeletons/Card.tsx (1 hunks)
  • frontend/src/components/skeletons/UserCard.tsx (1 hunks)
  • frontend/src/server/fetchAlgoliaData.ts (3 hunks)
  • frontend/src/types/algolia.ts (1 hunks)
  • frontend/src/types/button.ts (2 hunks)
  • frontend/src/types/card.ts (4 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/committee.ts (1 hunks)
  • frontend/src/types/home.ts (1 hunks)
  • frontend/src/types/issue.ts (1 hunks)
  • frontend/src/types/milestone.ts (1 hunks)
  • frontend/src/types/modal.ts (1 hunks)
  • frontend/src/types/organization.ts (1 hunks)
  • frontend/src/types/project.ts (2 hunks)
  • frontend/src/types/pullRequest.ts (1 hunks)
  • frontend/src/types/release.ts (1 hunks)
  • frontend/src/types/search.ts (1 hunks)
  • frontend/src/types/skeleton.ts (2 hunks)
  • frontend/src/types/snapshot.ts (1 hunks)
  • frontend/src/types/sortBy.ts (1 hunks)
  • frontend/src/types/user.ts (1 hunks)
  • frontend/src/utils/constants.ts (1 hunks)
  • frontend/src/utils/utility.ts (2 hunks)
✅ Files skipped from review due to trivial changes (21)
  • frontend/src/utils/constants.ts
  • frontend/src/components/LogoCarousel.tsx
  • frontend/src/components/skeletons/UserCard.tsx
  • frontend/src/components/Card.tsx
  • frontend/src/components/LeadersList.tsx
  • frontend/src/components/skeletons/Card.tsx
  • frontend/src/components/SnapshotCard.tsx
  • frontend/src/components/NavDropDown.tsx
  • frontend/src/components/Modal.tsx
  • frontend/src/components/InfoBlock.tsx
  • frontend/src/types/sortBy.ts
  • frontend/src/components/Footer.tsx
  • frontend/src/types/skeleton.ts
  • frontend/src/types/release.ts
  • frontend/src/components/NavButton.tsx
  • frontend/src/components/RecentPullRequests.tsx
  • frontend/src/types/button.ts
  • frontend/src/types/pullRequest.ts
  • frontend/src/components/RecentIssues.tsx
  • frontend/src/types/milestone.ts
  • frontend/src/components/Milestones.tsx
🚧 Files skipped from review as they are similar to previous changes (30)
  • frontend/src/app/members/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/components/TopContributorsList.tsx
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx
  • frontend/src/components/ChapterMapWrapper.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/types/algolia.ts
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/about/page.tsx
  • frontend/src/components/UserCard.tsx
  • frontend/src/app/snapshots/[id]/page.tsx
  • frontend/src/app/contribute/page.tsx
  • frontend/src/components/ContributorAvatar.tsx
  • frontend/src/components/ItemCardList.tsx
  • frontend/src/app/organizations/page.tsx
  • frontend/src/components/CardDetailsPage.tsx
  • frontend/src/types/organization.ts
  • frontend/src/types/committee.ts
  • frontend/src/components/ChapterMap.tsx
  • frontend/src/components/MultiSearch.tsx
  • frontend/src/types/issue.ts
  • frontend/src/server/fetchAlgoliaData.ts
  • frontend/src/types/search.ts
  • frontend/src/types/chapter.ts
  • frontend/src/utils/utility.ts
  • frontend/src/types/snapshot.ts
  • frontend/src/types/home.ts
  • frontend/src/types/project.ts
  • frontend/src/types/card.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
frontend/src/components/RecentReleases.tsx (1)
frontend/src/types/release.ts (1)
  • ReleaseType (3-13)
frontend/src/types/user.ts (4)
frontend/src/types/issue.ts (1)
  • IssueType (7-19)
frontend/src/types/release.ts (1)
  • ReleaseType (3-13)
frontend/src/types/project.ts (1)
  • RepositoryCardProps (49-59)
backend/apps/github/models/user.py (1)
  • User (14-129)
frontend/src/app/projects/page.tsx (3)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (29-139)
frontend/src/types/project.ts (1)
  • ProjectType (16-43)
frontend/src/utils/data.ts (1)
  • level (111-132)
🪛 Biome (1.9.4)
frontend/src/app/chapters/page.tsx

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/app/projects/page.tsx

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (4)
frontend/src/components/DisplayIcon.tsx (1)

4-4: Type-only import is a good move

Switching to import type makes the intent clear and helps TS/webpack eliminate dead code. Looks good.

frontend/src/types/modal.ts (2)

2-2: 👍 Good move to a type-only import

Using import type keeps the compiled JS lean by stripping this import at runtime—exactly what we want for purely-type dependencies.


4-13:

Details

✅ Verification successful

Check downstream code that previously used extends ModalProps

Switching from an interface to a type alias prevents declaration merging and disallows interface Foo extends ModalProps {}. If any component still relies on that syntax, the build will break.

Run this quick scan to ensure no remaining extends ModalProps usages survive:

If the command returns nothing, you’re clear. Otherwise refactor those interfaces to type Foo = ModalProps & { … }.


🏁 Script executed:

#!/bin/bash
# Locate interface extensions that would now fail
rg -n $'interface\\s+\\w+\\s+extends\\s+ModalProps' --type ts --type tsx

Length of output: 97


Let’s broaden the file filter so rg picks up both .ts and .tsx files:


🏁 Script executed:

#!/bin/bash
# Re-scan all TS/TSX files for any interface extending ModalProps
rg -n "interface\s+\w+\s+extends\s+ModalProps" -g '*.ts' -g '*.tsx'

Length of output: 69


No remaining interface … extends ModalProps usages detected
I ran:

rg -n "interface\s+\w+\s+extends\s+ModalProps" -g '*.ts' -g '*.tsx'

and found no matches. Switching from an interface to a type alias is safe—no downstream code relies on declaration merging for ModalProps.

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

8-8: Good move switching to a type-only import

Changing the import to import type makes the intent explicit and helps avoid tree-shaking / bundler confusion. 👍

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

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

10-15: Consider strong typing for number (numeric) and clarify units for timestamps

  1. GitHub issue numbers are integers; modelling them as string loses type safety and forces casts at call-sites.
  2. createdAt / updatedAt are typed as number, but it is unclear if this is a Unix epoch (seconds? ms?) or an ISO string already parsed to Date.getTime(). Ambiguity fuels bugs.

Suggested tweak:

-  createdAt: number
+  /** Unix epoch milliseconds.  Use Date.toISOString() when serialising */
+  createdAt: number

-  number?: string
+  number?: number

Applying this early prevents a cascade of parseInt / Number() fixes later.


18-21: Nit: rename repositoryLanguages to languages for cohesion

Every other field avoids data-source prefixes (projectName, organizationName), but repositoryLanguages keeps the origin baked in. languages (or repoLanguages) would keep the shape tight and future-proof if the same type is reused for non-repository contexts.

Not blocking, but worth considering before the API freezes.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7f2a8c and 7b39bea.

📒 Files selected for processing (3)
  • frontend/src/types/issue.ts (1 hunks)
  • frontend/src/types/release.ts (1 hunks)
  • frontend/src/types/user.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/types/user.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/types/release.ts (1)
frontend/src/types/user.ts (2)
  • User (32-32)
  • RepositoryDetails (5-8)
frontend/src/types/issue.ts (1)
frontend/src/types/user.ts (2)
  • User (32-32)
  • RepositoryDetails (5-8)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (2)
frontend/src/types/release.ts (1)

10-12: Required repositoryName when repository is optional may lead to inconsistent state

repository is optional but repositoryName is mandatory. When repository is undefined, it’s unclear what repositoryName should represent (empty string? orphaned data?). Either:

  1. Make both fields optional and document fallback behaviour, or
  2. Always require repository and derive its key/ownerKey instead of duplicating a name string.

Consider tightening the model to avoid partial data bugs.

frontend/src/types/issue.ts (1)

1-1: Verify path alias types/user exists in tsconfig

The import relies on a path alias (types/user). If the alias is missing or mis-configured, tsc/Vite will fail outside the IDE.

Ask yourself:

  • Is "paths": { "types/*": ["src/types/*"] } present in tsconfig.base.json?
  • Are Jest/ESLint aliases aligned?

If not, update the config or use a relative path.

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

♻️ Duplicate comments (2)
frontend/src/app/projects/page.tsx (1)

81-81: ⚠️ Potential issue

Optional-chain the projects collection (repeat of previous review)

The unsafe projects && … pattern survived the last review. Swap it for optional chaining so the component renders gracefully when the query hasn’t returned yet:

-      {projects && projects.filter((project) => project.isActive).map(renderProjectCard)}
+      {projects?.filter((project) => project.isActive).map(renderProjectCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/types/issue.ts (1)

1-19: 💡 Verification agent

🧩 Analysis chain

Left-over snake_case keys could still exist in the codebase

Previous reviews flagged open_issues_count/total_pages under
IssuesDataType. This file deletes that type, but we need to be sure all
references were removed or renamed.

Run the script to confirm no lingering snake_case usages:


🏁 Script executed:

#!/bin/bash
# Fail if any snake_case pagination keys remain
set -e
patterns=("open_issues_count" "total_pages")
for p in "${patterns[@]}"; do
  if rg -n "${p}" frontend | grep -q .; then
    echo "❌ Found residual usage of ${p}"
    exit 1
  fi
done
echo "✅ No residual snake_case pagination keys"

Length of output: 293


🏁 Script executed:

#!/bin/bash
# Locate all occurrences of total_pages in the frontend directory
rg -n "total_pages" frontend

Length of output: 104


Update remaining snake_case pagination key

A residual total_pages reference was found in a test and needs to be renamed to camelCase:

• frontend/tests/unit/pages/Contribute.test.tsx:138

-      total_pages: 1,
+      totalPages: 1,

No occurrences of open_issues_count were detected. Please update this test to match the renamed pagination key.

🧹 Nitpick comments (1)
frontend/src/app/projects/page.tsx (1)

33-36: Type-safe param list – use keyof Project instead of plain strings

Hard-coding property names as string[] bypasses the compiler’s help; a later rename in Project would silently break the icon rendering. Declare the list with a keyof Project union (and ideally as const) so TypeScript flags typos automatically.

-    const params: string[] = ['forksCount', 'starsCount', 'contributorsCount']
+    const params: Array<keyof Project> = [
+      'forksCount',
+      'starsCount',
+      'contributorsCount',
+    ] as const
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b39bea and 7da5ff2.

⛔ Files ignored due to path filters (1)
  • backend/poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (34)
  • backend/apps/core/api/algolia.py (2 hunks)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/app/committees/page.tsx (3 hunks)
  • frontend/src/app/contribute/page.tsx (3 hunks)
  • frontend/src/app/members/[memberKey]/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (3 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (2 hunks)
  • frontend/src/app/projects/page.tsx (4 hunks)
  • frontend/src/app/snapshots/[id]/page.tsx (3 hunks)
  • frontend/src/components/DisplayIcon.tsx (1 hunks)
  • frontend/src/components/ItemCardList.tsx (2 hunks)
  • frontend/src/components/LogoCarousel.tsx (1 hunks)
  • frontend/src/components/Milestones.tsx (1 hunks)
  • frontend/src/components/MultiSearch.tsx (6 hunks)
  • frontend/src/components/RecentIssues.tsx (1 hunks)
  • frontend/src/components/RecentPullRequests.tsx (1 hunks)
  • frontend/src/components/RecentReleases.tsx (1 hunks)
  • frontend/src/types/button.ts (1 hunks)
  • frontend/src/types/card.ts (3 hunks)
  • frontend/src/types/event.ts (1 hunks)
  • frontend/src/types/home.ts (2 hunks)
  • frontend/src/types/icon.ts (1 hunks)
  • frontend/src/types/issue.ts (1 hunks)
  • frontend/src/types/milestone.ts (1 hunks)
  • frontend/src/types/modal.ts (1 hunks)
  • frontend/src/types/organization.ts (1 hunks)
  • frontend/src/types/project.ts (2 hunks)
  • frontend/src/types/pullRequest.ts (1 hunks)
  • frontend/src/types/release.ts (1 hunks)
  • frontend/src/types/search.ts (1 hunks)
  • frontend/src/types/section.ts (1 hunks)
  • frontend/src/types/snapshot.ts (1 hunks)
  • frontend/src/types/user.ts (1 hunks)
  • frontend/src/utils/utility.ts (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • frontend/src/types/event.ts
  • frontend/src/types/icon.ts
🚧 Files skipped from review as they are similar to previous changes (30)
  • frontend/src/components/RecentIssues.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/app/members/[memberKey]/page.tsx
  • frontend/src/types/section.ts
  • backend/apps/core/api/algolia.py
  • frontend/src/app/about/page.tsx
  • frontend/src/components/RecentReleases.tsx
  • frontend/src/app/committees/page.tsx
  • frontend/src/types/button.ts
  • frontend/src/app/contribute/page.tsx
  • frontend/src/components/LogoCarousel.tsx
  • frontend/src/types/pullRequest.ts
  • frontend/src/components/DisplayIcon.tsx
  • frontend/src/types/modal.ts
  • frontend/src/components/Milestones.tsx
  • frontend/src/types/milestone.ts
  • frontend/src/types/organization.ts
  • frontend/src/components/RecentPullRequests.tsx
  • frontend/src/types/snapshot.ts
  • frontend/src/types/release.ts
  • frontend/src/components/MultiSearch.tsx
  • frontend/src/types/user.ts
  • frontend/src/utils/utility.ts
  • frontend/src/app/snapshots/[id]/page.tsx
  • frontend/src/app/organizations/page.tsx
  • frontend/src/components/ItemCardList.tsx
  • frontend/src/types/home.ts
  • frontend/src/types/search.ts
  • frontend/src/types/project.ts
  • frontend/src/types/card.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/types/issue.ts (1)
frontend/src/types/user.ts (2)
  • User (10-30)
  • RepositoryDetails (5-8)
frontend/src/app/projects/page.tsx (3)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (29-139)
frontend/src/types/project.ts (1)
  • Project (16-43)
frontend/src/utils/data.ts (1)
  • level (111-132)
🪛 Biome (1.9.4)
frontend/src/app/projects/page.tsx

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests

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

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afc1821 and a0de818.

📒 Files selected for processing (8)
  • backend/apps/common/utils.py (1 hunks)
  • backend/apps/core/utils/index.py (2 hunks)
  • backend/tests/apps/common/utils_test.py (2 hunks)
  • frontend/src/app/page.tsx (6 hunks)
  • frontend/src/components/Milestones.tsx (1 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/issue.ts (1 hunks)
  • frontend/src/types/milestone.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/types/milestone.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • frontend/src/components/Milestones.tsx
  • backend/apps/core/utils/index.py
  • frontend/src/app/page.tsx
  • frontend/src/types/chapter.ts
  • frontend/src/types/issue.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
backend/tests/apps/common/utils_test.py (1)
backend/apps/common/utils.py (1)
  • convert_to_camel_case (15-28)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Run frontend e2e tests
🔇 Additional comments (1)
backend/tests/apps/common/utils_test.py (1)

20-34: Add edge-case cases for empty and double-underscore strings

The parametrised suite is solid, but the implementation bug above isn’t surfaced because inputs like "", "_" or "__double" are missing. Including them would prevent regressions and document the intended behaviour:

         [
+            ("", ""),
             ("simple", "simple"),
             ("my_variable", "myVariable"),
@@
             ("multiple__underscores", "multipleUnderscores"),
             ("alreadyCamelCase", "alreadyCamelCase"),
+            ("_", "_"),                     # single underscore
+            ("__double_lead", "__doubleLead"),
         ],

After adding, assert that they pass with the refactored util.

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

♻️ Duplicate comments (1)
frontend/src/app/projects/page.tsx (1)

81-81: Optional chaining still missing (repeat of earlier feedback)

projects && … risks a runtime error when projects is undefined. Switch to projects?.filter(...).map(...) as previously suggested.

🧰 Tools
🪛 Biome (1.9.4)

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧹 Nitpick comments (1)
frontend/src/app/projects/page.tsx (1)

33-35: Leverage keyof Project for stronger type-safety

Using raw strings forfeits compile-time checks; a typo will silently slip through. Declare the list as Array<keyof Project> (and move it outside the render function to avoid re-allocating on every render).

-    const params: string[] = ['forksCount', 'starsCount', 'contributorsCount']
+    const params: Array<keyof Project> = ['forksCount', 'starsCount', 'contributorsCount']
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ddb1c3 and 972626c.

📒 Files selected for processing (24)
  • frontend/src/app/about/page.tsx (3 hunks)
  • frontend/src/app/chapters/[chapterKey]/page.tsx (2 hunks)
  • frontend/src/app/committees/[committeeKey]/page.tsx (1 hunks)
  • frontend/src/app/members/page.tsx (2 hunks)
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (2 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (2 hunks)
  • frontend/src/app/projects/page.tsx (3 hunks)
  • frontend/src/app/snapshots/[id]/page.tsx (3 hunks)
  • frontend/src/app/snapshots/page.tsx (3 hunks)
  • frontend/src/components/ContributorAvatar.tsx (2 hunks)
  • frontend/src/components/ItemCardList.tsx (2 hunks)
  • frontend/src/components/TopContributorsList.tsx (2 hunks)
  • frontend/src/types/button.ts (1 hunks)
  • frontend/src/types/card.ts (3 hunks)
  • frontend/src/types/chapter.ts (1 hunks)
  • frontend/src/types/committee.ts (1 hunks)
  • frontend/src/types/contributor.ts (1 hunks)
  • frontend/src/types/home.ts (2 hunks)
  • frontend/src/types/modal.ts (1 hunks)
  • frontend/src/types/project.ts (2 hunks)
  • frontend/src/types/section.ts (1 hunks)
  • frontend/src/types/skeleton.ts (1 hunks)
  • frontend/src/types/snapshot.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (22)
  • frontend/src/types/section.ts
  • frontend/src/app/snapshots/page.tsx
  • frontend/src/app/projects/[projectKey]/page.tsx
  • frontend/src/app/committees/[committeeKey]/page.tsx
  • frontend/src/app/chapters/[chapterKey]/page.tsx
  • frontend/src/app/members/page.tsx
  • frontend/src/app/about/page.tsx
  • frontend/src/types/contributor.ts
  • frontend/src/types/modal.ts
  • frontend/src/components/TopContributorsList.tsx
  • frontend/src/components/ItemCardList.tsx
  • frontend/src/types/button.ts
  • frontend/src/app/organizations/page.tsx
  • frontend/src/components/ContributorAvatar.tsx
  • frontend/src/types/committee.ts
  • frontend/src/app/snapshots/[id]/page.tsx
  • frontend/src/types/chapter.ts
  • frontend/src/types/snapshot.ts
  • frontend/src/types/project.ts
  • frontend/src/app/organizations/[organizationKey]/repositories/[repositoryKey]/page.tsx
  • frontend/src/types/home.ts
  • frontend/src/types/card.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
frontend/src/app/projects/page.tsx (4)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (29-139)
frontend/src/types/project.ts (1)
  • Project (16-43)
frontend/src/utils/utility.ts (1)
  • getFilteredIcons (22-35)
frontend/src/utils/data.ts (1)
  • level (111-132)
🪛 Biome (1.9.4)
frontend/src/app/projects/page.tsx

[error] 81-81: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (3)
frontend/src/types/skeleton.ts (2)

1-4: Interface-to-type switch may break declaration merging / extends chains

Changing CardSkeletonProps from interface to a type removes two TS capabilities:

  1. Declaration merging – consumers can no longer augment the shape in a different file.
  2. extends clauses – existing code like
    interface Foo extends CardSkeletonProps { … } will now error.

Before merging, grep the codebase for extends CardSkeletonProps or any duplicate declarations to ensure nothing breaks, and convert them to intersection types (Foo = CardSkeletonProps & { … }) if necessary.


13-17: Same merging concern for UserCardSkeletonProps

The interface-to-type conversion brings the same risk of breaking extends or merged interface patterns. Run the same verification for UserCardSkeletonProps.

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

40-44: Double-check prop naming consistency (onClick vs onclick)

The button object uses the lowercase onclick. Most components – and React conventions in general – expect onClick.
Please confirm Card is indeed looking for onclick; otherwise the handler will never fire.

Comment on lines +2 to +4
numIcons?: number
showActionButton?: boolean
showContributors?: 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

Potential ambiguity between numIcons and showIcons

numIcons?: number was added, but the existing boolean flag showIcons? remains.
If showIcons is false yet numIcons is a positive value, which prop wins? Consider either:

-  numIcons?: number
-  showIcons?: boolean
+  /**
+   * When > 0, component renders that many icons.
+   * If provided, `showIcons` is ignored.
+   */
+  numIcons?: number

or deprecate one of the two to avoid conflicting states.

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

🤖 Prompt for AI Agents
In frontend/src/types/skeleton.ts around lines 2 to 4, there is ambiguity
between the boolean `showIcons` and the numeric `numIcons` properties. To fix
this, clarify their relationship by either removing or deprecating one of the
properties to avoid conflicting states, or implement logic that clearly defines
which property takes precedence when both are set. Update the type definitions
and any related usage accordingly to ensure consistent behavior.

@sonarqubecloud
Copy link

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

It's a great clean up work even though we still have a few cases w/ interfaces. Let's take care of that after merging this PR.

@arkid15r arkid15r enabled auto-merge June 12, 2025 22:47
Copy link
Contributor

@aramattamara aramattamara left a comment

Choose a reason for hiding this comment

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

LGTM!

@arkid15r arkid15r added this pull request to the merge queue Jun 13, 2025
Merged via the queue into OWASP:main with commit 7d93637 Jun 13, 2025
23 checks passed
codic-yeeshu pushed a commit to codic-yeeshu/Nest that referenced this pull request Jun 28, 2025
* fixed backend to return camelCase

* fixed types for chapters, committees, members and organizations

* fixed types for all pages

* fixed types of all the pages, component, utility, types

* fixed unit tests

* fixed types and interfaces

* updated code

* Update code

* fixed types and import with types

* fixed more bugs

* updated code

* fixed code

* fixed camelcase fn

* fixed testcases

* fixed unit test

* Update code

* Update code

---------

Co-authored-by: Tamara Lazerka <98753789+aramattamara@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
@coderabbitai coderabbitai bot mentioned this pull request Sep 18, 2025
3 tasks
@coderabbitai coderabbitai bot mentioned this pull request Oct 17, 2025
2 tasks
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.

Restructure and Unify Frontend Types/Interfaces

3 participants