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

Update v2 projects routes, and archive old project pages at /projects-archive #2296

Merged
merged 2 commits into from
Nov 7, 2024

Conversation

mohitb35
Copy link
Collaborator

@mohitb35 mohitb35 commented Nov 7, 2024

  1. Moves new project pages (i.e. v2 pages) to the intended routes - / and /[p] - removing the temporary /prd prefix
  2. Archives old project routes at /projects-archive and /projects-archive/[p] until the old projects code can be removed

Copy link

vercel bot commented Nov 7, 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 Nov 7, 2024 1:13pm
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
planet-webapp ⬜️ Ignored (Inspect) Nov 7, 2024 1:13pm
planet-webapp-temp ⬜️ Ignored (Inspect) Nov 7, 2024 1:13pm

Copy link
Contributor

coderabbitai bot commented Nov 7, 2024

Walkthrough

The pull request introduces significant modifications across several files, primarily focusing on the routing logic and component visibility based on the pathname. Key changes include the introduction of a new URL structure that incorporates "projects-archive" for project-related pages, updates to type definitions for better type safety, and the removal of redundant state management. Additionally, several components have been streamlined to enhance modularity and maintainability, while some files have been deleted as their functionalities have been integrated elsewhere.

Changes

File Path Change Summary
pages/_app.tsx Updated logic for isMap and localShowVideo states based on pathname checks for 'projects-archive'. Modified type definitions for PageProps, PageComponentProps, and AppPropsWithLayout.
pages/sites/[slug]/[locale]/[p].tsx Refactored ProjectDetailsPage to use NextPageWithLayout, simplified state management, and updated rendering logic. Removed complex error handling and nested useEffect hooks.
pages/sites/[slug]/[locale]/index.tsx Replaced Donate component with ProjectListPage, utilizing NextPageWithLayout. Simplified component structure and updated getStaticProps for localization.
pages/sites/[slug]/[locale]/prd/[p].tsx Deleted file containing ProjectDetailsPage component and associated static methods.
pages/sites/[slug]/[locale]/prd/index.tsx Deleted file containing ProjectListPage component and associated static methods.
pages/sites/[slug]/[locale]/projects-archive/[p].tsx Introduced Donate component for project functionalities, handling state and side effects. Added getStaticPaths and getStaticProps for tenant configuration.
pages/sites/[slug]/[locale]/projects-archive/index.tsx Introduced Donate component for managing donations, including state management and error handling. Added getStaticPaths and getStaticProps.
src/features/common/LandingVideo/PlayButton.tsx Updated CSS class logic to reflect new pathname checks for play button visibility.
src/features/common/Layout/Footer/SelectLanguageAndCountry.tsx Modified conditional checks in handleOKClick for pathname updates after language selection.
src/features/projects/components/ProjectSnippet.tsx Changed project detail page URL structure to include "projects-archive".
src/features/projects/components/maps/Explore.tsx Added useLocale hook to manage locale in URL construction for project exploration.
src/features/projects/components/maps/MapHolder.tsx Simplified conditions for displaying MapLayout based on pathname checks.
src/features/projects/components/maps/Markers.tsx Updated project navigation URL structure to include "projects-archive".
src/features/projects/components/maps/Project.tsx Changed routing logic to redirect to new project URL structure with "projects-archive".
src/features/projects/components/maps/ProjectTabs.tsx Updated conditional assignment for containerClasses based on new pathname checks.
src/features/projects/components/maps/SitesDropdown.tsx Modified URL structure in handleChangeSite function to reflect new routing logic.
src/features/projects/screens/SingleProjectDetails.tsx Updated navigation paths in goBack function to align with new URL structure.
src/features/projectsV2/ProjectSnippet/microComponents/ImageSection.tsx Changed fallback navigation path in handleBackButton function to remove static prd segment.
src/features/projectsV2/ProjectsContext.tsx Updated updateProjectDetailsPath function to remove static prd segment from URL path construction.
src/features/projectsV2/ProjectsMap/ProjectMarkers/index.tsx Modified URL structure in visitProject function to remove static prd segment.
src/utils/projectV2.ts Updated generateProjectLink function to remove /prd prefix from returned URL.

Possibly related PRs

Suggested labels

MyForest 2.0, PR: unreviewed

Suggested reviewers

  • sunilsabatp

🐰 In the meadow, changes bloom,
New paths for projects, making room.
With routes so clear, we hop with glee,
For every click, a new journey!
So let’s explore, with joy and cheer,
Our projects thrive, the time is near! 🌼


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

@mohitb35 mohitb35 marked this pull request as ready for review November 7, 2024 13:10
@mohitb35 mohitb35 changed the title Update v2 projects route, and archive old project pages at /projects-archive Update v2 projects routes, and archive old project pages at /projects-archive Nov 7, 2024
Copy link
Contributor

@mariahosfeld mariahosfeld left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@mariahosfeld mariahosfeld merged commit f78ffaa into develop Nov 7, 2024
8 of 9 checks passed
@mariahosfeld mariahosfeld deleted the projects-redesign/route-replacement branch November 7, 2024 13:22
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: 9

🧹 Outside diff range and nitpick comments (23)
src/features/projects/components/maps/MapHolder.tsx (1)

18-19: Consider using exact path matching instead of substring inclusion.

While the simplified condition aligns with the PR objectives, using includes() for path matching could potentially match unintended future routes that contain 'projects-archive' as a substring. Consider using a more precise matching approach.

-    router.pathname.includes('projects-archive') &&
+    router.pathname.startsWith('/projects-archive') &&
src/features/projects/components/maps/ProjectTabs.tsx (1)

20-21: Consider using boolean type for showProjectDetails.

The string comparison showProjectDetails === 'false' suggests that showProjectDetails might be a string when it should ideally be a boolean. Consider updating the type and comparison.

- showProjectDetails === 'false'
+ showProjectDetails === false

Also update the type in the ParamsContext:

interface ParamsContextType {
  // ... other properties
- showProjectDetails: string;
+ showProjectDetails: boolean;
  // ... other properties
}
src/features/projects/components/maps/SitesDropdown.tsx (1)

37-39: Consider adding error handling for invalid navigation.

