Skip to content
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

Feature/intervention #2343

Open
wants to merge 39 commits into
base: develop
Choose a base branch
from
Open

Feature/intervention #2343

wants to merge 39 commits into from

Conversation

shyambhongle
Copy link
Member

Fixes #

Changes in this pull request:
Displaying other interventions in the web app.

Copy link

vercel bot commented Dec 27, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
planet-webapp-multi-tenancy-setup ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 8, 2025 11:55am
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
planet-webapp ⬜️ Ignored (Inspect) Jan 8, 2025 11:55am
planet-webapp-temp ⬜️ Ignored (Inspect) Jan 8, 2025 11:55am

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@sunilsabatp
Copy link
Contributor

Is the intervention feature applicable to all projects or only to selected ones? The interaction with the intervention dropdown does not show any results for some projects. Could you hide the intervention dropdown or its options if it is not applicable to a project?
Demo :
https://planet-webapp-multi-tenancy-setup-git-feature-c00ea7-planetapp.vercel.app/en/wfz-embangweni?site=site_UV8VYlrAiqCLC7m

@shyambhongle
Copy link
Member Author

Is the intervention feature applicable to all projects or only to selected ones? The interaction with the intervention dropdown does not show any results for some projects. Could you hide the intervention dropdown or its options if it is not applicable to a project? Demo : https://planet-webapp-multi-tenancy-setup-git-feature-c00ea7-planetapp.vercel.app/en/wfz-embangweni?site=site_UV8VYlrAiqCLC7m

It's should be visible for all Project. Not sure whether we would require to hide it when no intervention is present.

@sunilsabatp

This comment was marked as resolved.

Copy link
Contributor

coderabbitai bot commented Jan 6, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm warn config production Use --omit=dev instead.
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: [email protected]
npm error Found: [email protected]
npm error node_modules/eslint
npm error dev eslint@"^8.26.0" from the root project
npm error peer eslint@"6 || 7 || 8" from @emotion/[email protected]
npm error node_modules/@emotion/eslint-plugin
npm error dev @emotion/eslint-plugin@"^11.12.0" from the root project
npm error 15 more (@eslint-community/eslint-utils, ...)
npm error
npm error Could not resolve dependency:
npm error peer eslint@"^5.16.0 || ^6.8.0 || ^7.2.0" from [email protected]
npm error node_modules/eslint-config-airbnb
npm error dev eslint-config-airbnb@"^18.2.0" from the root project
npm error
npm error Conflicting peer dependency: [email protected]
npm error node_modules/eslint
npm error peer eslint@"^5.16.0 || ^6.8.0 || ^7.2.0" from [email protected]
npm error node_modules/eslint-config-airbnb
npm error dev eslint-config-airbnb@"^18.2.0" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error /root/.npm/_logs/2025-01-08T11_50_41_611Z-eresolve-report.txt
npm error A complete log of this run can be found in: /root/.npm/_logs/2025-01-08T11_50_41_611Z-debug-0.log

Walkthrough

This pull request introduces significant enhancements to the project's intervention management system, focusing on the user interface and functionality for displaying and interacting with various plant locations and interventions. Key changes include the addition of new React components, modifications to type definitions, the implementation of dropdown menus for intervention selection, and styling updates to support detailed intervention information across the project's map and details views.

Changes