While the URL structure update is correct, consider adding error handling for cases where project.slug or site ID might be invalid.

 router.push(
-  `/projects-archive/${project.slug}?site=${
-    geoJson.features[event.target.value as unknown as number].properties.id
-  }`
+  `/projects-archive/${project.slug}?site=${
+    geoJson.features[event.target.value as unknown as number]?.properties?.id ?? ''
+  }`,
+  undefined,
+  { shallow: true }
 );
src/features/projectsV2/ProjectsMap/ProjectMarkers/index.tsx (1)

Line range hint 40-49: Consider extracting URL construction logic.

The URL construction with query parameters could be simplified by extracting it into a utility function, making it reusable and easier to maintain.

Consider creating a utility function:

const buildProjectUrl = (
  locale: string,
  projectSlug: string,
  embed?: string,
  callbackUrl?: string
): string => {
  const baseUrl = `/${locale}/${projectSlug}`;
  if (embed !== 'true') return baseUrl;
  
  const params = new URLSearchParams();
  params.append('embed', 'true');
  if (callbackUrl) params.append('callback', callbackUrl);
  
  return `${baseUrl}?${params.toString()}`;
};

Then use it in the component:

-      `/${locale}/${projectSlug}${
-        embed === 'true'
-          ? `${
-              callbackUrl != undefined
-                ? `?embed=true&callback=${callbackUrl}`
-                : '?embed=true'
-            }`
-          : ''
-      }`
+      buildProjectUrl(locale, projectSlug, embed, callbackUrl)
src/features/projects/components/maps/Markers.tsx (1)

Line range hint 52-61: LGTM with a security suggestion.

The URL structure change to use /projects-archive/ aligns well with the PR objectives. However, consider encoding the callback URL to prevent potential XSS attacks.

Apply this diff to improve security:

      `/${locale}/projects-archive/${projectSlug}${
        embed === 'true'
          ? `${
              callbackUrl != undefined
-                ? `?embed=true&callback=${callbackUrl}`
+                ? `?embed=true&callback=${encodeURIComponent(callbackUrl)}`
                : '?embed=true'
            }`
          : ''
      }`
src/features/projects/components/maps/Project.tsx (1)

103-104: Consider making the condition check more explicit.

The current condition could be more explicit about handling null/undefined cases.

-    if (selectedPl)
+    if (selectedPl !== null && selectedPl !== undefined)
src/features/projectsV2/ProjectSnippet/microComponents/ImageSection.tsx (1)

49-49: LGTM! Consider enhancing navigation context.

The removal of /prd prefix aligns with the PR objectives of moving v2 projects to root routes.

Consider enhancing the default navigation by determining if the user is viewing an archived project:

-    const defaultRoute = `/${locale}`;
+    const defaultRoute = page === 'archived-project' 
+      ? `/${locale}/projects-archive`
+      : `/${locale}`;

This would provide a more intuitive navigation experience by returning users to the appropriate project listing page.

src/features/common/Layout/Footer/SelectLanguageAndCountry.tsx (2)

175-175: Fix typo in TODO comment.

The comment contains a typo: "TODOO" should be "TODO".

-    // TODOO - loader while changing the locale
+    // TODO - loader while changing the locale

Line range hint 176-186: Consider refactoring URL manipulation logic.

The current URL manipulation logic using string splitting and joining could be simplified using the URL API for better maintainability and robustness.

Here's a suggested refactor:

-      if (pathname === '/sites/[slug]/[locale]' || pathname === `/${locale}`) {
-        router.replace(encodeURI(`/${modalLanguage}`));
-      } else {
-        const splitPathnames = asPath.split('/');
-        if (splitPathnames.length > 2) {
-          const newPathname = splitPathnames.slice(2).join('/');
-          router.replace(encodeURI(`/${modalLanguage}/${newPathname}`));
-        } else {
-          router.replace(encodeURI(`/${modalLanguage}`));
-        }
-      }
+      const url = new URL(asPath, window.location.origin);
+      const pathSegments = url.pathname.split('/').filter(Boolean);
+      
+      if (pathname === '/sites/[slug]/[locale]' || pathname === `/${locale}`) {
+        router.replace(`/${modalLanguage}`);
+      } else {
+        const newPathname = pathSegments.length > 1
+          ? `/${modalLanguage}/${pathSegments.slice(1).join('/')}`
+          : `/${modalLanguage}`;
+        router.replace(newPathname);
+      }

This refactor:

  • Uses the URL API for more robust path manipulation
  • Simplifies the logic by reducing nesting
  • Removes redundant encodeURI calls as Next.js router handles encoding
src/features/projects/screens/SingleProjectDetails.tsx (1)

Line range hint 103-110: Consider extracting the base path as a constant.

The changes correctly implement the new routing structure. However, to improve maintainability, consider extracting the base path as a constant:

+ const PROJECTS_ARCHIVE_BASE_PATH = '/projects-archive';

  router.replace({
-   pathname: `/${locale}/projects-archive`,
+   pathname: `/${locale}${PROJECTS_ARCHIVE_BASE_PATH}`,
    query: {
      ...(isEmbed ? { embed: 'true' } : {}),
      ...(isEmbed && callbackUrl !== undefined
        ? { callback: callbackUrl }
        : {}),
    },
  });

This would:

  1. Make it easier to update the path in the future
  2. Ensure consistency across both router.push and router.replace calls
  3. Reduce the risk of typos
src/features/projects/components/ProjectSnippet.tsx (1)

Line range hint 123-135: LGTM! Consider using URL utility for better maintainability.

The URL construction for the projects archive aligns with the PR objectives. However, consider using a URL utility function to handle the path construction, making it more maintainable and reusable across components.

+ // Add to a shared utility file (e.g., src/utils/urlHelpers.ts)
+ export const getProjectArchiveUrl = (
+   locale: string,
+   slug: string,
+   embed?: string,
+   callback?: string
+ ) => {
+   const base = `/${locale}/projects-archive/${slug}`;
+   if (embed !== 'true') return base;
+   return `${base}${callback ? `?embed=true&callback=${callback}` : '?embed=true'}`;
+ };

  // In ProjectSnippet.tsx
- router.push(
-   `/${locale}/projects-archive/${project.slug}${
-     embed === 'true'
-       ? `${
-           callbackUrl != undefined
-             ? `?embed=true&callback=${callbackUrl}`
-             : '?embed=true'
-         }`
-       : ''
-   }`
- );
+ router.push(getProjectArchiveUrl(locale, project.slug, embed, callbackUrl));
pages/_app.tsx (3)

Line range hint 171-175: Consider using route constants for path checking.

While the logic is correct, using string literals for path checking can be fragile if route patterns change. Consider defining route constants to make the code more maintainable.

+// Add to a constants file
+export const ROUTES = {
+  PROJECTS_ARCHIVE: 'projects-archive'
+} as const;

-    if (router.pathname.includes('projects-archive')) {
+    if (router.pathname.includes(ROUTES.PROJECTS_ARCHIVE)) {

Line range hint 210-224: Several improvements needed for video visibility logic.

The current implementation has several issues that should be addressed:

  1. The pathname check is inconsistent with the map visibility logic (endsWith vs includes).
  2. Direct localStorage access without error handling could throw in some browsers.
  3. Missing cleanup in useEffect could cause memory leaks.
  4. Direct localStorage mutation without proper state management.

Here's a suggested improvement:

+const VIDEO_STORAGE_KEY = 'showVideo';

+const getStoredVideoPreference = () => {
+  try {
+    return localStorage.getItem(VIDEO_STORAGE_KEY) === 'true';
+  } catch (e) {
+    console.error('Failed to access localStorage:', e);
+    return true; // default value
+  }
+};

+const setStoredVideoPreference = (value: boolean) => {
+  try {
+    localStorage.setItem(VIDEO_STORAGE_KEY, String(value));
+  } catch (e) {
+    console.error('Failed to store video preference:', e);
+  }
+};

 React.useEffect(() => {
-    if (router.pathname.endsWith('projects-archive')) {
+    if (router.pathname.includes(ROUTES.PROJECTS_ARCHIVE)) {
       if (typeof window !== 'undefined') {
-        if (localStorage.getItem('showVideo')) {
-          if (localStorage.getItem('showVideo') === 'true') {
-            setLocalShowVideo(true);
-          } else {
-            setLocalShowVideo(false);
-          }
-        } else {
-          localStorage.setItem('showVideo', 'true');
-          setLocalShowVideo(true);
-        }
+        const preference = getStoredVideoPreference();
+        if (!preference) setStoredVideoPreference(true);
+        setLocalShowVideo(preference);
       }
     } else {
       setLocalShowVideo(false);
     }
+    return () => {
+      // Cleanup if needed
+    };
-  }, []);
+  }, [router.pathname]);

Line range hint 11-13: Plan cleanup of old projects code.

There are several TODO comments indicating that old projects code needs to be removed. Consider:

  1. Creating a tracking issue for the cleanup
  2. Documenting which components and styles are part of the old implementation
  3. Planning a timeline for the removal to avoid technical debt accumulation

Would you like me to help create a GitHub issue to track this cleanup task?

Also applies to: 15-16

src/features/projects/components/maps/Explore.tsx (2)

Line range hint 172-183: Security: Validate callback URL to prevent open redirect vulnerability.

The callbackUrl parameter is used directly in URL construction without validation, which could lead to open redirect vulnerabilities.

Consider adding URL validation:

 router.push(
-  `${locale}/projects-archive${
-    embed === 'true'
-      ? `${
-          callbackUrl != undefined
-            ? `?embed=true&callback=${callbackUrl}`
-            : '?embed=true'
-        }`
-      : ''
-  }`,
+  `${locale}/projects-archive${
+    embed === 'true'
+      ? `?embed=true${
+          callbackUrl != undefined && isValidUrl(callbackUrl)
+            ? `&callback=${encodeURIComponent(callbackUrl)}`
+            : ''
+        }`
+      : ''
+  }`,
   undefined,
   {
     shallow: true,
   }
 );

// Add this helper function
+ function isValidUrl(url: string): boolean {
+   try {
+     const parsedUrl = new URL(url);
+     // Add additional validation rules as needed
+     return ['http:', 'https:'].includes(parsedUrl.protocol);
+   } catch (e) {
+     return false;
+   }
+ }

Line range hint 172-183: Refactor: Simplify URL construction logic.

The URL construction using template literals is complex and could be simplified for better maintainability.

Consider extracting the URL construction logic:

+ const buildProjectsArchiveUrl = (
+   locale: string,
+   embed: string,
+   callbackUrl?: string
+ ): string => {
+   const params = new URLSearchParams();
+   if (embed === 'true') {
+     params.set('embed', 'true');
+     if (callbackUrl && isValidUrl(callbackUrl)) {
+       params.set('callback', callbackUrl);
+     }
+   }
+   const queryString = params.toString();
+   return `${locale}/projects-archive${queryString ? `?${queryString}` : ''}`;
+ };

 router.push(
-  `${locale}/projects-archive${
-    embed === 'true'
-      ? `${
-          callbackUrl != undefined
-            ? `?embed=true&callback=${callbackUrl}`
-            : '?embed=true'
-        }`
-      : ''
-  }`,
+  buildProjectsArchiveUrl(locale, embed, callbackUrl),
   undefined,
   {
     shallow: true,
   }
 );
src/features/projectsV2/ProjectsContext.tsx (2)

Line range hint 371-379: Consider handling invalid site index more explicitly.

In the site selection logic, when handling a direct link with an invalid site ID, the code silently falls back to index 0. Consider making this fallback behavior more explicit and possibly logging a warning for debugging purposes.

 if (index !== undefined) {
+  if (index === -1) {
+    console.warn(`Invalid site ID: ${requestedSite}, falling back to first site`);
+  }
   updateSiteAndUrl(locale, singleProject.slug, index !== -1 ? index : 0);
   return;
 }

Line range hint 252-266: Enhance type safety for query parameters.

Consider creating a type for the expected query parameters to improve type safety and maintainability.

type ProjectQueryParams = {
  locale?: string;
  slug?: string;
  p?: string;
  ploc?: string;
  site?: string;
  [key: string]: string | undefined;
};

const updateProjectDetailsPath = (
  locale: string,
  projectSlug: string,
  queryParams: ProjectQueryParams = {}
) => {
  // ... rest of the function
};
pages/sites/[slug]/[locale]/index.tsx (2)

1-5: Import types from 'next' instead of 'next/types'

It's standard practice to import Next.js types from 'next' rather than 'next/types'. Importing from 'next' ensures compatibility and follows conventional usage.

Apply this diff to adjust the import:

-import type {
-  GetStaticProps,
-  GetStaticPropsContext,
-  GetStaticPropsResult,
-} from 'next/types';
+import type {
+  GetStaticProps,
+  GetStaticPropsContext,
+  GetStaticPropsResult,
+} from 'next';

43-48: Consider removing unnecessary as const assertion

The as const assertion on layoutProps may be unnecessary unless you need to enforce literal types for its properties. Removing it can simplify the code without affecting functionality.

Apply this diff to remove the as const:

   const layoutProps = {
     currencyCode: pageComponentProps.currencyCode,
     setCurrencyCode: pageComponentProps.setCurrencyCode,
     page: 'project-list',
     isMobile: pageComponentProps.isMobile,
-  } as const;
+  };
pages/sites/[slug]/[locale]/projects-archive/[p].tsx (3)