File Change Summary
public/assets/images/icons/InterventionIcon.tsx New SVG icon component for interventions
src/features/common/types/plantLocation.d.ts Added type property to PlantLocationSingle and PlantLocationMulti interfaces
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx New component for displaying intervention details
src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx New component for intervention header
src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx New component for other intervention header
src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx New component for displaying other intervention metadata
src/features/projectsV2/ProjectDetails/index.tsx Integrated OtherInterventionInfo component
src/features/projectsV2/ProjectsContext.tsx Added state management for interventions
src/features/projectsV2/ProjectsMap/InterventionDropDown/* New dropdown components for intervention selection
src/utils/constants/intervention.ts Added intervention-related constants, types, and utility functions
src/features/projectsV2/ProjectsMap/MapControls.tsx Updated to include intervention dropdown functionality
src/features/projectsV2/ProjectsMap/ProjectSiteDropDown/index.tsx Enhanced dropdown logic to manage intervention filters
src/features/projectsV2/ProjectsMap/ProjectsMap.module.scss Modified styles for project map controls
src/features/projectsV2/ProjectsMap/microComponents/PlantLocations.tsx Updated filtering logic based on selected intervention type

Sequence Diagram

sequenceDiagram
    participant User
    participant MapControls
    participant InterventionDropdown
    participant ProjectsContext
    participant ProjectsMap

    User->>MapControls: Open intervention dropdown
    MapControls->>InterventionDropdown: Render dropdown
    User->>InterventionDropdown: Select intervention type
    InterventionDropdown->>ProjectsContext: Update selectedIntervention
    ProjectsContext-->>ProjectsMap: Filter plant locations
    ProjectsMap->>User: Display filtered locations
Loading

Possibly related PRs

  • Implement mobile UI for MapFeatureExplorer #2213: The changes in this PR involve the introduction of a new React component ExploreIcon, which is related to the main PR's addition of the InterventionIcon component, as both involve creating new icon components in the same context of enhancing UI elements.
  • Fix data explorer queries for single tree registrations #2273: This PR focuses on fixing data explorer queries for single tree registrations, which aligns with the main PR's introduction of the InterventionIcon component, as both are related to the management and representation of interventions in the application.
  • Post Launch feedback for projects facelift #2302: This PR includes enhancements to the UI and functionality of the project, which may relate to the visual representation of interventions, similar to the InterventionIcon added in the main PR.
  • Address mgmt/separate translation #2323: The restructuring of translation resources in this PR could be relevant as it may affect how icons like InterventionIcon are labeled or described in the UI, linking it to the main PR's focus on new UI components.

Suggested Labels

projects redesign, MyForest 2.0

Suggested Reviewers

  • sunilsabatp
  • mohitb35

Poem

🌱 Intervention's tale, a digital delight,
Mapping forests with technological might.
Dropdowns dancing, icons so bright,
Revealing nature's complex design,
A code-woven forest, simply divine! 🐰


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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 (19)
src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx (1)

9-9: Remove or rename unused type prop.

According to the static analysis hint, type is not utilized in this component. If it's truly irrelevant, remove it from both the component signature and the Props interface; otherwise, prefix it with an underscore if you intend to keep it as an unused placeholder.

-const OtherInterventionInfoHeader = ({ plantDate, type }: Props) => {
+const OtherInterventionInfoHeader = ({ plantDate }: Props) => {
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 9-9: src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx#L9
'type' is defined but never used. Allowed unused args must match /^_/u. (@typescript-eslint/no-unused-vars)

src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (1)

14-17: Provide a fallback label for missing intervention data.

When an intervention is not found in AllIntervention, returning an empty string may lead to unclear UI states. Consider using a more descriptive fallback label (e.g., "Unknown Intervention") to help users understand the missing data.

 return found ? found.label : '';
+// Or use a fallback:
+// return found ? found.label : 'Unknown Intervention';
src/utils/mapsV2/zoomOut.tsx (1)

17-17: Make newZoom configurable.

Locking the zoom level to 12 may not be ideal for all user flows and map contexts. Allowing it to be set via a parameter or context would improve adaptability.

 const newZoom = 12;
+// Consider passing zoom as a parameter:
+// function zoomOut(handleViewStateChange, mapRef, { duration = 1000, zoom = 12 }) {
+//   ...
+//   const newZoom = zoom;

Also applies to: 19-24

src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx (1)

32-60: Consider splitting nested logic into separate helper functions.
Multiple nested conditions make the code harder to follow. Splitting out the JSON parsing and key/value processing into smaller functions will improve readability and maintainability.

-  if (typeof value === 'string') {
-    checkForPublic.push({ value, key });
-  } else if (typeof value === 'object' && value !== null && 'value' in value && 'label' in value) {
-    if (isJsonString(value.value)) {
-      ...
-    }
-    ...
-  }
+  function parsePublicEntry(key: string, value: string | MetaDataValue) {
+    if (typeof value === 'string') {
+      return { key, value };
+    }
+    if (typeof value === 'object' && value !== null && 'value' in value && 'label' in value) {
+      if (isJsonString(value.value)) {
+        // parse JSON if valid
+      }
+      return { key: value.label, value: value.value };
+    }
+    return null;
+  }
+
+  // then call parsePublicEntry within forEach
src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (1)

63-73: Remove unnecessary fragment.
According to the static analysis tool, the fragment containing a single child is redundant. Removing it simplifies the JSX.

- <>
    {selectedSiteData && (
      <div className={styles.labelTextContainer}>
        ...
      </div>
    )}
- </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 63-73: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

src/utils/constants/intervention.ts (1)

48-88: Consider localization of labels
The AllIntervention array contains user-facing labels. If the application supports multiple languages, consider integrating these text values into your translation system to maintain consistency.

src/features/projectsV2/ProjectsMap/MapControls.tsx (1)

78-79: Confirm role of disableInterventionFilter
Closely review how this prop is used. If it also merely calls setDisableInterventionMenu(false), consider inlining it to simplify logic.

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (3)

50-65: Leverage optional chaining to simplify
You can avoid nested property checks by using optional chaining.

- plantLocationInfo &&
- plantLocationInfo.plantedSpecies &&
- plantLocationInfo.plantedSpecies.length > 0
+ plantLocationInfo?.plantedSpecies?.length > 0
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-53: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


68-78: Optional chain for sampleInterventions
Consider using plantLocationInfo?.sampleInterventions?.map to streamline the check and reduce potential undefined errors.

-if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
-  const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
+if (plantLocationInfo?.sampleInterventions?.length > 0) {
+  const result = plantLocationInfo.sampleInterventions.map((item) => {
🧰 Tools
🪛 Biome (1.9.4)

[error] 69-75: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


116-117: Optional chain for sampleInterventions
Similarly, you can apply an optional chain when accessing plantLocationInfo.sampleInterventions.

- plantLocationInfo &&
- plantLocationInfo.sampleInterventions &&
- plantLocationInfo.sampleInterventions.length > 0
+ plantLocationInfo?.sampleInterventions?.length > 0
🧰 Tools
🪛 Biome (1.9.4)

[error] 116-117: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/features/projectsV2/ProjectsMap/microComponents/PlantLocations.tsx (2)

137-142: Refactor the filtering logic for clarity.
These chained conditions can be extracted into a short helper function for better readability and maintainability.

-const features = plantLocations.filter(d =>
-  selectedIntervention === 'all' ||
-  (selectedIntervention !== 'default' && d.type === selectedIntervention) ||
-  (selectedIntervention === 'default' &&
-    (d.type === 'multi-tree-registration' || d.type === 'single-tree-registration'))
-).map((el) => {
+const shouldInclude = (d: PlantLocation) => {
+  if (selectedIntervention === 'all') return true;
+  if (selectedIntervention === 'default') {
+    return d.type === 'multi-tree-registration' || d.type === 'single-tree-registration';
+  }
+  return d.type === selectedIntervention;
+};
+const features = plantLocations.filter(shouldInclude).map((el) => {

197-197: Switch fallback color might need brand alignment.
If the satellite view color is hardcoded to #ffffff, ensure this aligns with your brand guidelines. Otherwise, consider configuring a single color strategy.

src/features/projectsV2/ProjectsMap/index.tsx (1)

179-181: Keep naming straightforward.
mapContainerClass merges base styles with the device-specific class. This is fine; just ensure the naming is intuitive for future contributors.

src/features/projectsV2/ProjectsContext.tsx (1)

99-100: Explicit types might be unnecessary.
As previously noted, TypeScript can infer the types from default values. Consider omitting them for brevity.

src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.module.scss (4)

3-5: Consider using more descriptive variable names.
Variables such as $layoutPaddingTop and $layoutPaddingSide are clear, but ensuring they reflect the intended usage (e.g., $dropdownLayoutPaddingTop) might aid future maintainers.


25-36: Consider reusing classes for text styles.
.sitesLabel and nested span are well-structured, but watch for repeated patterns of color and font-size across the codebase to maintain consistency.


37-46: Use variable for color.
Line 45 has a comment //to be replaced. Consider referencing an SCSS variable from the theme to maintain consistency with the rest of your styling.


100-104: Good approach to indicating selection state.
.selectedItem clarifies the user’s active choice by increasing text weight. As noted, replace the hex color with a theme variable for consistency.

src/features/projectsV2/ProjectDetails/styles/PlantLocationInfo.module.scss (1)

15-24: Consider reusing existing .plantLocationInfoSection structure.
.otherInterventionInfoSection essentially mirrors .plantLocationInfoSection. Reusing a base class or applying a mixin could reduce CSS duplication.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e639c93 and a7555c3.

📒 Files selected for processing (20)
  • public/assets/images/icons/InterventionIcon.tsx (1 hunks)
  • src/features/common/types/plantLocation.d.ts (2 hunks)
  • src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/index.tsx (3 hunks)
  • src/features/projectsV2/ProjectDetails/styles/PlantLocationInfo.module.scss (3 hunks)
  • src/features/projectsV2/ProjectsContext.tsx (5 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.module.scss (1 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/MapControls.tsx (4 hunks)
  • src/features/projectsV2/ProjectsMap/ProjectSiteDropDown/SiteDropdown.module.scss (1 hunks)
  • src/features/projectsV2/ProjectsMap/ProjectSiteDropDown/index.tsx (4 hunks)
  • src/features/projectsV2/ProjectsMap/ProjectsMap.module.scss (1 hunks)
  • src/features/projectsV2/ProjectsMap/index.tsx (4 hunks)
  • src/features/projectsV2/ProjectsMap/microComponents/PlantLocations.tsx (8 hunks)
  • src/utils/constants/intervention.ts (1 hunks)
  • src/utils/mapsV2/zoomOut.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • public/assets/images/icons/InterventionIcon.tsx
🧰 Additional context used
🪛 GitHub Check: CodeFactor
src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx

[notice] 9-9: src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx#L9
'type' is defined but never used. Allowed unused args must match /^_/u. (@typescript-eslint/no-unused-vars)

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[warning] 87-87: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L87
Missing "key" prop for element in array (react/jsx-key)

🪛 Biome (1.9.4)
src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx

[error] 63-73: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 52-53: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 69-75: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 116-117: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 87-87: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🪛 GitHub Check: ESLint on Ubuntu
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[failure] 87-87:
Missing "key" prop for element in array

🪛 GitHub Actions: ESLint error report
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 87-87: Missing "key" prop for element in array (react/jsx-key)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (50)
src/features/projectsV2/ProjectsMap/ProjectsMap.module.scss (3)

14-14: Ensure alignment is intentional.

Switching to justify-content: flex-end; moves the items to the right. Verify that the right alignment aligns with the design specifications for desktop and mobile breakpoints.


16-16: Responsive gap usage.

Using gap: 2vw; is a great way to make spacing responsive. However, be mindful of extremely wide or narrow screens—vw might lead to either too much or too little spacing in edge cases.


19-19: Check container width constraints.

Assigning width: 85% to a container with position: absolute; can be tricky. Confirm there are no unwanted overlaps or alignment issues on varied viewport sizes.

src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1)

30-38: Use a unique key and add accessibility attributes (duplicate of previous comment).

Using the array index as a key can cause issues in dynamic lists and lead to suboptimal rendering behavior. Additionally, the list items do not provide accessibility hints for screen readers, such as role="option" and keyboard event handlers, to support accessibility.

src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx (1)

69-70: Avoid using array index as the key prop.
Using key={key} can cause rendering issues when list items change order. Please switch to a more stable, unique identifier.

src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (1)

46-50: Confirm the logic for disabling the dropdown menu.
Currently, the dropdown closes when disableInterventionMenu === false. If the intended behavior is to close it when disableInterventionMenu === true, consider updating the condition.

 useEffect(() => {
-  if(!disableInterventionMenu){
+  if(disableInterventionMenu){
     setIsMenuOpen(false)
   }
 }, [disableInterventionMenu])
src/features/common/types/plantLocation.d.ts (1)

1-8: Import and type usage look good.
The new property type: InterventionTypes and its import appear consistent with the existing typings.

src/features/projectsV2/ProjectsMap/ProjectSiteDropDown/index.tsx (2)

80-84: Ensure alignment between menu and intervention states.
Closing the dropdown when disableInterventionMenu is true is logical. Confirm that other features depending on menu availability also gracefully handle this condition.


90-93: Verify if the menu toggle should always disable the intervention filter.
Currently, toggling the menu calls disableInterventionFilter() unconditionally. If the user intends to disable filtering only upon closing the menu, consider wrapping this logic with a condition.

src/utils/constants/intervention.ts (6)

4-5: Clarify identical color codes for SINGLE_TREE and MULTI_TREE
Both constants use the same hex color value (#007A49). Confirm whether this is intentional or if each intervention should have a distinct color to improve clarity and differentiation.


10-11: Confirm usage of the term "regenerant"
It's unclear whether “regenerant” is domain-specific or a potential typo. If the term is correct, consider adding clarifying comments or references explaining its meaning to improve maintainability.


48-88: Check for identical index values
All interventions here have index: 0. If these indices are meant to be unique or arranged in a particular order, ensure that the values are properly maintained.


93-95: Function behavior looks good
The isNonPlantationType helper accurately checks for non-plantation types.


98-100: Usage of findMatchingIntervention
No concerns. This helper cleanly retrieves an intervention by value.


102-107: Confirm multi-tree location guard
isPlantLocationMulti is a logical type guard. Ensure all call sites handle the returned type correctly, especially when chaining with other location checks.

src/features/projectsV2/ProjectsMap/MapControls.tsx (4)

64-66: Inline or remove enableInterventionFilter
This function only calls setDisableInterventionMenu(true). In accordance with the previous suggestion (line 70 from older commits), consider removing it or inlining it directly to keep the code simpler and reduce indirection.

-  const enableInterventionFilter=()=>{
-    setDisableInterventionMenu(true)
-  }
+  // Remove the function and call `setDisableInterventionMenu(true)` directly wherever needed

82-90: Descriptive naming for props
InterventionDropdownProps effectively conveys the needed props. Ensure naming consistency across similar objects (e.g., siteDropdownProps) and verify each property is used.


136-138: Confirm layout spacing
When rendering both ProjectSiteDropdown and InterventionDropDown in mobile view, confirm that sufficient space is allocated to avoid unwanted overlapping.


150-153: Desktop layout synergy
Placing ProjectSiteDropdown and InterventionDropDown side by side looks good. Validate hover or click behaviors are intuitive for desktop users.

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1)

103-108: ⚠️ Potential issue

Duplicate key "plantingDetails"
“plantingDetails” is used twice. Use distinct keys to avoid React warnings.

    <OtherInterventionInfoHeader
-      key="plantingDetails"
+      key="otherInterventionHeader"
      plantDate={plantLocationInfo?.interventionStartDate}
      type={plantLocationInfo?.type}
    />,
    checkForPublicData && <OtherInterventionMetaData
-      key="plantingDetails"
+      key="otherInterventionMetaData"
      ...
    />

Likely invalid or redundant comment.

src/features/projectsV2/ProjectDetails/index.tsx (3)

26-27: Good modularization
Importing OtherInterventionInfo and isNonPlantationType from shared utilities centralizes intervention logic.


130-136: Ensure clarity in shouldShowOtherIntervention
isNonPlantationType is checked on both hoveredPlantLocation and selectedPlantLocation, plus a !isMobile check on only the latter. Confirm whether it’s deliberate that hovered non-plantation types appear on mobile but selected non-plantation types do not.


199-200: Validate new OtherInterventionInfo usage
The conditional rendering logic is straightforward. Confirm that the layout coexists cleanly with MultiPlantLocationInfo and SinglePlantLocationInfo components.

src/features/projectsV2/ProjectsMap/microComponents/PlantLocations.tsx (6)

17-17: Centralized color definition is good practice.
Importing FillColor from a constants file fosters maintainability and consistency.


27-27: No immediate concerns with the new state usage.
The selectedIntervention addition aligns well with the filtering logic. Please ensure thorough testing wherever this state is accessed or modified.


151-151: No issues with property assignment.
Including the type in GeoJSON properties is consistent for debugging or later usage.


170-170: Centralized usage of FillColor is consistent.
Good job maintaining a single source of truth for color values.


179-179: Uniform use of FillColor for circles.
This maintains consistency across different geometry types.


216-239: Conditional rendering of sample markers looks correct.
The marker rendering logic appears coherent; ensure you have tests covering scenarios with and without sampleInterventions.

src/features/projectsV2/ProjectsMap/index.tsx (3)

27-28: Useful additions for extended functionality.
Importing OtherInterventionInfo and PLANTATION_TYPES is a clear step toward supporting multiple intervention types.


141-168: Ensure user experience consistency on repeated clicks.
The onClick callback handles toggling plant locations. Consider verifying click behavior in edge cases (e.g., user double-clicks on multi-tree points repeatedly).


230-231: Enhancement for secondary interventions.
Conditionally rendering OtherInterventionInfo is a neat approach to handle non-plantation interventions.

src/features/projectsV2/ProjectsContext.tsx (3)

61-64: New fields in the interface appear consistent.
selectedIntervention and disableInterventionMenu align with the broader interventions feature.


245-246: Resetting intervention states on page change.
This effectively prevents carrying stale data from the project details to the project list. Provide test coverage for transitions.


Line range hint 451-475: Well-organized context value.
The addition of selectedIntervention and disableInterventionMenu is structured properly in the context.

src/features/projectsV2/ProjectsMap/ProjectSiteDropDown/SiteDropdown.module.scss (1)

145-145: Consider the potential overlap.
Shifting right to 40% might cause layout overlap in certain screen widths. Verify positioning across device sizes.

src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.module.scss (8)

1-2: Import usage looks good.
Importing the theme at the top ensures consistent styling throughout.


21-24: LGTM!
The layout for .siteIconAndTextContainer is simple and straightforward.


47-55: Handles icon sizing consistently.
The .menuArrow class aligns icons consistently with the rest of the UI. This helps maintain uniform spacing across components.


56-77: Beware of complex absolute positioning.
Positioning the dropdown absolutely can cause display issues in mobile or smaller layouts. Confirm this usage doesn’t clash with other components overlapping or going off-screen.


78-90: Ensure consistent vertical spacing.
The .listItem class sets gap and padding, which is good for readability. Just be sure that users don’t accidentally tap multiple items on mobile if the spacing is too tight.


91-99: Conditional utility classes are a good pattern.
.hideDivider and .showDivider can be toggled dynamically, improving flexibility of the UI.


106-159: Responsive tweaks appreciated.
The media query adjusts layout effectively for smaller screens. Monitor the real device testing to ensure the dropdown doesn’t overlap other critical UI elements.


6-20: Ensure accessible contrast for background color.
The usage of $backgroundColor in combination with text color should meet accessibility guidelines. Verify your color contrast ratio to ensure readability.

✅ Verification successful

Color contrast appears to be sufficient with #333 text color
The dropdown uses #333 (dark gray) text color which typically provides excellent contrast against light backgrounds, meeting WCAG accessibility guidelines. The consistent use of this color combination across dropdown components suggests it's part of an accessible design system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Use ast-grep or a color contrast checker to confirm background color contrast in .dropdownButton.
# This script searches for the `.dropdownButton` definition and any usage of $backgroundColor.
rg -A 5 $'\.dropdownButton'

Length of output: 3869


Script:

#!/bin/bash
# Search for backgroundColor variable definition and color-related variables
rg -g '*.scss' -g '*.css' '\$backgroundColor' -A 2
rg -g '*.scss' -g '*.css' 'color:' -A 1 src/features/projectsV2/ProjectsMap/

Length of output: 34868

src/features/projectsV2/ProjectDetails/styles/PlantLocationInfo.module.scss (6)

49-50: Gap property is a welcome addition.
Increasing the gap for .plantingDetailsGroup can improve readability.


53-56: No concerns.
The .otherInterventionGroup class is straightforward and uses a consistent font size.


58-62: Good approach to highlight “Other Intervention” sections.
The background color and padding highlight these items well. Ensure they remain visually distinct for better user experience.


66-66: Minor dimension update is consistent with the design standard.
Changing .plantingDetailsItem from 162px to 160px should be verified across views to ensure it doesn’t break layout on smaller screens.


220-225: Nice modular approach for metadata styling.
.interventionMetaItem indicates a clear separation for each metadata entry. This can easily be reused for additional attributes in future expansions.


227-232: Check label alignment.
If .plantMetaDataCardLabel is intended to appear on top or inline with .interventionMetaItem, verify the design requirement. Spacing might need adjusting for a consistent layout across different screen sizes.

const checkForPublicData = plantLocationInfo?.metadata.public.length !== 0

const content = [
<InterventionHeader plHid={plantLocationInfo?.hid} type={plantLocationInfo?.type} />,
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Add unique keys to array elements
The review comment is correct. The InterventionHeader component is rendered within an array and requires a key prop. Additionally, there's a duplicate key="plantingDetails" between OtherInterventionInfoHeader and OtherInterventionMetaData components that should be fixed.

  • Add key="interventionHeader" to InterventionHeader
  • Change the key of OtherInterventionMetaData to key="interventionMetadata" to avoid duplicate keys
🔗 Analysis chain

Add a unique key property
When rendering an item within an array, React requires a unique key.

-    <InterventionHeader plHid={plantLocationInfo?.hid} type={plantLocationInfo?.type} />,
+    <InterventionHeader 
+      key="interventionHeader" 
+      plHid={plantLocationInfo?.hid} 
+      type={plantLocationInfo?.type} 
+    />,
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# View the complete file content to understand the context
cat src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

Length of output: 4778

🧰 Tools
🪛 Biome (1.9.4)

[error] 87-87: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🪛 GitHub Check: ESLint on Ubuntu

[failure] 87-87:
Missing "key" prop for element in array

🪛 GitHub Check: CodeFactor

[warning] 87-87: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L87
Missing "key" prop for element in array (react/jsx-key)

🪛 GitHub Actions: ESLint error report

[error] 87-87: Missing "key" prop for element in array (react/jsx-key)

Comment on lines 214 to 217
.interventionMetaDataGroup {
display: flex;
flex-direction: column,

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential syntax error.
In .interventionMetaDataGroup, there's a comma instead of a semicolon on line 216. Sass might parse this incorrectly. Please confirm.

-  flex-direction: column,
+  flex-direction: column;
📝 Committable suggestion

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

Suggested change
.interventionMetaDataGroup {
display: flex;
flex-direction: column,
.interventionMetaDataGroup {
display: flex;
flex-direction: column;

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (1)

14-17: Ensure an empty fallback is appropriate

Returning an empty string might make debugging difficult if the intervention type is unexpected. Consider at least logging or handling an unknown type scenario for better maintainability.

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (2)

36-40: Keep the interface separate if expansions are expected

The Props interface is clearly defined. If more properties will be added in the future, consider placing it in a dedicated file for easier maintenance and reusability.


50-65: Optional chaining recommendation

The static analysis hints suggest optional chaining, which can reduce repetitive checks. A minimal example within this block:

- (plantLocationInfo &&
-   plantLocationInfo.plantedSpecies &&
-   plantLocationInfo.plantedSpecies.length > 0)
+ (plantLocationInfo?.plantedSpecies?.length ?? 0) > 0
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-53: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7555c3 and 4c6de8d.

📒 Files selected for processing (2)
  • src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 52-53: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 69-75: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 116-117: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (2)

5-8: Good use of typed props

Providing explicit types for plHid and interventionType ensures clearer usage. Keep it up.


19-26: Sensible layout with consistent naming

Using both a custom class (plant-location-header-container) and an SCSS module class helps maintain consistent styling throughout. The usage of descriptive class names like tree-count and hid is clear and aids readability.

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (4)

23-34: Interface extension is well-structured

The OtherInterventions interface extends PlantLocationBase and adds relevant fields for interventions. This approach cleanly organizes shared and specialized fields.


126-138: Mobile and Desktop views are well-structured

You’ve separated logic for mobile and desktop, improving clarity and user experience. Good approach.


67-78: ⚠️ Potential issue

Prevent potential undefined array access

In line 68, you assume plantLocationInfo.sampleInterventions.length > 0. If sampleInterventions is undefined, this would throw an error. Safeguardino with optional chaining would improve stability:

- if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
+ if (plantLocationInfo?.sampleInterventions?.length > 0) {

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 69-75: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


86-124: ⚠️ Potential issue

Duplicate key usage

At lines 99 and 104, the key is plantingDetails for both OtherInterventionInfoHeader and OtherInterventionMetaData. This causes a React warning for duplicate keys. Use distinct keys:

+ <OtherInterventionInfoHeader
+   key="plantingDetailsHeader"
    ...
  />,
- checkForPublicData && <OtherInterventionMetaData
-   key="plantingDetails"
+ checkForPublicData && <OtherInterventionMetaData
+   key="plantingDetailsMeta"
    ...
  />,

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 116-117: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Copy link
Collaborator

@mohitb35 mohitb35 left a comment

Choose a reason for hiding this comment

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

@shyambhongle Please go through my feedback.

Functionally, most things are fine, although I would combine some of the cards/sections together.

Please go through the code feedback, particular about cleaning up references to old code (e.g. sites) where they don't make sense any more, naming consistency, and the logic to keep only one dropdown open at a time.

In addition, I noticed that the code formatting differs, could you make sure the prettier rules aren't being overridden.

src/features/common/types/plantLocation.d.ts Outdated Show resolved Hide resolved
public/assets/images/icons/InterventionIcon.tsx Outdated Show resolved Hide resolved
src/utils/constants/intervention.ts Outdated Show resolved Hide resolved
src/utils/constants/intervention.ts Outdated Show resolved Hide resolved
src/features/projectsV2/ProjectsContext.tsx Outdated Show resolved Hide resolved
@@ -92,6 +96,8 @@ export const ProjectsProvider: FC<ProjectsProviderProps> = ({
const [hoveredPlantLocation, setHoveredPlantLocation] =
useState<PlantLocation | null>(null);
const [selectedSite, setSelectedSite] = useState<number | null>(null);
const [selectedIntervention, setSelectedIntervention] = useState('all');
const [disableInterventionMenu, setDisableInterventionMenu] = useState(false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

The logic to keep only one menu open is unclear, partly due to using terms like enable and disable instead of open/close/toggle. The names disableInterventionMenu, enableInterventionFilter, disableInterventionFilter need rethinking.

Please revisit this logic across the ProjectSiteDropdown, InterventionDropdown, ProjectsContext and MapControls

Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps a structure like this may be useful

const [activeDropdown, setActiveDropdown] = useState(null);

// In Site Dropdown
const toggleSiteMenu = () => {
  setIsMenuOpen((prev) => !prev);
  setActiveDropdown('site');
};

// In Intervention Dropdown
const toggleInterventionMenu = () => {
  setIsMenuOpen((prev) => !prev);
  setActiveDropdown('intervention');
};

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

🧹 Nitpick comments (6)
src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1)

25-28: Rename function to match its purpose.

The function name handleFilterSelection should be renamed to handleInterventionSelection to better reflect its purpose.

-  const handleFilterSelection = (key: string) => {
+  const handleInterventionSelection = (key: string) => {
     setIsMenuOpen(false);
     setSelectedIntervention(key);
   };
src/utils/constants/intervention.ts (1)

102-107: Remove unused code.

The isPlantLocationMulti function appears to be unused. Consider removing it if it's not needed.

src/features/projectsV2/ProjectsMap/MapControls.tsx (2)

64-69: Simplify state management.

The enableInterventionFilter and disableInterventionFilter functions only set state. Consider calling setDisableInterventionMenu directly where needed.

-  const enableInterventionFilter=()=>{
-    setDisableInterventionMenu(true)
-  }
-  const disableInterventionFilter=()=>{
-    setDisableInterventionMenu(false)
-  }

Update the usage:

-  onClick={enableInterventionFilter}
+  onClick={() => setDisableInterventionMenu(true)}

82-91: Use camelCase for variable names.

Rename InterventionDropdownProps to follow JavaScript naming conventions.

-  const InterventionDropdownProps = {
+  const interventionDropdownProps = {
     selectedIntervention,
     setSelectedIntervention,
     allInterventions: AllInterventions,
     selectedPlantLocation,
     setSelectedPlantLocation,
     setSelectedSamplePlantLocation,
     enableInterventionFilter,
     disableInterventionMenu
   };
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (2)

34-45: Consider making nullable fields optional in OtherInterventions interface.

Fields that can be null should be marked as optional using the ? operator for better type safety.

 export interface OtherInterventions extends PlantLocationBase {
   sampleTreeCount: number;
   sampleInterventions: SamplePlantLocation[];
   plantedSpecies: PlantedSpecies[];
-  nextMeasurementDate: null;
-  scientificName: string | null;
-  scientificSpecies: string | null;
-  tag: string | null;
+  nextMeasurementDate?: null;
+  scientificName?: string;
+  scientificSpecies?: string;
+  tag?: string;
   measurements: Measurements;
   originalGeometry: turf.Point;
   geometry: turf.Point;
 }

137-138: Store and memoize metadata rendering result.

The renderMetaData() result should be memoized to prevent unnecessary recalculations.

-const checkForPublicData = renderMetaData()
+const checkForPublicData = useMemo(() => renderMetaData(), [plantLocationInfo?.metadata]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c6de8d and 6bf4248.

📒 Files selected for processing (10)
  • public/assets/images/icons/InterventionIcon.tsx (1 hunks)
  • src/features/common/types/plantLocation.d.ts (2 hunks)
  • src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/styles/PlantLocationInfo.module.scss (3 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/MapControls.tsx (4 hunks)
  • src/utils/constants/intervention.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • public/assets/images/icons/InterventionIcon.tsx
  • src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx
  • src/features/common/types/plantLocation.d.ts
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 63-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 80-86: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 171-172: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx

[error] 65-75: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1)

31-44: Improve accessibility and list rendering.

The list implementation needs improvements for accessibility and React best practices:

  1. Using index as key in map function is an anti-pattern
  2. Missing accessibility attributes for interactive elements
  3. Missing semantic HTML structure
-    <ul className={styles.siteListOptions}>
+    <ul className={styles.interventionListOptions} role="listbox">
       {interventionList.map((intervention) => {
         return (
           <li
-            className={`${styles.listItem} ${intervention.value === selectedSiteData?.value ? styles.selectedItem : ''}`}
-            onClick={() => handleFilterSelection(intervention.value)}
-            key={index}
+            className={`${styles.listItem} ${intervention.value === selectedSiteData?.value ? styles.selectedItem : ''}`}
+            onClick={() => handleInterventionSelection(intervention.value)}
+            key={intervention.value}
+            role="option"
+            aria-selected={intervention.value === selectedSiteData?.value}
+            tabIndex={0}
+            onKeyDown={(e) => {
+              if (e.key === 'Enter' || e.key === ' ') {
+                handleInterventionSelection(intervention.value);
+              }
+            }}
           >
             <p>{intervention.label}</p>
           </li>
         );
       })}
     </ul>
src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (2)

48-52: Fix the useEffect logic condition.

The current logic seems reversed. The menu should close when disableInterventionMenu is true, not false.

   useEffect(() => {
-    if(!disableInterventionMenu){
+    if(disableInterventionMenu){
       setIsMenuOpen(false)
     }
   }, [disableInterventionMenu])

61-94: Improve accessibility and remove unnecessary fragments.

The dropdown button needs proper accessibility attributes and the code structure can be improved:

  1. Remove unnecessary fragment
  2. Add proper ARIA attributes for accessibility
  3. Move inline styles to CSS module
-    <>
-      <div className={styles.dropdownButton} onClick={toggleMenu}>
+      <div 
+        className={styles.dropdownButton} 
+        onClick={toggleMenu}
+        role="button"
+        aria-haspopup="listbox"
+        aria-expanded={isMenuOpen}
+        tabIndex={0}
+        onKeyDown={(e) => {
+          if (e.key === 'Enter' || e.key === ' ') {
+            toggleMenu();
+          }
+        }}
+      >
         <div className={styles.siteIconAndTextContainer} >
           <InterventionIcon />
-          <>
             {selectedSiteData && (
               <div className={styles.labelTextContainer}>
                 {isMobile ? <label className={styles.sitesLabel}>
                   {truncateString(selectedSiteData?.label, 40)}
                 </label> :
-                  <p className={styles.siteName} style={{ marginTop: '5px' }}>
+                  <p className={`${styles.siteName} ${styles.siteNameSpacing}`}>
                     {truncateString(selectedSiteData?.label, 40)}
                   </p>}
               </div>
             )}
-          </>

Add to CSS module:

.siteNameSpacing {
  margin-top: 5px;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-75: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

src/features/projectsV2/ProjectDetails/styles/PlantLocationInfo.module.scss (1)

214-216: ⚠️ Potential issue

Fix syntax error in CSS.

Replace the comma with a semicolon in the .interventionMetaDataGroup class.

  .interventionMetaDataGroup {
    display: flex;
-   flex-direction: column,
+   flex-direction: column;
  }

Likely invalid or redundant comment.

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (2)

78-89: 🛠️ Refactor suggestion

Simplify sampleInterventionSpeciesImages logic and add null checks.

The current implementation has redundant checks and potential null reference issues.

 const sampleInterventionSpeciesImages = useMemo(() => {
-  if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
-    const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
+  if (plantLocationInfo?.sampleInterventions?.length > 0) {
+    return plantLocationInfo.sampleInterventions.map((item) => {
       return {
         id: item.coordinates[0].id,
-        image: item.coordinates[0].image ?? '',
+        image: item.coordinates[0]?.image ?? '',
         description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
       };
     });
-    return result;
   }
+  return [];
-}, [plantLocationInfo]);
+}, [plantLocationInfo?.sampleInterventions, tProjectDetails]);

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 80-86: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


61-76: Simplify totalTreesCount calculation using optional chaining.

The current implementation has unnecessary complexity and can be simplified.

 const { totalTreesCount } = useMemo(() => {
   const totalTreesCount =
-    plantLocationInfo &&
-      plantLocationInfo.plantedSpecies &&
-      plantLocationInfo.plantedSpecies.length > 0
+    plantLocationInfo?.plantedSpecies?.length > 0
       ? plantLocationInfo.plantedSpecies.reduce(
         (sum, species: { treeCount: number }) => sum + species.treeCount,
         0
       )
       : 0;
   const area = plantLocationInfo?.geometry
     ? turf.area(plantLocationInfo?.geometry)
     : 0;
   const plantedLocationArea = area / 10000;
   return { totalTreesCount, plantedLocationArea };
-}, [plantLocationInfo?.geometry, plantLocationInfo?.type]);
+}, [plantLocationInfo?.geometry, plantLocationInfo?.plantedSpecies]);

The dependency array should include plantLocationInfo.plantedSpecies since it's used in the calculation.

✅ Verification successful

Dependency array change is correct and necessary.

The suggested changes are valid because:

  • plantLocationInfo.plantedSpecies is used in the calculation but missing from dependencies
  • plantLocationInfo.type can be safely removed as it's not used within this useMemo hook
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Get the complete file content to see all usages of plantLocationInfo.type
cat src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

# Find imports of this component
rg -l "OtherInterventionInfo" --type typescript --type tsx

# Look for similar useMemo patterns with plantLocationInfo
rg "plantLocationInfo\?.type" --type typescript --type tsx -A 2 -B 2

Length of output: 6525


Script:

#!/bin/bash
# Search for similar useMemo patterns with plantedSpecies
rg "plantedSpecies" --type=ts --type=tsx -B 2 -A 2

# Look for other components that might be affected
fd -e tsx -e ts | xargs grep -l "OtherInterventionInfo"

Length of output: 468

🧰 Tools
🪛 Biome (1.9.4)

[error] 63-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +48 to +88
export const AllInterventions: Array<{
label: string
value: INTERVENTION_TYPE
index: number
}> = [
{
label: 'All Intervention',
value: 'all',
index: 0,
},
{
label: 'Single/Multi Tree Plantation',
value: 'default',
index: 1,
},
{
label: 'Single Tree Plantation',
value: 'single-tree-registration',
index: 2,
},
{ label: 'Multi Tree Plantation', value: 'multi-tree-registration', index: 3 },
{ label: 'Fire Patrol', value: 'fire-patrol', index: 4 },
{ label: 'Fire Suppression Team', value: 'fire-suppression', index: 5 },
{ label: 'Establish Fire Breaks', value: 'firebreaks', index: 6 },
{ label: 'Fencing', value: 'fencing', index: 7 },
{
label: 'Removal of Invasive Species',
value: 'removal-invasive-species',
index: 8,
},
{ label: 'Direct Seeding', value: 'direct-seeding', index: 9 },
{ label: 'Grass Suppression', value: 'grass-suppression', index: 10 },
{ label: 'Marking Regenerant', value: 'marking-regenerant', index: 11 },
{ label: 'Enrichment Planting', value: 'enrichment-planting', index: 12 },
{ label: 'Liberating Regenerant', value: 'liberating-regenerant', index: 13 },
{ label: 'Soil Improvement', value: 'soil-improvement', index: 14 },
{ label: 'Assisting Seed Rain', value: 'assisting-seed-rain', index: 15 },
{ label: 'Stop Tree Harvesting', value: 'stop-tree-harvesting', index: 16 },
{ label: 'Maintenance', value: 'maintenance', index: 17 },
{ label: 'Other Intervention', value: 'other-intervention', index: 18 }
]
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

Improve intervention configuration.

Several improvements needed:

  1. Labels should be translatable for internationalization
  2. The index property seems unnecessary as it's always sequential
  3. Consider encapsulating color constants in an object for better maintainability
+import { useTranslation } from 'next-i18next';
+
+const interventionColors = {
+  SINGLE_TREE: '#007A49',
+  MULTI_TREE: '#007A49',
+  INVASIVE_SPECIES: '#EB5757',
+  // ... other colors
+};
+
 export const AllInterventions: Array<{
   label: string
   value: INTERVENTION_TYPE
-  index: number
 }> = [
   {
-    label: 'All Intervention',
+    label: t('interventions.all'),
     value: 'all',
-    index: 0,
   },
   // ... other interventions
 ];

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

Comment on lines 141 to 179
const content = [
<InterventionHeader plHid={plantLocationInfo?.hid} interventionType={plantLocationInfo?.type} key="interventionHeader" />,
shouldDisplayImageCarousel && (
<ImageSlider
key="imageSlider"
images={sampleInterventionSpeciesImages}
type="coordinate"
isMobile={isMobile}
imageSize="large"
allowFullView={!isMobile}
/>
),
<OtherInterventionInfoHeader
key="plantingDetails"
plantDate={plantLocationInfo?.interventionStartDate}
type={plantLocationInfo?.type}
/>,
checkForPublicData.length > 0 && <OtherInterventionMetaData
key="plantingDetails"
metaData={checkForPublicData}
plantDate={plantLocationInfo?.interventionStartDate}
type={plantLocationInfo?.type}
/>,
plantLocationInfo?.plantedSpecies && plantLocationInfo.plantedSpecies.length > 0 && (
<SpeciesPlanted
key="speciesPlanted"
totalTreesCount={totalTreesCount}
plantedSpecies={plantLocationInfo.plantedSpecies}
/>
),
plantLocationInfo &&
plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.length > 0 && (
<SampleTrees
key="sampleTrees"
sampleInterventions={plantLocationInfo.sampleInterventions}
setSelectedSamplePlantLocation={setSelectedSamplePlantLocation}
/>
),
].filter(Boolean);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix duplicate keys and improve conditional rendering in content array.

There are several issues in the content array:

  1. Duplicate key "plantingDetails" between OtherInterventionInfoHeader and OtherInterventionMetaData
  2. Complex conditional rendering can be simplified
 const content = [
   <InterventionHeader plHid={plantLocationInfo?.hid} interventionType={plantLocationInfo?.type} key="interventionHeader" />,
   shouldDisplayImageCarousel && (
     <ImageSlider
       key="imageSlider"
       images={sampleInterventionSpeciesImages}
       type="coordinate"
       isMobile={isMobile}
       imageSize="large"
       allowFullView={!isMobile}
     />
   ),
   <OtherInterventionInfoHeader
     key="plantingDetails"
     plantDate={plantLocationInfo?.interventionStartDate}
     type={plantLocationInfo?.type}
   />,
   checkForPublicData.length > 0 && <OtherInterventionMetaData
-    key="plantingDetails"
+    key="interventionMetaData"
     metaData={checkForPublicData}
     plantDate={plantLocationInfo?.interventionStartDate}
     type={plantLocationInfo?.type}
   />,
   plantLocationInfo?.plantedSpecies?.length > 0 && (
     <SpeciesPlanted
       key="speciesPlanted"
       totalTreesCount={totalTreesCount}
       plantedSpecies={plantLocationInfo.plantedSpecies}
     />
   ),
-  plantLocationInfo &&
-  plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.length > 0 && (
+  plantLocationInfo?.sampleInterventions?.length > 0 && (
     <SampleTrees
       key="sampleTrees"
       sampleInterventions={plantLocationInfo.sampleInterventions}
       setSelectedSamplePlantLocation={setSelectedSamplePlantLocation}
     />
   ),
 ].filter(Boolean);

Additionally, based on the past review comments, consider combining the image slider with the header component for better organization.

📝 Committable suggestion

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

Suggested change
const content = [
<InterventionHeader plHid={plantLocationInfo?.hid} interventionType={plantLocationInfo?.type} key="interventionHeader" />,
shouldDisplayImageCarousel && (
<ImageSlider
key="imageSlider"
images={sampleInterventionSpeciesImages}
type="coordinate"
isMobile={isMobile}
imageSize="large"
allowFullView={!isMobile}
/>
),
<OtherInterventionInfoHeader
key="plantingDetails"
plantDate={plantLocationInfo?.interventionStartDate}
type={plantLocationInfo?.type}
/>,
checkForPublicData.length > 0 && <OtherInterventionMetaData
key="plantingDetails"
metaData={checkForPublicData}
plantDate={plantLocationInfo?.interventionStartDate}
type={plantLocationInfo?.type}
/>,
plantLocationInfo?.plantedSpecies && plantLocationInfo.plantedSpecies.length > 0 && (
<SpeciesPlanted
key="speciesPlanted"
totalTreesCount={totalTreesCount}
plantedSpecies={plantLocationInfo.plantedSpecies}
/>
),
plantLocationInfo &&
plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.length > 0 && (
<SampleTrees
key="sampleTrees"
sampleInterventions={plantLocationInfo.sampleInterventions}
setSelectedSamplePlantLocation={setSelectedSamplePlantLocation}
/>
),
].filter(Boolean);
const content = [
<InterventionHeader plHid={plantLocationInfo?.hid} interventionType={plantLocationInfo?.type} key="interventionHeader" />,
shouldDisplayImageCarousel && (
<ImageSlider
key="imageSlider"
images={sampleInterventionSpeciesImages}
type="coordinate"
isMobile={isMobile}
imageSize="large"
allowFullView={!isMobile}
/>
),
<OtherInterventionInfoHeader
key="plantingDetails"
plantDate={plantLocationInfo?.interventionStartDate}
type={plantLocationInfo?.type}
/>,
checkForPublicData.length > 0 && <OtherInterventionMetaData
key="interventionMetaData"
metaData={checkForPublicData}
plantDate={plantLocationInfo?.interventionStartDate}
type={plantLocationInfo?.type}
/>,
plantLocationInfo?.plantedSpecies?.length > 0 && (
<SpeciesPlanted
key="speciesPlanted"
totalTreesCount={totalTreesCount}
plantedSpecies={plantLocationInfo.plantedSpecies}
/>
),
plantLocationInfo?.sampleInterventions?.length > 0 && (
<SampleTrees
key="sampleTrees"
sampleInterventions={plantLocationInfo.sampleInterventions}
setSelectedSamplePlantLocation={setSelectedSamplePlantLocation}
/>
),
].filter(Boolean);
🧰 Tools
🪛 Biome (1.9.4)

[error] 171-172: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

🧹 Nitpick comments (6)
src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1)

24-27: Rename function for clarity.

The function name handleFilterSelection should be renamed to handleInterventionSelection to better reflect its purpose.

-  const handleFilterSelection = (key: string) => {
+  const handleInterventionSelection = (key: string) => {
     setIsMenuOpen(false);
     setSelectedInterventionType(key);
   };
src/utils/constants/intervention.ts (2)

1-2: Remove unused import.

The PlantLocationMulti type is imported but never used.

 import { DataDrivenPropertyValueSpecification } from "maplibre-gl";
-import { PlantLocation, PlantLocationMulti } from "../../features/common/types/plantLocation";
+import { PlantLocation } from "../../features/common/types/plantLocation";
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 2-2: src/utils/constants/intervention.ts#L2
'PlantLocationMulti' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)


4-21: Encapsulate color constants.

For better maintainability, encapsulate the color constants in an object.

-const SINGLE_TREE = '#007A49';
-const MULTI_TREE = '#007A49';
-const INVASIVE_SPECIES = '#EB5757';
-// ... other color constants

+const interventionColors = {
+  SINGLE_TREE: '#007A49',
+  MULTI_TREE: '#007A49',
+  INVASIVE_SPECIES: '#EB5757',
+  FIRE_SUPPRESSION: '#F2C94C',
+  FIRE_PATROL: '#F2994A',
+  FENCING: '#48AADD',
+  MARKING_REGENERANT: '#27AE60',
+  LIBERATING_REGENERANT: '#56CCF2',
+  GRASS_SUPPRESSION: '#219653',
+  FIREBREAKS: '#E86F56',
+  SEED_RAIN: '#2F80ED',
+  SOIL_IMPROVEMENT: '#6D4230',
+  STOP_HARVESTING: '#4F4F4F',
+  DIRECT_SEEDING: '#6FCF97',
+  ENRICHMENT_PLANTING: '#EB67CE',
+  MAINTENANCE: '#6C63FF',
+  OTHER_INTERVENTION: '#9B51E0'
+} as const;
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (2)

61-76: Simplify optional chaining and separate area calculation.

The current implementation can be improved:

  1. Simplify the optional chaining operators
  2. Separate the area calculation for better memoization
 const { totalTreesCount } = useMemo(() => {
   const totalTreesCount =
-    plantLocationInfo &&
-      plantLocationInfo.plantedSpecies &&
-      plantLocationInfo.plantedSpecies.length > 0
+    plantLocationInfo?.plantedSpecies?.length > 0
       ? plantLocationInfo.plantedSpecies.reduce(
           (sum, species: { treeCount: number }) => sum + species.treeCount,
           0
         )
       : 0;
+  return { totalTreesCount };
+}, [plantLocationInfo?.plantedSpecies]);
+
+const plantedLocationArea = useMemo(() => {
   const area = plantLocationInfo?.geometry
     ? turf.area(plantLocationInfo?.geometry)
     : 0;
-  const plantedLocationArea = area / 10000;
-  return { totalTreesCount, plantedLocationArea };
-}, [plantLocationInfo?.geometry, plantLocationInfo?.type]);
+  return area / 10000;
+}, [plantLocationInfo?.geometry]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 63-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


78-89: Simplify sample interventions mapping and handle undefined case.

The current implementation can be improved:

  1. Simplify the optional chaining
  2. Handle the undefined case explicitly
 const sampleInterventionSpeciesImages = useMemo(() => {
-  if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
-    const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
+  if (plantLocationInfo?.sampleInterventions?.length > 0) {
+    return plantLocationInfo.sampleInterventions.map((item) => {
       return {
         id: item.coordinates[0].id,
         image: item.coordinates[0].image ?? '',
         description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
       };
     });
-    return result;
   }
+  return [];
 }, [plantLocationInfo]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 80-86: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/features/projectsV2/ProjectsContext.tsx (1)

99-100: Remove unnecessary type annotations.

TypeScript can infer the types based on the initial values provided.

-const [selectedInterventionType, setSelectedInterventionType] = useState('all');
-const [disableInterventionMenu, setDisableInterventionMenu] = useState(false);
+const [selectedInterventionType, setSelectedInterventionType] = useState('all');
+const [disableInterventionMenu, setDisableInterventionMenu] = useState(false);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bf4248 and 548994b.

📒 Files selected for processing (11)
  • src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/styles/PlantLocationInfo.module.scss (4 hunks)
  • src/features/projectsV2/ProjectsContext.tsx (5 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.module.scss (1 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/MapControls.tsx (4 hunks)
  • src/features/projectsV2/ProjectsMap/microComponents/PlantLocations.tsx (8 hunks)
  • src/utils/constants/intervention.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.module.scss
  • src/features/projectsV2/ProjectDetails/components/microComponents/InterventionHeader.tsx
  • src/features/projectsV2/ProjectsMap/microComponents/PlantLocations.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 63-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 80-86: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 172-173: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx

[error] 65-75: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🪛 GitHub Check: CodeFactor
src/utils/constants/intervention.ts

[notice] 2-2: src/utils/constants/intervention.ts#L2
'PlantLocationMulti' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionHeader.tsx (1)

1-21: LGTM!

The component is well-structured with proper type definitions, conditional rendering, and CSS module usage.

src/features/projectsV2/ProjectsMap/InterventionDropDown/InterventionList.tsx (1)

30-43: 🛠️ Refactor suggestion

Improve accessibility and list rendering.

The list implementation needs improvements for accessibility and React best practices:

  1. Using index as key in map function is an anti-pattern
  2. Missing accessibility attributes
  3. Missing keyboard navigation support
-    <ul className={styles.interventionListOptions}>
+    <ul className={styles.interventionListOptions} role="listbox">
       {interventionList.map((intervention, index) => {
         return (
           <li
             className={`${styles.listItem} ${intervention.value === selectedInterventionData?.value ? styles.selectedItem : ''}`}
-            onClick={() => handleFilterSelection(intervention.value)}
-            key={index}
+            onClick={() => handleInterventionSelection(intervention.value)}
+            key={intervention.value}
+            role="option"
+            aria-selected={intervention.value === selectedInterventionData?.value}
+            tabIndex={0}
+            onKeyDown={(e) => {
+              if (e.key === 'Enter' || e.key === ' ') {
+                handleInterventionSelection(intervention.value);
+              }
+            }}
           >
             <p>{intervention.label}</p>
           </li>
         );
       })}
     </ul>

Likely invalid or redundant comment.

src/features/projectsV2/ProjectsMap/InterventionDropDown/index.tsx (1)

48-52: ⚠️ Potential issue

Fix the useEffect logic condition.

The current logic seems reversed. The menu should close when disableInterventionMenu is true, not false.

   useEffect(() => {
-    if(!disableInterventionMenu){
+    if(disableInterventionMenu){
       setIsMenuOpen(false)
     }
   }, [disableInterventionMenu])

Likely invalid or redundant comment.

src/utils/constants/intervention.ts (1)

48-88: 🛠️ Refactor suggestion

Improve intervention configuration.

Several improvements needed:

  1. Labels should be translatable for internationalization
  2. The index property seems unnecessary as it's always sequential
  3. Consider pluralizing variable names for clarity
+import { useTranslation } from 'next-i18next';
+
-export const AllInterventions: Array<{
+export const AllInterventionTypes: Array<{
   label: string
   value: INTERVENTION_TYPE
-  index: number
 }> = [
   {
-    label: 'All Intervention',
+    label: t('interventions.all'),
     value: 'all',
-    index: 0,
   },
   {
-    label: 'Single/Multi Tree Plantation',
+    label: t('interventions.default'),
     value: 'default',
-    index: 1,
   },
   // ... other interventions with similar changes
 ];

Likely invalid or redundant comment.

src/features/projectsV2/ProjectsMap/MapControls.tsx (1)

71-90: 🛠️ Refactor suggestion

Update props to match the suggested menu state management.

If you implement the suggested menu state management approach, update the props accordingly:

 const siteDropdownProps = {
   selectedSite,
   setSelectedSite,
   projectSites: singleProject?.sites,
   selectedPlantLocation,
   setSelectedPlantLocation,
   setSelectedSamplePlantLocation,
-  disableInterventionFilter,
-  disableInterventionMenu
+  activeDropdown,
+  setActiveDropdown
 };

 const interventionDropDownProps = {
   selectedInterventionType,
   setSelectedInterventionType,
   allInterventions: AllInterventions,
   selectedPlantLocation,
   setSelectedPlantLocation,
   setSelectedSamplePlantLocation,
-  enableInterventionFilter,
-  disableInterventionMenu
+  activeDropdown,
+  setActiveDropdown
 };

Likely invalid or redundant comment.

src/features/projectsV2/ProjectsContext.tsx (1)

245-246: ⚠️ Potential issue

Add state setters to useEffect dependencies.

The effect resets intervention states but the corresponding state setters are missing from the dependency array.

   }, [
     page,
+    setSelectedInterventionType,
+    setDisableInterventionMenu,
   ]);

Likely invalid or redundant comment.

Comment on lines +61 to +84
<>
<div className={styles.dropdownButton} onClick={toggleMenu}>
<div className={styles.siteIconAndTextContainer} >
<InterventionIcon />
<>
{selectedSiteData && (
<div className={styles.labelTextContainer}>
{isMobile ? <label className={styles.sitesLabel}>{truncateString(selectedSiteData?.label, 40)}
</label> :
<p className={styles.siteName} style={{ marginTop: '5px' }}>
{truncateString(selectedSiteData?.label, 40)}
</p>}
</div>
)}
</>
</div>
<div className={styles.menuArrow}>
{isMenuOpen ? (
<DropdownUpArrow width={10} />
) : (
<DropdownDownArrow width={10} />
)}
</div>
</div>
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

Improve accessibility and remove unnecessary fragments.

The dropdown button needs proper accessibility attributes and the code structure can be improved:

  1. Remove unnecessary fragments
  2. Add proper ARIA attributes
  3. Move inline styles to CSS module
-    <>
-      <div className={styles.dropdownButton} onClick={toggleMenu}>
+      <div 
+        className={styles.dropdownButton} 
+        onClick={toggleMenu}
+        role="button"
+        aria-haspopup="listbox"
+        aria-expanded={isMenuOpen}
+        tabIndex={0}
+        onKeyDown={(e) => {
+          if (e.key === 'Enter' || e.key === ' ') {
+            toggleMenu();
+          }
+        }}
+      >
         <div className={styles.siteIconAndTextContainer} >
           <InterventionIcon />
-          <>
             {selectedSiteData && (
               <div className={styles.labelTextContainer}>
                 {isMobile ? <label className={styles.sitesLabel}>
                   {truncateString(selectedSiteData?.label, 40)}
                 </label> :
-                  <p className={styles.siteName} style={{ marginTop: '5px' }}>
+                  <p className={`${styles.siteName} ${styles.siteNameSpacing}`}>
                     {truncateString(selectedSiteData?.label, 40)}
                   </p>}
               </div>
             )}
-          </>

Add to CSS module:

.siteNameSpacing {
  margin-top: 5px;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-75: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

Comment on lines +15 to +24
.otherInterventionInfoSection {
background: #fff;
border-radius: 12px;
margin-top: 23px;
padding: 12px 12px 24px;
display: flex;
flex-direction: column;
gap: 15px;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
}
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

Address dropdown height and mobile view issues.

Per PR objectives, users reported that the intervention dropdown:

  1. Obscures the satellite switch feature
  2. Is taller than the site dropdown
  3. Overlaps with other dropdowns in mobile view

Add max-height and mobile-specific styles:

.otherInterventionInfoSection {
  background: #fff;
  border-radius: 12px;
  margin-top: 23px;
  padding: 12px 12px 24px;
  display: flex;
  flex-direction: column;
  gap: 15px;
  box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
  max-height: 300px; // Add max-height
  overflow-y: auto;  // Enable scrolling
  
  @media (max-width: 768px) {
    max-height: 250px; // Smaller height for mobile
    position: absolute;
    z-index: 1; // Prevent overlap
  }
}

Comment on lines +64 to +69
const enableInterventionFilter=()=>{
setDisableInterventionMenu(true)
}
const disableInterventionFilter=()=>{
setDisableInterventionMenu(false)
}
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

Improve menu state management logic.

The current implementation has several issues:

  1. The naming is confusing as it uses "disable" and "enable" for what appears to be menu open/close operations.
  2. The functions only set state and could be simplified by directly calling setDisableInterventionMenu.

Consider this alternative approach for better clarity:

-const enableInterventionFilter=()=>{
-  setDisableInterventionMenu(true)
-}
-const disableInterventionFilter=()=>{
-  setDisableInterventionMenu(false)
-}

+const [activeDropdown, setActiveDropdown] = useState<'site' | 'intervention' | null>(null);
+
+const toggleInterventionMenu = () => {
+  setActiveDropdown((prev) => prev === 'intervention' ? null : 'intervention');
+};

This approach:

  1. Uses clear naming that reflects the actual operation
  2. Manages which dropdown is currently active
  3. Allows only one dropdown to be open at a time

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/utils/constants/intervention.ts (2)

4-20: Encapsulate color constants in an object for better maintainability.

Consider grouping the color constants in an object to improve code organization and make it easier to maintain color themes.

-const SINGLE_TREE = '#007A49';
-const MULTI_TREE = '#007A49';
-const INVASIVE_SPECIES = '#EB5757';
-// ... other color constants
+const interventionColors = {
+  SINGLE_TREE: '#007A49',
+  MULTI_TREE: '#007A49',
+  INVASIVE_SPECIES: '#EB5757',
+  // ... other colors
+} as const;

22-44: Consider using a distinctive default color.

The current implementation uses SINGLE_TREE color as the default case. Consider using a more distinctive color for unmatched types to make them easily identifiable on the map.

 export const FillColor: DataDrivenPropertyValueSpecification<string> = [
     'match',
     ['get', 'type'],
     // ... existing matches
-    SINGLE_TREE
+    '#CCCCCC' // neutral gray for unmatched types
 ]
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (3)

1-22: Remove unused imports.

The following imports are not used in the code:

  • Measurements
  • PlantLocationMulti
  • turf
 import type {
-  Measurements,
   PlantedSpecies,
   PlantLocationBase,
-  PlantLocationMulti,
   SamplePlantLocation,
 } from '../../../common/types/plantLocation';
 import type { SetState } from '../../../common/types/common';
 import { useMemo } from 'react';
 import { useTranslations } from 'next-intl';
-import * as turf from '@turf/turf';
 import styles from '../styles/PlantLocationInfo.module.scss';
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 2-2: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L2
'Measurements' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)


[notice] 12-12: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L12
'turf' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)


[notice] 5-5: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L5
'PlantLocationMulti' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)


55-66: Simplify totalTreesCount calculation using optional chaining.

The current implementation has unnecessary complexity in the null checks.

 const { totalTreesCount } = useMemo(() => {
   const totalTreesCount =
-    plantLocationInfo &&
-      plantLocationInfo.plantedSpecies &&
-      plantLocationInfo.plantedSpecies.length > 0
+    plantLocationInfo?.plantedSpecies?.length > 0
       ? plantLocationInfo.plantedSpecies.reduce(
         (sum, species: { treeCount: number }) => sum + species.treeCount,
         0
       )
       : 0;
   return { totalTreesCount };
 }, [plantLocationInfo, plantLocationInfo?.type]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 57-58: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


68-79: Simplify sampleInterventionSpeciesImages logic.

The current implementation has unnecessary complexity and potential undefined access.

 const sampleInterventionSpeciesImages = useMemo(() => {
-  if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
-    const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
+  if (plantLocationInfo?.sampleInterventions?.length > 0) {
+    return plantLocationInfo.sampleInterventions.map((item) => {
       return {
         id: item.coordinates[0].id,
-        image: item.coordinates[0].image ?? '',
+        image: item.coordinates[0]?.image ?? '',
         description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
       };
     });
-    return result;
   }
+  return [];
 }, [plantLocationInfo]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 70-76: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 548994b and 555e3ec.

📒 Files selected for processing (4)
  • src/features/common/types/plantLocation.d.ts (2 hunks)
  • src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/index.tsx (4 hunks)
  • src/utils/constants/intervention.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/features/common/types/plantLocation.d.ts
  • src/features/projectsV2/ProjectsMap/index.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 57-58: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 70-76: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 162-163: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: CodeFactor
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[notice] 2-2: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L2
'Measurements' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)


[notice] 12-12: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L12
'turf' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)


[notice] 5-5: src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx#L5
'PlantLocationMulti' is defined but never used. Allowed unused vars must match /^_/u. (@typescript-eslint/no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
src/utils/constants/intervention.ts (4)

45-45: LGTM! Comprehensive type definition.

The INTERVENTION_TYPE union type is well-defined and includes all necessary intervention types along with special values.


90-90: LGTM! Well-defined plantation types.

The PLANTATION_TYPES constant correctly identifies the plantation-specific intervention types.


93-95: LGTM! Robust type checking.

The helper function correctly handles null cases and uses proper type checking.


48-88: 🛠️ Refactor suggestion

Improve intervention configuration.

Several improvements needed:

  1. The index property seems unnecessary as it's always sequential
  2. Labels should be translatable for internationalization
+import { useTranslations } from 'next-i18next';
+
 export const AllInterventions: Array<{
   label: string
   value: INTERVENTION_TYPE
-  index: number
 }> = [
   {
-    label: 'All Intervention',
+    label: t('interventions.all'),
     value: 'all',
-    index: 0,
   },
   // ... other interventions
 ];

Likely invalid or redundant comment.

src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1)

131-170: ⚠️ Potential issue

Fix duplicate keys and simplify conditional rendering.

Several issues need to be addressed:

  1. Duplicate key "interventionHeader" between components
  2. Complex conditional rendering that can be simplified using optional chaining
 const content = [
   <>
     <InterventionHeader plHid={plantLocationInfo?.hid} interventionType={plantLocationInfo?.type} key="interventionHeader" />
     {shouldDisplayImageCarousel && (
       <ImageSlider
         key="imageSlider"
         images={sampleInterventionSpeciesImages}
         type="coordinate"
         isMobile={isMobile}
         imageSize="large"
         allowFullView={!isMobile}
       />
     )}
   </>,
   <OtherInterventionInfoHeader
-    key="interventionHeader"
+    key="otherInterventionHeader"
     plantDate={plantLocationInfo?.interventionStartDate}
   />,
   checkForPublicData.length > 0 && <OtherInterventionMetaData
     key="plantingDetails"
     metaData={checkForPublicData}
     plantDate={plantLocationInfo?.interventionStartDate}
     type={plantLocationInfo?.type}
   />,
   plantLocationInfo?.plantedSpecies?.length > 0 && (
     <SpeciesPlanted
       key="speciesPlanted"
       totalTreesCount={totalTreesCount}
       plantedSpecies={plantLocationInfo.plantedSpecies}
     />
   ),
-  plantLocationInfo &&
-  plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.length > 0 && (
+  plantLocationInfo?.sampleInterventions?.length > 0 && (
     <SampleTrees
       key="sampleTrees"
       sampleInterventions={plantLocationInfo.sampleInterventions}
       setSelectedSamplePlantLocation={setSelectedSamplePlantLocation}
     />
   ),
 ].filter(Boolean);

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 162-163: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/utils/constants/intervention.ts Show resolved Hide resolved
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 (1)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1)

128-167: ⚠️ Potential issue

Fix duplicate keys and improve content organization.

There are several issues in the content array that need to be addressed:

  1. Duplicate key "interventionHeader" between components
  2. Complex conditional rendering that can be simplified
  3. Consider combining the header with image slider as suggested in past reviews
   const content = [
-    <>
+    <div key="headerSection">
       <InterventionHeader plHid={plantLocationInfo?.hid} interventionType={plantLocationInfo?.type} key="interventionHeader" />
       {shouldDisplayImageCarousel && (
         <ImageSlider
           key="imageSlider"
           images={sampleInterventionSpeciesImages}
           type="coordinate"
           isMobile={isMobile}
           imageSize="large"
           allowFullView={!isMobile}
         />
       )}
-    </>,
+    </div>,
     <OtherInterventionInfoHeader
-      key="interventionHeader"
+      key="otherInterventionHeader"
       plantDate={plantLocationInfo?.interventionStartDate}
     />,
     cleanedPublicMetadata.length > 0 && <OtherInterventionMetaData
       key="plantingDetails"
       metaData={cleanedPublicMetadata}
       plantDate={plantLocationInfo?.interventionStartDate}
       type={plantLocationInfo?.type}
     />,
-    plantLocationInfo?.plantedSpecies && plantLocationInfo.plantedSpecies.length > 0 && (
+    plantLocationInfo?.plantedSpecies?.length > 0 && (
       <SpeciesPlanted
         key="speciesPlanted"
         totalTreesCount={totalTreesCount}
         plantedSpecies={plantLocationInfo.plantedSpecies}
       />
     ),
-    plantLocationInfo &&
-    plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.length > 0 && (
+    plantLocationInfo?.sampleInterventions?.length > 0 && (
       <SampleTrees
         key="sampleTrees"
         sampleInterventions={plantLocationInfo.sampleInterventions}
         setSelectedSamplePlantLocation={setSelectedSamplePlantLocation}
       />
     ),
   ].filter(Boolean);
🧰 Tools
🪛 Biome (1.9.4)

[error] 159-160: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧹 Nitpick comments (3)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (3)

24-30: Remove extra blank lines between interface definitions.

Maintain consistent spacing with a single blank line between interfaces for better code organization.

 }
 
-
-
 interface PublicMetaData {
   [key: string]: string | MetaDataValue;
 }
 
-

94-122: Refactor createCardData for better maintainability.

The function has complex nested logic that could be simplified by extracting the value processing logic into a separate function.

+  const processMetadataValue = (value: string | MetaDataValue, key: string) => {
+    if (typeof value === 'string') {
+      return { value, key };
+    }
+    
+    if (typeof value === 'object' && value !== null && 'value' in value && 'label' in value) {
+      if (isJsonString(value.value)) {
+        try {
+          const parsedValue = JSON.parse(value.value);
+          if (parsedValue && typeof parsedValue === 'object' && 'value' in parsedValue) {
+            return { value: parsedValue.value, key: value.label };
+          }
+        } catch (error) {
+          console.error('Error parsing JSON:', error);
+        }
+      }
+      return { value: value.value, key: value.label };
+    }
+    return null;
+  };
+
   const createCardData = () => {
     const checkForPublic: { key: string; value: string }[] = [];
     const parsedData = plantLocationInfo?.metadata;
 
     if (parsedData?.public && typeof parsedData.public === 'object' && !Array.isArray(parsedData.public)) {
       Object.entries(parsedData.public as PublicMetaData).forEach(([key, value]) => {
-        if (key !== 'isEntireSite') {
-          if (typeof value === 'string') {
-            checkForPublic.push({ value, key });
-          } else if (typeof value === 'object' && value !== null && 'value' in value && 'label' in value) {
-            if (isJsonString(value.value)) {
-              try {
-                const parsedValue = JSON.parse(value.value);
-                if (parsedValue && typeof parsedValue === 'object' && 'value' in parsedValue) {
-                  checkForPublic.push({ value: parsedValue.value, key: value.label });
-                }
-              } catch (error) {
-                console.error('Error parsing JSON:', error);
-              }
-            } else {
-              checkForPublic.push({ value: value.value, key: value.label });
-            }
-          }
+        if (key !== 'isEntireSite') {
+          const processed = processMetadataValue(value, key);
+          if (processed) {
+            checkForPublic.push(processed);
+          }
         }
       });
     }

168-175: Remove unnecessary fragment wrapper.

The fragment wrapper around MobileInfoSwiper is not needed as there's only one child element.

   return isMobile ? (
-    <>
       <MobileInfoSwiper
         slides={content}
         uniqueKey={plantLocationInfo?.hid || ''}
       />
-    </>
   ) : (
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 555e3ec and d7dc806.

📒 Files selected for processing (2)
  • src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx (1 hunks)
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/projectsV2/ProjectDetails/components/microComponents/OtherInterventionMetaData.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/features/projectsV2/ProjectDetails/components/OtherInterventionInfo.tsx

[error] 54-55: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 67-73: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 159-160: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)

Comment on lines +52 to +63
const { totalTreesCount } = useMemo(() => {
const totalTreesCount =
plantLocationInfo &&
plantLocationInfo.plantedSpecies &&
plantLocationInfo.plantedSpecies.length > 0
? plantLocationInfo.plantedSpecies.reduce(
(sum, species: { treeCount: number }) => sum + species.treeCount,
0
)
: 0;
return { totalTreesCount };
}, [plantLocationInfo, plantLocationInfo?.type]);
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

Simplify totalTreesCount calculation using optional chaining.

The current implementation has unnecessary complexity and can be simplified.

   const { totalTreesCount } = useMemo(() => {
     const totalTreesCount =
-      plantLocationInfo &&
-        plantLocationInfo.plantedSpecies &&
-        plantLocationInfo.plantedSpecies.length > 0
+      plantLocationInfo?.plantedSpecies?.length > 0
         ? plantLocationInfo.plantedSpecies.reduce(
           (sum, species: { treeCount: number }) => sum + species.treeCount,
           0
         )
         : 0;
     return { totalTreesCount };
-  }, [plantLocationInfo, plantLocationInfo?.type]);
+  }, [plantLocationInfo?.plantedSpecies]);
📝 Committable suggestion

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

Suggested change
const { totalTreesCount } = useMemo(() => {
const totalTreesCount =
plantLocationInfo &&
plantLocationInfo.plantedSpecies &&
plantLocationInfo.plantedSpecies.length > 0
? plantLocationInfo.plantedSpecies.reduce(
(sum, species: { treeCount: number }) => sum + species.treeCount,
0
)
: 0;
return { totalTreesCount };
}, [plantLocationInfo, plantLocationInfo?.type]);
const { totalTreesCount } = useMemo(() => {
const totalTreesCount =
plantLocationInfo?.plantedSpecies?.length > 0
? plantLocationInfo.plantedSpecies.reduce(
(sum, species: { treeCount: number }) => sum + species.treeCount,
0
)
: 0;
return { totalTreesCount };
}, [plantLocationInfo?.plantedSpecies]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 54-55: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +65 to +76
const sampleInterventionSpeciesImages = useMemo(() => {
if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
return {
id: item.coordinates[0].id,
image: item.coordinates[0].image ?? '',
description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
};
});
return result;
}
}, [plantLocationInfo]);
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

Simplify sampleInterventionSpeciesImages logic and add return type.

The current implementation has unnecessary complexity and lacks a return type annotation.

-  const sampleInterventionSpeciesImages = useMemo(() => {
+  const sampleInterventionSpeciesImages = useMemo((): Array<{
+    id: string;
+    image: string;
+    description: string;
+  }> => {
-    if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
-      const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
+    if (plantLocationInfo?.sampleInterventions?.length > 0) {
+      return plantLocationInfo.sampleInterventions.map((item) => {
         return {
           id: item.coordinates[0].id,
-          image: item.coordinates[0].image ?? '',
+          image: item.coordinates[0]?.image ?? '',
           description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
         };
       });
-      return result;
     }
+    return [];
   }, [plantLocationInfo]);
📝 Committable suggestion

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

Suggested change
const sampleInterventionSpeciesImages = useMemo(() => {
if (plantLocationInfo && plantLocationInfo.sampleInterventions.length > 0) {
const result = plantLocationInfo.sampleInterventions && plantLocationInfo.sampleInterventions.map((item) => {
return {
id: item.coordinates[0].id,
image: item.coordinates[0].image ?? '',
description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
};
});
return result;
}
}, [plantLocationInfo]);
const sampleInterventionSpeciesImages = useMemo((): Array<{
id: string;
image: string;
description: string;
}> => {
if (plantLocationInfo?.sampleInterventions?.length > 0) {
return plantLocationInfo.sampleInterventions.map((item) => {
return {
id: item.coordinates[0].id,
image: item.coordinates[0]?.image ?? '',
description: tProjectDetails('sampleTreeTag', { tag: item.tag }),
};
});
}
return [];
}, [plantLocationInfo]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 67-73: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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.

3 participants