206-220: Simplify conditional rendering for better readability

The return statement contains unnecessary fragments and empty elements, making the code less readable.

Simplify the conditional rendering as follows:

return pageProps.tenantConfig ? (
  <>
    {project && <ProjectDetailsMeta project={project} />}
    {project && <SingleProjectDetails />}
    <Credits setCurrencyCode={setCurrencyCode} />
  </>
) : null;

223-240: Generate paths for all supported locales in getStaticPaths

In getStaticPaths, only 'en' is used as the locale (line 231). If your application supports multiple locales, you should generate paths for each to ensure proper localization.

Modify getStaticPaths to include all supported locales:

- locale: 'en',
+ locale,

You'll need to loop over your supported locales when constructing the paths.


248-264: Validate and fallback the locale in getStaticProps

In getStaticProps, the locale is directly taken from context.params?.locale without validation, which could lead to issues if an unsupported locale is provided.

Ensure that the locale is valid and provide a fallback if necessary:

const locale = validateLocale(context.params?.locale) ? context.params?.locale : 'en';

Implement a validateLocale function or use existing utilities to check for supported locales.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7c9ed20 and 9511b68.

📒 Files selected for processing (21)
  • pages/_app.tsx (2 hunks)
  • pages/sites/[slug]/[locale]/[p].tsx (3 hunks)
  • pages/sites/[slug]/[locale]/index.tsx (2 hunks)
  • pages/sites/[slug]/[locale]/prd/[p].tsx (0 hunks)
  • pages/sites/[slug]/[locale]/prd/index.tsx (0 hunks)
  • pages/sites/[slug]/[locale]/projects-archive/[p].tsx (1 hunks)
  • pages/sites/[slug]/[locale]/projects-archive/index.tsx (1 hunks)
  • src/features/common/LandingVideo/PlayButton.tsx (1 hunks)
  • src/features/common/Layout/Footer/SelectLanguageAndCountry.tsx (1 hunks)
  • src/features/projects/components/ProjectSnippet.tsx (1 hunks)
  • src/features/projects/components/maps/Explore.tsx (3 hunks)
  • src/features/projects/components/maps/MapHolder.tsx (1 hunks)
  • src/features/projects/components/maps/Markers.tsx (1 hunks)
  • src/features/projects/components/maps/Project.tsx (1 hunks)
  • src/features/projects/components/maps/ProjectTabs.tsx (1 hunks)
  • src/features/projects/components/maps/SitesDropdown.tsx (3 hunks)
  • src/features/projects/screens/SingleProjectDetails.tsx (2 hunks)
  • src/features/projectsV2/ProjectSnippet/microComponents/ImageSection.tsx (1 hunks)
  • src/features/projectsV2/ProjectsContext.tsx (1 hunks)
  • src/features/projectsV2/ProjectsMap/ProjectMarkers/index.tsx (1 hunks)
  • src/utils/projectV2.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • pages/sites/[slug]/[locale]/prd/[p].tsx
  • pages/sites/[slug]/[locale]/prd/index.tsx
🔇 Additional comments (23)
src/features/common/LandingVideo/PlayButton.tsx (2)

24-25: LGTM! Path updates align with project archival strategy.

The pathname checks have been correctly updated to use the new /projects-archive/[p] routes, which aligns with the PR objective of archiving old project pages.


24-25: Verify consistent pathname updates across the codebase.

Let's ensure all related components have been updated to use the new /projects-archive path pattern consistently.

✅ Verification successful

Path pattern /projects-archive/[p] is consistently used across the codebase

The verification shows that all components using the [p] path parameter are consistently using the /projects-archive/[p] pattern:

  • src/features/common/LandingVideo/PlayButton.tsx
  • src/features/projects/components/maps/SitesDropdown.tsx
  • src/features/projects/components/maps/ProjectTabs.tsx

Each component properly handles both the direct path /projects-archive/[p] and where applicable, the nested path /sites/[slug]/[locale]/projects-archive/[p].

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining old project path patterns that might need updating

# Test 1: Search for old path patterns that might need updating
echo "Checking for potential missed path updates..."
rg -l "'/\[p\]'" --type ts --type tsx

# Test 2: Verify new path pattern usage is consistent
echo "Verifying new path pattern usage..."
rg -l "'/projects-archive/\[p\]'" --type ts --type tsx

# Test 3: Check for any mixed usage of old and new patterns
echo "Checking for components that might have mixed path patterns..."
rg "pathname.*\[p\]" --type ts --type tsx

Length of output: 553


Script:

#!/bin/bash
# Let's try with correct ripgrep file type options and proper escaping

# Test 1: Search for any path patterns with [p]
echo "Checking path patterns with [p]..."
rg --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -l "pathname.*\[p\]" 

# Test 2: Look specifically for the projects-archive pattern
echo "Checking projects-archive patterns..."
rg --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -l "projects-archive/\[p\]"

# Test 3: Get more context around the pathname usages
echo "Checking pathname context..."
rg --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -A 2 -B 2 "pathname.*\[p\]"

Length of output: 2773

src/features/projects/components/maps/ProjectTabs.tsx (1)

20-21: LGTM! Route change aligns with PR objectives.

The updated condition correctly handles the new /projects-archive/[p] route structure, which is consistent with the PR's goal of archiving old project routes.

src/features/projects/components/maps/SitesDropdown.tsx (1)

47-49: LGTM: Consistent pathname checks for archived projects.

The pathname checks are correctly updated to reflect the new routing structure with "/projects-archive/", maintaining consistent styling logic across the component.

Also applies to: 57-59

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

Line range hint 40-49: Verify handling of archived projects.

The URL structure change aligns with the PR objectives by removing the /prd prefix. However, we should verify if archived projects need to be handled differently.

Let's check if there are any conditions that determine whether a project should use the archive route:

src/features/projects/components/maps/Project.tsx (1)

103-104: LGTM! Routing change aligns with PR objectives.

The URL path modification correctly implements the new routing structure by redirecting to /projects-archive/${project.slug}, maintaining the plant location query parameter.

src/features/common/Layout/Footer/SelectLanguageAndCountry.tsx (1)

176-176: LGTM: Additional pathname check for root-level locale paths.

The added condition correctly handles locale switching for root-level paths (e.g., /en, /de), which aligns with the PR's objective of moving v2 pages to root routes.

src/utils/projectV2.ts (2)

219-221: LGTM! URL structure simplified as intended.

The removal of the /prd prefix aligns with the PR objective to relocate v2 project pages to root routes.


219-221: Verify handling of existing /prd URLs.

While the URL structure change is correct, we should ensure proper handling of existing bookmarked URLs.

Let's check for any remaining /prd references and verify redirect handling:

src/features/projects/screens/SingleProjectDetails.tsx (1)

Line range hint 88-97: LGTM: URL path update aligns with archival requirements.

The modification correctly implements the new /projects-archive route structure while preserving the existing query parameter handling for embedded views and callbacks.

src/features/projects/components/maps/Explore.tsx (2)

5-5: LGTM: Import addition aligns with localization needs.

The addition of useLocale import is appropriate for handling localized routes in the new URL structure.


Line range hint 172-183: Verify locale handling in URL construction.

The code assumes the locale value is always valid and available. We should verify how invalid or missing locales are handled.

✅ Verification successful

Let me gather more information about the locale handling by examining the identified configuration files.


Based on the gathered information, I can now provide the final response:

Locale handling is properly implemented and validated at the middleware level

The locale handling in the URL construction is safe because:

  • The middleware (middleware.ts) validates locales against supported languages and provides fallback to default locale
  • Invalid or missing locales are automatically handled through:
    • Validation against i18nConfig.locales which defines supported locales (en, de, cs, es, fr, it, pt-BR)
    • Tenant-specific locale filtering via commonSupportedLocales
    • Fallback to defaultLocale: 'en' when errors occur
  • The useLocale() hook used in the Explore component is provided by the framework and guaranteed to return a valid locale
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for locale validation in the codebase

# Look for locale validation patterns
echo "Searching for locale validation patterns..."
rg -A 3 "useLocale|getLocale|validateLocale" --type ts --type tsx

# Look for locale-related error handling
echo "Searching for locale-related error handling..."
rg -A 3 "defaultLocale|fallbackLocale" --type ts --type tsx

# Look for middleware or configuration files that might handle locale
echo "Searching for locale configuration..."
fd -e ts -e js "middleware|i18n|locale"

Length of output: 549


Script:

#!/bin/bash
# Check the content of locale-related configuration files
echo "=== Content of i18n-config.ts ==="
cat i18n-config.ts

echo -e "\n=== Content of i18n.ts ==="
cat i18n.ts

echo -e "\n=== Content of middleware.ts ==="
cat middleware.ts

# Search for locale usage in the specific component
echo -e "\n=== Checking locale usage in Explore component ==="
rg -A 5 "locale" src/features/projects/components/maps/Explore.tsx || true

# Look for any locale-related hooks or context usage
echo -e "\n=== Checking for locale-related hooks or context ==="
ast-grep --pattern 'const $_ = use$_()' src/features/projects/components/maps/Explore.tsx || true

Length of output: 10149

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

253-253: LGTM! Verify the impact of URL structure change.

The removal of '/prd' from the pathname aligns with the PR objectives. The implementation correctly maintains the locale and project slug while properly handling query parameters.

Let's verify that no other components still expect the '/prd' prefix:

✅ Verification successful

URL path structure change is safe to proceed

Based on the comprehensive search results, the removal of '/prd' from the pathname is safe as there are no remaining references to this prefix in the codebase. All project-related URL constructions follow the new pattern of /${locale}/${projectSlug}, consistent with the change in ProjectsContext.tsx. The URL handling across components (ProjectSnippet, ProjectMarkers, ProjectDetails) all align with this structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to '/prd' in the codebase
rg "/prd" --type tsx --type ts

Length of output: 58


Script:

#!/bin/bash
# Search for any remaining references to '/prd' in the codebase using ripgrep
# Note: Using --type-add to properly recognize TypeScript/TSX files
rg "/prd" --type-add 'typescript:*.{ts,tsx}' --type typescript

Length of output: 62


Script:

#!/bin/bash
# Let's try a more comprehensive search for URL patterns in TypeScript files
# Search for route definitions and URL manipulations
rg -A 2 -B 2 "pathname\s*=|route\s*=|path\s*=" --type-add 'typescript:*.{ts,tsx}' --type typescript

# Also search for any project-related route handling
rg -A 2 -B 2 "projectSlug|projectId.*route" --type-add 'typescript:*.{ts,tsx}' --type typescript

Length of output: 17335

pages/sites/[slug]/[locale]/[p].tsx (9)

1-6: Appropriate use of TypeScript imports for Next.js and React types

The imports for GetStaticProps, GetStaticPropsContext, GetStaticPropsResult, and ReactElement enhance type safety and clarity in your Next.js application.


7-11: Consistent import of custom page component types

Importing NextPageWithLayout, PageComponentProps, and PageProps from your _app ensures consistent typing across your application, promoting maintainability.


19-25: Correctly importing necessary hooks and components

The imports for useRouter, useTenant, useEffect, v4, ProjectsLayout, MobileProjectsLayout, and ProjectDetails are appropriately included, setting up the component for proper functionality.


27-31: Simplified component props destructuring for better readability

Destructuring pageProps, currencyCode, and isMobile directly in the component parameters improves readability and reduces the need for an explicit Props interface.


35-40: Effective use of useEffect to set tenant configuration

Using useEffect with router.isReady to set the tenant configuration ensures that the configuration is applied once the router is ready, preventing potential issues with uninitialized routes.


41-42: Rendering ProjectDetails with necessary props

Passing currencyCode and isMobile to the ProjectDetails component aligns with the expected prop interface, ensuring consistent behavior across different devices.


44-59: Conditional layout rendering based on device type

The getLayout function effectively switches between MobileProjectsLayout and ProjectsLayout based on the isMobile prop, promoting a responsive design that adapts to different screen sizes.


77-77: Using fallback: 'blocking' in getStaticPaths

Setting fallback to 'blocking' allows for dynamic generation of pages not generated at build time, which is appropriate for handling a large number of paths.


90-99: Expanded localization support with additional message files

Including more filenames in getMessagesForPage, such as 'allProjects', 'projectDetails', 'donate', etc., enhances the application's internationalization capabilities, supporting a wider range of localized content.

pages/sites/[slug]/[locale]/projects-archive/index.tsx (1)

89-95: ⚠️ Potential issue

Include router.query.p in the useEffect dependencies

The useEffect hook relies on router.query.p, but the dependency array only includes [router]. To ensure the effect runs when router.query.p changes, include it in the dependency array.

Apply this diff to update the dependency array:

-  }, [router]);
+  }, [router.query.p]);

Likely invalid or redundant comment.

Comment on lines +30 to 34
useEffect(() => {
if (router.isReady) {
setTenantConfig(pageProps.tenantConfig);
}
}, [router.isReady]);
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

Include all dependencies in the useEffect dependency array

The useEffect hook depends on router.isReady, setTenantConfig, and pageProps.tenantConfig. To comply with React's Hooks rules and prevent potential bugs, include all these dependencies in the dependency array.

Apply this diff to update the dependency array:

 useEffect(() => {
   if (router.isReady) {
     setTenantConfig(pageProps.tenantConfig);
   }
-}, [router.isReady]);
+}, [router.isReady, setTenantConfig, pageProps.tenantConfig]);
📝 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
useEffect(() => {
if (router.isReady) {
setTenantConfig(pageProps.tenantConfig);
}
}, [router.isReady]);
useEffect(() => {
if (router.isReady) {
setTenantConfig(pageProps.tenantConfig);
}
}, [router.isReady, setTenantConfig, pageProps.tenantConfig]);

Comment on lines +68 to +72
React.useEffect(() => {
if (router.isReady) {
setTenantConfig(pageProps.tenantConfig);
}
}, [router.isReady]);
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

Add missing dependency pageProps.tenantConfig to the useEffect hook

The useEffect hook depends on pageProps.tenantConfig, but the dependency array only includes [router.isReady]. To ensure that setTenantConfig is called whenever pageProps.tenantConfig changes, include it in the dependency array.

Apply this diff to include the missing dependency:

-  }, [router.isReady]);
+  }, [router.isReady, pageProps.tenantConfig]);
📝 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
React.useEffect(() => {
if (router.isReady) {
setTenantConfig(pageProps.tenantConfig);
}
}, [router.isReady]);
React.useEffect(() => {
if (router.isReady) {
setTenantConfig(pageProps.tenantConfig);
}
}, [router.isReady, pageProps.tenantConfig]);

Comment on lines +104 to +138
React.useEffect(() => {
async function loadProjects() {
if (
!internalCurrencyCode ||
currencyCode !== internalCurrencyCode ||
internalLanguage !== locale
) {
const currency = getStoredCurrency();
setInternalCurrencyCode(currency);
setCurrencyCode(currency);
setInternalLanguage(locale);
try {
const projects = await getRequest<MapProject[]>(
pageProps.tenantConfig.id,
`/app/projects`,
{
_scope: 'map',
currency: currency,
tenant: pageProps.tenantConfig.id,
'filter[purpose]': 'trees,conservation',
locale: locale,
}
);
setProjects(projects);
setProject(null);
setShowSingleProject(false);
setZoomLevel(1);
} catch (err) {
setErrors(handleError(err as APIError));
redirect('/');
}
}
}
loadProjects();
}, [currencyCode, locale]);
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

Add missing dependencies to the useEffect hook for loading projects

The useEffect hook depends on internalCurrencyCode, currencyCode, internalLanguage, and locale, but the dependency array only includes [currencyCode, locale]. To ensure that the effect responds to changes in all relevant variables, include them in the dependency array.

Apply this diff to update the dependency array:

-  }, [currencyCode, locale]);
+  }, [internalCurrencyCode, internalLanguage, currencyCode, locale]);
📝 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
React.useEffect(() => {
async function loadProjects() {
if (
!internalCurrencyCode ||
currencyCode !== internalCurrencyCode ||
internalLanguage !== locale
) {
const currency = getStoredCurrency();
setInternalCurrencyCode(currency);
setCurrencyCode(currency);
setInternalLanguage(locale);
try {
const projects = await getRequest<MapProject[]>(
pageProps.tenantConfig.id,
`/app/projects`,
{
_scope: 'map',
currency: currency,
tenant: pageProps.tenantConfig.id,
'filter[purpose]': 'trees,conservation',
locale: locale,
}
);
setProjects(projects);
setProject(null);
setShowSingleProject(false);
setZoomLevel(1);
} catch (err) {
setErrors(handleError(err as APIError));
redirect('/');
}
}
}
loadProjects();
}, [currencyCode, locale]);
React.useEffect(() => {
async function loadProjects() {
if (
!internalCurrencyCode ||
currencyCode !== internalCurrencyCode ||
internalLanguage !== locale
) {
const currency = getStoredCurrency();
setInternalCurrencyCode(currency);
setCurrencyCode(currency);
setInternalLanguage(locale);
try {
const projects = await getRequest<MapProject[]>(
pageProps.tenantConfig.id,
`/app/projects`,
{
_scope: 'map',
currency: currency,
tenant: pageProps.tenantConfig.id,
'filter[purpose]': 'trees,conservation',
locale: locale,
}
);
setProjects(projects);
setProject(null);
setShowSingleProject(false);
setZoomLevel(1);
} catch (err) {
setErrors(handleError(err as APIError));
redirect('/');
}
}
}
loadProjects();
}, [internalCurrencyCode, internalLanguage, currencyCode, locale]);

}
} catch (err) {
setErrors(handleError(err as APIError | ClientError));
redirect('/');
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 7, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Include locale in the error redirect

When redirecting after an error in line 120, the path '/' doesn't include the locale, which may result in the user landing on a page with the wrong language.

Modify the redirect call to include locale:

- redirect('/');
+ redirect(`/${locale}/`);
📝 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
redirect('/');
redirect(`/${locale}/`);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Add this as an issue, as it is many places and is not related to this PR specifically

Copy link
Contributor

Choose a reason for hiding this comment

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

@mohitb35, I've created the issue to track this problem across the codebase: #2297.

I've noted this for future reviews.

🔗 Analysis chain

@mohitb35, understood. I'll create a new issue to track this problem across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Create a new GitHub issue to address the locale parameter in redirects
gh issue create \
  --title "Redirects should include locale parameter" \
  --body "In multiple places across the codebase, redirects after errors do not include the \`locale\` in the path. This may result in users landing on pages with the wrong language.

**PR:** https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296

**Comment:** https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296#discussion_r1832677705

Reported by @mohitb35." \
  --assignee mohitb35

Length of output: 545


✏️ Learnings added
Learnt from: mohitb35
PR: Plant-for-the-Planet-org/planet-webapp#2296
File: pages/sites/[slug]/[locale]/projects-archive/[p].tsx:120-120
Timestamp: 2024-11-07T13:33:42.538Z
Learning: When redirecting after an error, ensure that the redirect includes the `locale` parameter in the path to prevent users from landing on a page with the wrong language.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

return router.query.site === singleSite?.properties.id;
});
if (siteIndex === -1) {
router.push(`/projects-archive/${project.slug}`);
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 7, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Include locale in the redirect path

In line 183, when redirecting, the path does not include the locale, which could lead to incorrect routing in a multi-language setup.

Update the redirect path to include the locale:

- router.push(`/projects-archive/${project.slug}`);
+ router.push(`/${locale}/projects-archive/${project.slug}`);
📝 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
router.push(`/projects-archive/${project.slug}`);
router.push(`/${locale}/projects-archive/${project.slug}`);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

add this as an issue, along with similar points. I'll address this later

Copy link
Contributor

Choose a reason for hiding this comment

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

@mohitb35, I've opened a new GitHub issue regarding the missing locale in redirect paths and similar points for you to address later. You can find it here: Issue #2299.

🔗 Analysis chain

@mohitb35, I've opened a new GitHub issue with this point and similar ones for you to address later.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Create a new GitHub issue regarding missing 'locale' in redirect paths
gh issue create \
  --title "Missing 'locale' in redirect paths leading to incorrect routing" \
  --body "There are instances in the codebase where the 'locale' parameter is not included in redirect paths, which could lead to incorrect routing in a multi-language setup.

Reference: PR [#2296](https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296) and [this comment](https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296#discussion_r1832677708).

@mojitb35" \
  --assignee mohitb35

Length of output: 582

});

if (singlePlantLocation === undefined) {
router.push(`/projects-archive/${project.slug}`);
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 7, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Include locale in the redirect path

Similarly, in line 199, the redirect path lacks the locale, which is important for proper localization.

Adjust the redirect path:

- router.push(`/projects-archive/${project.slug}`);
+ router.push(`/${locale}/projects-archive/${project.slug}`);
📝 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
router.push(`/projects-archive/${project.slug}`);
router.push(`/${locale}/projects-archive/${project.slug}`);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

add this as an issue, along with similar points. I'll address this later

Copy link
Contributor

Choose a reason for hiding this comment

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

@mohitb35, I have created an issue to track this, along with the similar points. You can find it here: #2298

🔗 Analysis chain

@mohitb35, I'll create an issue to track this, along with the similar points.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Create a GitHub issue to track inclusion of 'locale' in redirect paths
gh issue create \
  --title "Include 'locale' in redirect paths for proper localization" \
  --body "As discussed in [PR #2296](https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296), there are instances where redirect paths lack the \`locale\`, which is essential for proper localization. This issue aims to update all redirect paths to include the \`locale\` parameter.

Referenced from [this comment](https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296#discussion_r1832677709) by @mohitb35." \
  --assignee mohitb35

Length of output: 610

Comment on lines +176 to +188
React.useEffect(() => {
//for selecting one of the site of project if user use link to directly visit to site from home page
if (project && geoJson && router.query.site) {
const siteIndex: number = geoJson?.features.findIndex((singleSite) => {
return router.query.site === singleSite?.properties.id;
});
if (siteIndex === -1) {
router.push(`/projects-archive/${project.slug}`);
} else {
setSelectedSite(siteIndex);
}
}
}, [setSelectedSite, geoJson, project]);
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

Include router.query.site in the dependencies of useEffect

The useEffect hook starting at line 176 uses router.query.site but doesn't list it in the dependencies array. This may prevent the effect from running when router.query.site updates.

Update the dependencies array to include router.query.site:

- }, [setSelectedSite, geoJson, project]);
+ }, [setSelectedSite, geoJson, project, router.query.site]);
📝 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
React.useEffect(() => {
//for selecting one of the site of project if user use link to directly visit to site from home page
if (project && geoJson && router.query.site) {
const siteIndex: number = geoJson?.features.findIndex((singleSite) => {
return router.query.site === singleSite?.properties.id;
});
if (siteIndex === -1) {
router.push(`/projects-archive/${project.slug}`);
} else {
setSelectedSite(siteIndex);
}
}
}, [setSelectedSite, geoJson, project]);
React.useEffect(() => {
//for selecting one of the site of project if user use link to directly visit to site from home page
if (project && geoJson && router.query.site) {
const siteIndex: number = geoJson?.features.findIndex((singleSite) => {
return router.query.site === singleSite?.properties.id;
});
if (siteIndex === -1) {
router.push(`/projects-archive/${project.slug}`);
} else {
setSelectedSite(siteIndex);
}
}
}, [setSelectedSite, geoJson, project, router.query.site]);

Comment on lines +190 to +205
React.useEffect(() => {
//for selecting one of the plant location. if user use link to directly visit to plantLocation from home page
if (geoJson && router.query.ploc && plantLocations && project) {
const singlePlantLocation: PlantLocation | undefined =
plantLocations?.find((singlePlantLocation) => {
return router.query.ploc === singlePlantLocation?.hid;
});

if (singlePlantLocation === undefined) {
router.push(`/projects-archive/${project.slug}`);
} else {
setSelectedPl(singlePlantLocation);
}
}
}, [router, router.query.ploc, plantLocations, setSelectedPl, project]);

Copy link
Contributor

@coderabbitai coderabbitai bot Nov 7, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid using the entire router object in dependencies

Including the whole router object in the dependencies array at line 190 can cause unnecessary re-renders since the router object may change on every render. It's better to specify only the needed properties.

Modify the dependencies to include specific properties:

- }, [router, router.query.ploc, plantLocations, setSelectedPl, project]);
+ }, [router.query.ploc, plantLocations, setSelectedPl, project]);
📝 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
React.useEffect(() => {
//for selecting one of the plant location. if user use link to directly visit to plantLocation from home page
if (geoJson && router.query.ploc && plantLocations && project) {
const singlePlantLocation: PlantLocation | undefined =
plantLocations?.find((singlePlantLocation) => {
return router.query.ploc === singlePlantLocation?.hid;
});
if (singlePlantLocation === undefined) {
router.push(`/projects-archive/${project.slug}`);
} else {
setSelectedPl(singlePlantLocation);
}
}
}, [router, router.query.ploc, plantLocations, setSelectedPl, project]);
React.useEffect(() => {
//for selecting one of the plant location. if user use link to directly visit to plantLocation from home page
if (geoJson && router.query.ploc && plantLocations && project) {
const singlePlantLocation: PlantLocation | undefined =
plantLocations?.find((singlePlantLocation) => {
return router.query.ploc === singlePlantLocation?.hid;
});
if (singlePlantLocation === undefined) {
router.push(`/projects-archive/${project.slug}`);
} else {
setSelectedPl(singlePlantLocation);
}
}
}, [router.query.ploc, plantLocations, setSelectedPl, project]);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Add this as an issue, will take care of it later

Copy link
Contributor

Choose a reason for hiding this comment

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

@mohitb35, I've opened a new GitHub issue to track this: #2300.

🔗 Analysis chain

@mohitb35, I've opened a new GitHub issue to track this.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Open a new GitHub issue to track the suggested change
gh issue create \
  --title "Avoid using the entire router object in dependencies" \
  --body "As discussed in [PR #2296](https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296), it's recommended to avoid including the entire \`router\` object in the dependencies array in \`pages/sites/[slug]/[locale]/projects-archive/[p].tsx\` at line 190. Instead, specify only the needed properties to prevent unnecessary re-renders.

[Comment reference](https://github.com/Plant-for-the-Planet-org/planet-webapp/pull/2296#discussion_r1832677716)" \
  --assignee mohitb35

Length of output: 631

Comment on lines +81 to +127
React.useEffect(() => {
async function loadProject() {
if (
!internalCurrencyCode ||
currencyCode !== internalCurrencyCode ||
internalLanguage !== locale
) {
const currency = getStoredCurrency(
pageProps.tenantConfig.config.fallbackCurrency!
);
setInternalCurrencyCode(currency);
setInternalLanguage(locale);
setCurrencyCode(currency);
try {
const { p } = router.query;
const project = await getRequest<ProjectExtended>(
pageProps.tenantConfig.id,
encodeURI(`/app/projects/${p}`),
{
_scope: 'extended',
currency: currency || '',
locale: locale,
}
);
if (
project.purpose === 'conservation' ||
project.purpose === 'trees'
) {
setProject(project);
setShowSingleProject(true);
setZoomLevel(2);
} else {
throw new ClientError(404, {
error_type: 'project_not_available',
error_code: 'project_not_available',
});
}
} catch (err) {
setErrors(handleError(err as APIError | ClientError));
redirect('/');
}
}
}
if (router.query.p) {
loadProject();
}
}, [router.query.p, currencyCode, locale]);
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

Add missing dependencies to the useEffect hook

In the useEffect starting at line 81, the dependencies array does not include internalCurrencyCode and internalLanguage, which are used inside the effect. This could lead to stale values or unintended behavior.

Consider adding internalCurrencyCode and internalLanguage to the dependencies array:

- }, [router.query.p, currencyCode, locale]);
+ }, [router.query.p, currencyCode, locale, internalCurrencyCode, internalLanguage]);

Alternatively, refactor the logic to avoid potential infinite loops if these values change frequently.

📝 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
React.useEffect(() => {
async function loadProject() {
if (
!internalCurrencyCode ||
currencyCode !== internalCurrencyCode ||
internalLanguage !== locale
) {
const currency = getStoredCurrency(
pageProps.tenantConfig.config.fallbackCurrency!
);
setInternalCurrencyCode(currency);
setInternalLanguage(locale);
setCurrencyCode(currency);
try {
const { p } = router.query;
const project = await getRequest<ProjectExtended>(
pageProps.tenantConfig.id,
encodeURI(`/app/projects/${p}`),
{
_scope: 'extended',
currency: currency || '',
locale: locale,
}
);
if (
project.purpose === 'conservation' ||
project.purpose === 'trees'
) {
setProject(project);
setShowSingleProject(true);
setZoomLevel(2);
} else {
throw new ClientError(404, {
error_type: 'project_not_available',
error_code: 'project_not_available',
});
}
} catch (err) {
setErrors(handleError(err as APIError | ClientError));
redirect('/');
}
}
}
if (router.query.p) {
loadProject();
}
}, [router.query.p, currencyCode, locale]);
React.useEffect(() => {
async function loadProject() {
if (
!internalCurrencyCode ||
currencyCode !== internalCurrencyCode ||
internalLanguage !== locale
) {
const currency = getStoredCurrency(
pageProps.tenantConfig.config.fallbackCurrency!
);
setInternalCurrencyCode(currency);
setInternalLanguage(locale);
setCurrencyCode(currency);
try {
const { p } = router.query;
const project = await getRequest<ProjectExtended>(
pageProps.tenantConfig.id,
encodeURI(`/app/projects/${p}`),
{
_scope: 'extended',
currency: currency || '',
locale: locale,
}
);
if (
project.purpose === 'conservation' ||
project.purpose === 'trees'
) {
setProject(project);
setShowSingleProject(true);
setZoomLevel(2);
} else {
throw new ClientError(404, {
error_type: 'project_not_available',
error_code: 'project_not_available',
});
}
} catch (err) {
setErrors(handleError(err as APIError | ClientError));
redirect('/');
}
}
}
if (router.query.p) {
loadProject();
}
}, [router.query.p, currencyCode, locale, internalCurrencyCode, internalLanguage]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants