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

'Visit' Button Feature Added to Joined Organizations Filter #3232

Open
wants to merge 20 commits into
base: develop-postgres
Choose a base branch
from

Conversation

gkbishnoi07
Copy link

@gkbishnoi07 gkbishnoi07 commented Jan 10, 2025

What kind of change does this PR introduce?
Feature

Issue Number:
Fixes #3162

Did you add tests for your changes?
No

Snapshots/Videos:

issue.3162.mp4

Summary
This PR introduces a 'Visit' button in the Joined Organizations filter.

Enhances the user experience by providing direct navigation to organizations from the filter.
Solves the issue of limited navigation options in the Joined Organizations section.

Does this PR introduce a breaking change?
No

Other information

The feature was tested in multiple scenarios to ensure seamless functionality.

Have you read the contributing guide?
Yes

Summary by CodeRabbit

  • Tests

    • Enhanced unit tests for the OrganizationCard component with comprehensive scenarios, including rendering variations and button visibility based on membership status.
    • Improved test suite for OrganizationTags with better mock functions and more robust testing of user interactions.
  • New Features

    • Added more detailed organization membership management functionality, including joining and withdrawing requests.
    • Introduced isJoined property to track organization membership status.
    • Added a new script for formatting files using Prettier.
  • Bug Fixes

    • Improved error handling for organization membership interactions, providing better feedback to users.
  • Chores

    • Updated the Organizations component name for consistency and improved clarity.
    • Revised component documentation for better clarity on props.
    • Streamlined rendering logic in the Organizations component for enhanced user experience.

Copy link
Contributor

coderabbitai bot commented Jan 10, 2025

Walkthrough

This pull request introduces comprehensive changes to the OrganizationCard component and its associated test suite. The modifications enhance the component's functionality by adding new properties like description, admins, members, and address, and improving membership request handling. The test suite has been updated to provide more robust coverage, testing various scenarios such as rendering with different membership statuses and button interactions.

Changes

File Change Summary
src/components/OrganizationCard/OrganizationCard.spec.tsx Restructured unit tests with new imports, added comprehensive test cases for rendering and interaction scenarios, migrated from Jest to Vitest.
src/components/OrganizationCard/OrganizationCard.tsx Updated props interface, added new imports, implemented membership request handling functions, enhanced rendering logic.
src/screens/UserPortal/Organizations/Organizations.tsx Added isJoined property to organization objects to explicitly track membership status, renamed component for consistency.
src/screens/OrganizationTags/OrganizationTags.spec.tsx Added mock functions for toast notifications, improved test structure and asynchronous handling, migrated from Jest to Vitest.
package.json Added a new script for formatting files using Prettier.
talawa-admin Introduced a new subproject commit.

Assessment against linked issues

Objective Addressed Explanation
Visit Button for Joined Organizations [#3162] The changes do not directly address the visibility of the "Visit" button for joined organizations in the filter.

Possibly related issues

Possibly related PRs

Suggested labels

test, ignore-sensitive-files-pr, refactor

Suggested reviewers

  • palisadoes
  • disha1202
  • noman2002

Poem

🐰 A Rabbit's Ode to Organization Cards 🏢
Buttons dance, memberships flow,
Tests leap high, code starts to glow,
Cards now smart, with details bright,
Joining orgs becomes a delight!
Hop, hop, hooray for clean design! 🎉


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.

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

Our Pull Request Approval Process

Thanks for contributing!

Testing Your Code

Remember, your PRs won't be reviewed until these criteria are met:

  1. We don't merge PRs with poor code quality.
    1. Follow coding best practices such that CodeRabbit.ai approves your PR.
  2. We don't merge PRs with failed tests.
    1. When tests fail, click on the Details link to learn more.
    2. Write sufficient tests for your changes (CodeCov Patch Test). Your testing level must be better than the target threshold of the repository
    3. Tests may fail if you edit sensitive files. Ask to add the ignore-sensitive-files-pr label if the edits are necessary.
  3. We cannot merge PRs with conflicting files. These must be fixed.

Our policies make our code better.

Reviewers

Do not assign reviewers. Our Queue Monitors will review your PR and assign them.
When your PR has been assigned reviewers contact them to get your code reviewed and approved via:

  1. comments in this PR or
  2. our slack channel

Reviewing Your Code

Your reviewer(s) will have the following roles:

  1. arbitrators of future discussions with other contributors about the validity of your changes
  2. point of contact for evaluating the validity of your work
  3. person who verifies matching issues by others that should be closed.
  4. person who gives general guidance in fixing your tests

CONTRIBUTING.md

Read our CONTRIBUTING.md file. Most importantly:

  1. PRs with issues not assigned to you will be closed by the reviewer
  2. Fix the first comment in the PR so that each issue listed automatically closes

Other

  1. 🎯 Please be considerate of our volunteers' time. Contacting the person who assigned the reviewers is not advised unless they ask for your input. Do not @ the person who did the assignment otherwise.
  2. Read the CONTRIBUTING.md file make

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 (12)
src/components/OrganizationCard/OrganizationCard.tsx (6)

184-186: Safely render props.description to prevent potential errors

If props.description is undefined or null, rendering it directly could cause unintended output or errors. Consider conditionally rendering the description only if it exists.

Modify the code to:

{props.description && (
  <h6 className={`${styles.orgdesc} fw-semibold`}>
    <span>{props.description}</span>
  </h6>
)}
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


72-73: Ensure userId is not null before using it in queries

Since userId can be null, using it directly in GraphQL queries may result in errors or unintended behavior. Consider adding a null check before using it in useQuery or provide a default value.

Example:

const userId = getItem('userId');

if (userId) {
  const { refetch } = useQuery(USER_JOINED_ORGANIZATIONS, {
    variables: { id: userId },
  });
  // Rest of your code that depends on userId
}

Alternatively, you can handle the null case gracefully within the component or redirect the user to log in if userId is not available.


107-136: Handle potential errors more comprehensively in joinOrganization

The error handling in joinOrganization assumes that the error is an ApolloError with graphQLErrors. However, there's a possibility of other errors occurring. Consider adding a general error message or logging for unexpected error types.

Modify the catch block to handle unexpected errors:

} catch (error: unknown) {
  if (error instanceof ApolloError) {
    const errorCode = error.graphQLErrors[0]?.extensions?.code;

    if (errorCode === 'ALREADY_MEMBER') {
      toast.error(t('AlreadyJoined') as string);
    } else {
      toast.error(t('errorOccured') as string);
    }
  } else {
    // Handle non-ApolloError types
    toast.error(t('unexpectedError') as string);
    console.error('An unexpected error occurred:', error);
  }
}

143-145: Improve type safety when finding membershipRequest

When finding the membershipRequest, ensure that userId is not null to avoid potential errors.

Add a null check for userId:

if (!userId) {
  toast.error(t('UserNotLoggedIn') as string);
  return;
}

const membershipRequest = props.membershipRequests.find(
  (request) => request.user._id === userId,
);

198-200: Handle undefined props.admins and props.members safely

In cases where props.admins or props.members might be undefined, using .length may cause errors. Consider providing default values to ensure safe access.

Modify the code to provide default empty arrays:

{tCommon('admins')}: <span>{props.admins?.length ?? 0}</span> &nbsp;
&nbsp; &nbsp; {tCommon('members')}: <span>{props.members?.length ?? 0}</span>

170-177: Simplify image rendering logic

You can simplify the conditional rendering of the organization image by leveraging short-circuit evaluation.

Simplify the code as follows:

<div className={styles.orgImgContainer}>
  {props.image ? (
    <img src={props.image} alt={`${props.name} image`} />
  ) : (
    <Avatar
      name={props.name}
      alt={`${props.name} image`}
      dataTestId="emptyContainerForImage"
    />
  )}
</div>

This maintains readability and reduces unnecessary complexity.

src/components/OrganizationCard/OrganizationCard.spec.tsx (2)

168-209: Separate tests for each membership status to improve clarity

Currently, the test displays correct button based on membership status uses rerender to test different statuses within a single test case. Separating these into individual test cases enhances readability and maintainability.

Refactor the tests as follows:

test('renders "Join Now" button when membershipRequestStatus is empty', () => {
  render(
    // ...
    <OrganizationCard {...defaultProps} membershipRequestStatus="" />
    // ...
  );
  expect(screen.getByTestId('joinBtn')).toBeInTheDocument();
});

test('renders "Visit" button when membershipRequestStatus is accepted', () => {
  render(
    // ...
    <OrganizationCard {...defaultProps} membershipRequestStatus="accepted" />
    // ...
  );
  const visitButton = screen.getByTestId('manageBtn');
  expect(visitButton).toBeInTheDocument();
  fireEvent.click(visitButton);
  expect(mockNavigate).toHaveBeenCalledWith('/user/organization/123');
});

test('renders "Withdraw" button when membershipRequestStatus is pending', () => {
  render(
    // ...
    <OrganizationCard {...defaultProps} membershipRequestStatus="pending" />
    // ...
  );
  expect(screen.getByTestId('withdrawBtn')).toBeInTheDocument();
});

19-23: Avoid side effects in mocks by using jest.fn() within the mock scope

To ensure that mocks do not leak between tests, consider defining mockNavigate within the mock scope rather than at the module level.

Modify the mock setup:

jest.mock('react-router-dom', () => {
  const originalModule = jest.requireActual('react-router-dom');
  return {
    ...originalModule,
    useNavigate: jest.fn(),
  };
});

Then, within your tests, you can access useNavigate:

import { useNavigate } from 'react-router-dom';

// Inside your test
const mockNavigate = useNavigate() as jest.Mock;
// Now you can assert on `mockNavigate`
src/screens/UserPortal/Organizations/Organizations.tsx (4)

254-258: Ensure membershipRequestStatus is accurately determined

In the mapping function, consider handling cases where membershipRequestStatus might not be 'accepted' or may be undefined. This ensures that isJoined reflects the actual membership status.

Add a default case for membershipRequestStatus:

return {
  ...organization,
  membershipRequestStatus,
  isJoined: membershipRequestStatus === 'accepted',
};

Ensure that membershipRequestStatus is set correctly and consider handling other statuses like 'pending' if applicable.


Line range hint 98-100: Check for null userId before using it in queries

Since userId can be null, using it directly in useQuery may cause issues. Add a null check or default handling to prevent potential errors.

Example:

const userId: string | null = getItem('userId');

if (userId) {
  const { data: joinedOrganizationsData } = useQuery(USER_JOINED_ORGANIZATIONS, {
    variables: { id: userId },
  });

  const { data: createdOrganizationsData } = useQuery(
    USER_CREATED_ORGANIZATIONS,
    {
      variables: { id: userId },
    },
  );
} else {
  // Handle the case when userId is null, e.g., redirect to login
}

This ensures that queries relying on userId do not execute with invalid parameters.


266-272: Handle undefined data when mapping joinedOrganizations

When mapping over joinedOrganizations, ensure that the nested properties are not undefined to prevent runtime errors.

Modify the code:

const organizations =
  joinedOrganizationsData.users[0]?.user?.joinedOrganizations?.map(
    (org: InterfaceOrganization) => ({
      ...org,
      membershipRequestStatus: 'accepted',
      isJoined: true,
    }),
  ) || [];

Adding ? before .map ensures that the code does not attempt to map over undefined.


281-287: Handle undefined data when mapping createdOrganizations

Similar to the previous comment, ensure that createdOrganizations is defined before mapping.

Modify the code:

const organizations =
  createdOrganizationsData.users[0]?.appUserProfile?.createdOrganizations?.map(
    (org: InterfaceOrganization) => ({
      ...org,
      membershipRequestStatus: 'accepted',
      isJoined: true,
    }),
  ) || [];

This prevents runtime errors if createdOrganizations is undefined.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e9aec17 and 34335ce.

📒 Files selected for processing (5)
  • eslint.config.cjs (1 hunks)
  • eslint.config.js (1 hunks)
  • src/components/OrganizationCard/OrganizationCard.spec.tsx (2 hunks)
  • src/components/OrganizationCard/OrganizationCard.tsx (1 hunks)
  • src/screens/UserPortal/Organizations/Organizations.tsx (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: PR Workflow
eslint.config.cjs

[error] SyntaxError: Unexpected identifier 'eslint' - Possible configuration file syntax error

🪛 Biome (1.9.4)
eslint.config.js

[error] 17-17: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)


[error] 17-17: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)

src/components/OrganizationCard/OrganizationCard.tsx

[error] 186-186: 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: Analyse Code With CodeQL (javascript)

eslint.config.cjs Outdated Show resolved Hide resolved
eslint.config.cjs Outdated Show resolved Hide resolved
eslint.config.js Outdated Show resolved Hide resolved
eslint.config.js Outdated Show resolved Hide resolved
@Cioppolo14
Copy link
Contributor

@gkbishnoi07 Please fix the failed tests and make sure coderabbit approves of the PR.

@gkbishnoi07
Copy link
Author

@Cioppolo14 working on failed test cases

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/components/OrganizationCard/OrganizationCard.tsx (2)

74-101: Destructure props for better code readability

Multiple static analysis tools suggest destructuring props. This would improve code readability and follow React best practices.

-function OrganizationCard(props: InterfaceOrganizationCardProps): JSX.Element {
+function OrganizationCard({
+  id,
+  name,
+  image,
+  description,
+  admins,
+  members,
+  address,
+  membershipRequestStatus,
+  userRegistrationRequired,
+  membershipRequests
+}: InterfaceOrganizationCardProps): JSX.Element {
🧰 Tools
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch

[failure] 85-85:
Must use destructuring props assignment


[failure] 90-90:
Must use destructuring props assignment


[failure] 95-95:
Must use destructuring props assignment

🪛 eslint

[error] 85-85: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 90-90: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 95-95: Must use destructuring props assignment

(react/destructuring-assignment)


186-196: Use optional chaining for address checks

Simplify the address check using optional chaining for better readability.

-            {props.address && props.address.city && (
+            {props.address?.city && (
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 eslint

[error] 186-186: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 186-186: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 189-189: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 190-190: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 192-192: Must use destructuring props assignment

(react/destructuring-assignment)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 34335ce and 60df684.

📒 Files selected for processing (1)
  • src/components/OrganizationCard/OrganizationCard.tsx (1 hunks)
🧰 Additional context used
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch
src/components/OrganizationCard/OrganizationCard.tsx

[failure] 12-12:
'/home/runner/work/talawa-admin/talawa-admin/node_modules/@apollo/client/index.js' imported multiple times


[failure] 20-20:
All imports in the declaration are only used as types. Use import type


[failure] 20-20:
'/home/runner/work/talawa-admin/talawa-admin/node_modules/@apollo/client/index.js' imported multiple times


[failure] 85-85:
Must use destructuring props assignment


[failure] 90-90:
Must use destructuring props assignment


[failure] 95-95:
Must use destructuring props assignment


[failure] 108-108:
Must use destructuring props assignment


[failure] 111-111:
Must use destructuring props assignment


[failure] 118-118:
Must use destructuring props assignment


[failure] 143-143:
Must use destructuring props assignment

🪛 Biome (1.9.4)
src/components/OrganizationCard/OrganizationCard.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 eslint
src/components/OrganizationCard/OrganizationCard.tsx

[error] 12-12: '@apollo/client' imported multiple times.

(import/no-duplicates)


[error] 20-20: All imports in the declaration are only used as types. Use import type.

(@typescript-eslint/consistent-type-imports)


[error] 20-20: '@apollo/client' imported multiple times.

(import/no-duplicates)


[error] 85-85: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 90-90: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 95-95: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 108-108: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 111-111: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 118-118: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 143-143: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 159-159: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 169-169: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 170-170: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 170-170: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 173-173: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 174-174: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 180-180: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 181-181: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 184-184: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 186-186: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 186-186: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 189-189: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 190-190: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 192-192: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 198-198: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 200-200: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 204-204: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 210-210: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 217-217: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 228-228: Must use destructuring props assignment

(react/destructuring-assignment)

🪛 GitHub Actions: PR Workflow
src/components/OrganizationCard/OrganizationCard.tsx

[error] 12-12: '/home/runner/work/talawa-admin/talawa-admin/node_modules/@apollo/client/index.js' imported multiple times (import/no-duplicates)

🔇 Additional comments (4)
src/components/OrganizationCard/OrganizationCard.tsx (4)

26-49: LGTM! Well-structured interface definition.

The interface properties are well-defined and properly typed, providing a comprehensive structure for organization data.


52-71: LGTM! Excellent documentation.

The JSDoc documentation is comprehensive and clearly describes all component props and functionality.


204-214: LGTM! Visit button implementation.

The Visit button implementation aligns with the PR objectives, providing direct navigation to organizations from the filter.

🧰 Tools
🪛 eslint

[error] 204-204: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 210-210: Must use destructuring props assignment

(react/destructuring-assignment)


1-241: Add unit tests for the new Visit button feature

While the implementation looks good, the PR mentions that no tests were added. Consider adding tests for:

  • Visit button rendering conditions
  • Navigation functionality
  • Different membership states

Would you like me to help generate the test cases for the Visit button feature?

🧰 Tools
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch

[failure] 12-12:
'/home/runner/work/talawa-admin/talawa-admin/node_modules/@apollo/client/index.js' imported multiple times


[failure] 20-20:
All imports in the declaration are only used as types. Use import type


[failure] 20-20:
'/home/runner/work/talawa-admin/talawa-admin/node_modules/@apollo/client/index.js' imported multiple times


[failure] 85-85:
Must use destructuring props assignment


[failure] 90-90:
Must use destructuring props assignment


[failure] 95-95:
Must use destructuring props assignment


[failure] 108-108:
Must use destructuring props assignment


[failure] 111-111:
Must use destructuring props assignment


[failure] 118-118:
Must use destructuring props assignment


[failure] 143-143:
Must use destructuring props assignment

🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 eslint

[error] 12-12: '@apollo/client' imported multiple times.

(import/no-duplicates)


[error] 20-20: All imports in the declaration are only used as types. Use import type.

(@typescript-eslint/consistent-type-imports)


[error] 20-20: '@apollo/client' imported multiple times.

(import/no-duplicates)


[error] 85-85: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 90-90: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 95-95: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 108-108: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 111-111: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 118-118: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 143-143: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 159-159: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 169-169: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 170-170: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 170-170: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 173-173: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 174-174: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 180-180: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 181-181: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 184-184: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 186-186: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 186-186: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 189-189: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 190-190: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 192-192: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 198-198: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 200-200: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 204-204: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 210-210: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 217-217: Must use destructuring props assignment

(react/destructuring-assignment)


[error] 228-228: Must use destructuring props assignment

(react/destructuring-assignment)

🪛 GitHub Actions: PR Workflow

[error] 12-12: '/home/runner/work/talawa-admin/talawa-admin/node_modules/@apollo/client/index.js' imported multiple times (import/no-duplicates)

src/components/OrganizationCard/OrganizationCard.tsx Outdated Show resolved Hide resolved
src/components/OrganizationCard/OrganizationCard.tsx Outdated 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: 0

🧹 Nitpick comments (3)
src/components/OrganizationCard/OrganizationCard.tsx (3)

12-12: Fix formatting in imports

Remove the trailing comma after useQuery.

-import { useMutation, useQuery, } from '@apollo/client';
+import { useMutation, useQuery } from '@apollo/client';
🧰 Tools
🪛 eslint

[error] 12-12: Delete ,

(prettier/prettier)

🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.


113-143: Improve error type handling in joinOrganization

The error handling could be more type-safe. Consider creating a custom type for the GraphQL error structure.

+interface GraphQLErrorExtensions {
+  code: string;
+}
+
+interface CustomGraphQLError extends ApolloError {
+  graphQLErrors: Array<{
+    extensions?: GraphQLErrorExtensions;
+  }>;
+}

 async function joinOrganization(): Promise<void> {
   try {
     // ... existing code ...
   } catch (error: unknown) {
     if (error instanceof Error) {
-      const apolloError = error as ApolloError;
+      const apolloError = error as CustomGraphQLError;
       const errorCode = apolloError.graphQLErrors[0]?.extensions?.code;
🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.


189-197: Optimize conditional rendering with optional chaining

The address check can be simplified using optional chaining.

-{address && address.city && (
+{address?.city && (
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 60df684 and f9a2705.

📒 Files selected for processing (1)
  • src/components/OrganizationCard/OrganizationCard.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/OrganizationCard/OrganizationCard.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 eslint
src/components/OrganizationCard/OrganizationCard.tsx

[error] 12-12: Delete ,

(prettier/prettier)

🪛 GitHub Actions: PR Workflow
src/components/OrganizationCard/OrganizationCard.tsx

[warning] Code formatting issues detected. File needs to be formatted using Prettier.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (4)
src/components/OrganizationCard/OrganizationCard.tsx (4)

27-49: LGTM! Well-structured interface definition

The interface is well-defined with proper typing for all properties. The nested structures for admins, members, address, and membershipRequests provide good type safety.

🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.


53-70: LGTM! Excellent documentation

The JSDoc comments are comprehensive and well-structured, clearly documenting all parameters and their purposes.

🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.


86-111: LGTM! Well-structured component setup

Good practices observed:

  • Proper translation setup with namespaces
  • GraphQL mutations with appropriate refetch queries
  • Clean organization of hooks and mutations
🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.


204-237: LGTM! Clean conditional rendering

The button rendering logic is well-organized with clear conditions and appropriate variants for different states.

🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code formatting issues detected. File needs to be formatted using Prettier.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/components/OrganizationCard/OrganizationCard.tsx (4)

53-70: Consider adding usage examples to the documentation.

The documentation is comprehensive but could be even more helpful with examples showing different membership states and how they affect the component's rendering.


94-108: Consider extracting duplicate refetchQueries configuration.

The refetchQueries configuration is repeated across multiple mutations. Consider extracting it to a constant to improve maintainability.

+const MEMBERSHIP_REFETCH_QUERIES = [
+  { query: USER_ORGANIZATION_CONNECTION, variables: { id } },
+];

 const [sendMembershipRequest] = useMutation(SEND_MEMBERSHIP_REQUEST, {
-  refetchQueries: [
-    { query: USER_ORGANIZATION_CONNECTION, variables: { id } },
-  ],
+  refetchQueries: MEMBERSHIP_REFETCH_QUERIES,
 });

 const [joinPublicOrganization] = useMutation(JOIN_PUBLIC_ORGANIZATION, {
-  refetchQueries: [
-    { query: USER_ORGANIZATION_CONNECTION, variables: { id } },
-  ],
+  refetchQueries: MEMBERSHIP_REFETCH_QUERIES,
 });

 const [cancelMembershipRequest] = useMutation(CANCEL_MEMBERSHIP_REQUEST, {
-  refetchQueries: [
-    { query: USER_ORGANIZATION_CONNECTION, variables: { id } },
-  ],
+  refetchQueries: MEMBERSHIP_REFETCH_QUERIES,
 });

131-142: Consider creating a custom error type for better error handling.

The error handling could be more specific by creating a custom type for GraphQL errors. This would make the error handling more type-safe and maintainable.

type OrganizationError = {
  code: 'ALREADY_MEMBER' | 'MEMBERSHIP_NOT_FOUND' | 'UNKNOWN_ERROR';
  message: string;
};

// Usage in error handling
if (error instanceof ApolloError) {
  const errorCode = error.graphQLErrors[0]?.extensions?.code as OrganizationError['code'];
  // ...
}

189-197: Use optional chaining for safer address access.

The address check can be simplified using optional chaining for better readability and safety.

-{address && address.city && (
+{address?.city && (
   <div className={styles.address}>
     <h6 className="text-secondary">
-      <span className="address-line">{address.line1}, </span>
-      <span className="address-line">{address.city}, </span>
-      <span className="address-line">{address.countryCode}</span>
+      <span className="address-line">{address?.line1}, </span>
+      <span className="address-line">{address?.city}, </span>
+      <span className="address-line">{address?.countryCode}</span>
     </h6>
   </div>
 )}
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f9a2705 and 074bf17.

📒 Files selected for processing (1)
  • src/components/OrganizationCard/OrganizationCard.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/OrganizationCard/OrganizationCard.tsx

[error] 189-189: 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: Test Application
🔇 Additional comments (3)
src/components/OrganizationCard/OrganizationCard.tsx (3)

12-12: Consolidate duplicate imports from '@apollo/client'

Combine the multiple imports from '@apollo/client' into a single import statement and use import type for type-only imports.

-import { useMutation, useQuery } from '@apollo/client';
-import type { ApolloError } from '@apollo/client';
+import { useMutation, useQuery } from '@apollo/client';
+import type { ApolloError } from '@apollo/client';

Also applies to: 20-20


28-49: LGTM! Well-structured interface with comprehensive type definitions.

The interface has been enhanced with well-defined types for organization properties including description, admins, members, address, and membership-related fields.


204-237: LGTM! Well-implemented conditional rendering for membership states.

The button rendering logic is clean and properly handles all membership states (accepted, pending, and new joins) with appropriate styling and functionality.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/components/OrganizationCard/OrganizationCard.spec.tsx (3)

29-45: Consider adding validation for required props

The defaultProps object is well-structured, but consider adding JSDoc comments to document which props are required vs optional, especially for the new membershipRequestStatus prop.

Add documentation like this:

+/**
+ * Default props for OrganizationCard tests
+ * @property {string} id - Required. Organization ID
+ * @property {string} membershipRequestStatus - Required. Current membership status
+ */
const defaultProps = {

105-124: Add error handling test cases for navigation

While the basic navigation test is good, consider adding test cases for:

  1. Error handling when navigation fails
  2. Loading state during navigation

Add these test cases:

test('handles navigation errors gracefully', () => {
  mockNavigate.mockImplementationOnce(() => {
    throw new Error('Navigation failed');
  });
  // Test implementation
});

test('shows loading state during navigation', () => {
  // Test implementation with loading state check
});

47-171: Consider grouping related test cases

The test cases are well-written but could be better organized using describe blocks to group related tests.

Consider restructuring like this:

describe('OrganizationCard', () => {
  describe('Rendering', () => {
    // Tests for basic rendering (with/without image)
  });

  describe('Membership Status', () => {
    // Tests for different membership statuses
  });

  describe('Navigation', () => {
    // Tests for navigation functionality
  });
});
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 074bf17 and 480a62d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json (2 hunks)
  • src/components/OrganizationCard/OrganizationCard.spec.tsx (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Test Application
  • GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (3)
package.json (1)

152-152: Verify Jest upgrade compatibility

The significant version jump in Jest (27.4.5 to 29.7.0) might introduce breaking changes. Ensure all existing tests are compatible with the new version.

Run this script to check for potential compatibility issues:

✅ Verification successful

Jest upgrade appears safe to proceed

The codebase uses modern Jest patterns and APIs that are compatible with Jest 29.x. The configuration and test implementations follow current best practices without any deprecated features.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for Jest breaking changes and compatibility issues

# Search for Jest configuration files
echo "Searching for Jest config files..."
fd -e json -e js -e ts --full-path "jest.config"

# Look for potentially affected test patterns
echo "Checking for potentially affected test patterns..."
rg -l "jest.mock|jest.spyOn|jest.fn" -g "*.spec.{ts,tsx,js,jsx}"

Length of output: 378


Script:

#!/bin/bash
# Check Jest configuration and test implementation
echo "=== Jest Configuration ==="
cat jest.config.js

echo -e "\n=== Test Implementation ==="
cat src/components/OrganizationCard/OrganizationCard.spec.tsx

Length of output: 9088

src/components/OrganizationCard/OrganizationCard.spec.tsx (2)

20-27: LGTM! Well-structured navigation mock

The navigation mock is properly implemented using jest.mock, which is essential for testing the Visit button's navigation functionality.


105-124: LGTM! Tests align perfectly with PR objectives

The test coverage for the Visit button feature is comprehensive, including:

  • Correct button rendering based on membership status
  • Navigation functionality
  • Different membership states

Also applies to: 172-214

@palisadoes
Copy link
Contributor

Exclude the sensitive files from your PR. Don't delete them.

Your PR has too many unnecessary files that don’t relate to your issue. You can exclude them from the PR by running the commands below from the root directory of the repository

git add -u
git reset HEAD path/to/file
git commit
git push

Please apply these changes to this file(s).

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 (2)
src/screens/OrganizationTags/OrganizationTags.spec.tsx (1)

293-296: Replace non-null assertions with proper error handling.

The non-null assertions (!) on the form element should be replaced with proper error handling to improve type safety.

-    const form = screen.getByTestId('createTagSubmitBtn').closest('form');
-    await act(async () => {
-      fireEvent.submit(form!);
-    });
+    const submitBtn = screen.getByTestId('createTagSubmitBtn');
+    const form = submitBtn.closest('form');
+    if (!form) {
+      throw new Error('Form not found');
+    }
+    await act(async () => {
+      fireEvent.submit(form);
+    });

Also applies to: 312-314

🧰 Tools
🪛 eslint

[error] 295-295: Forbidden non-null assertion.

(@typescript-eslint/no-non-null-assertion)

src/components/OrganizationCard/OrganizationCard.spec.tsx (1)

179-214: Consider splitting the membership status tests

While the test is comprehensive, consider splitting it into separate test cases for better maintainability and clearer failure messages.

Here's a suggested approach:

describe('membership status buttons', () => {
  const renderComponent = (status: string) => {
    return render(
      <MockedProvider>
        <I18nextProvider i18n={i18nForTest}>
          <OrganizationCard {...defaultProps} membershipRequestStatus={status} />
        </I18nextProvider>
      </MockedProvider>
    );
  };

  test('shows Join Now button for empty status', () => {
    renderComponent("");
    expect(screen.getByTestId('joinBtn')).toBeInTheDocument();
  });

  test('shows Visit button for accepted status', () => {
    renderComponent("accepted");
    expect(screen.getByTestId('manageBtn')).toBeInTheDocument();
  });

  test('shows Withdraw button for pending status', () => {
    renderComponent("pending");
    expect(screen.getByTestId('withdrawBtn')).toBeInTheDocument();
  });
});
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 480a62d and 072625f.

📒 Files selected for processing (2)
  • src/components/OrganizationCard/OrganizationCard.spec.tsx (2 hunks)
  • src/screens/OrganizationTags/OrganizationTags.spec.tsx (2 hunks)
🧰 Additional context used
📓 Learnings (1)
src/screens/OrganizationTags/OrganizationTags.spec.tsx (1)
Learnt from: meetulr
PR: PalisadoesFoundation/talawa-admin#2398
File: src/screens/OrganizationTags/OrganizationTags.test.tsx:184-0
Timestamp: 2024-11-12T10:40:58.655Z
Learning: In the `talawa-admin` project, it's acceptable for test cases in `src/screens/OrganizationTags/OrganizationTags.test.tsx` to test multiple behaviors within a single test function without needing to split them into smaller, focused tests.
🪛 Biome (1.9.4)
src/components/OrganizationCard/OrganizationCard.spec.tsx

[error] 27-28: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '==='.

Expected a property, a shorthand property, a getter, a setter, or a method here.

(parse)


[error] 28-28: Expected an expression but instead found '==='.

Expected an expression here.

(parse)


[error] 28-28: Expected an expression but instead found '='.

Expected an expression here.

(parse)


[error] 25-28: Invalid assignment to { ...actual, BrowserRouter: ({ children }: { children: React.ReactNode }) => children, ======

This expression cannot be assigned to

(parse)


[error] 28-29: Expected an expression, or an assignment but instead found 'const'.

Expected an expression, or an assignment here.

(parse)


[error] 33-34: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '>'.

Expected a property, a shorthand property, a getter, a setter, or a method here.

(parse)


[error] 34-34: Expected an expression but instead found '>>>'.

Expected an expression here.

(parse)


[error] 34-34: Expected an expression but instead found '>'.

Expected an expression here.

(parse)


[error] 34-34: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 36-36: Expected an expression but instead found '}'.

Expected an expression here.

(parse)


[error] 36-36: expected , but instead found ;

Remove ;

(parse)


[error] 25-28: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 35-35: Unexpected label.

Only loops should be labeled.
The use of labels for other statements is suspicious and unfamiliar.

(lint/suspicious/noConfusingLabels)


[error] 35-35: This code is unreachable

... because this statement will return from the function beforehand

(lint/correctness/noUnreachable)


[error] 28-36: This code is unreachable

... because this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🪛 GitHub Actions: PR Workflow
src/components/OrganizationCard/OrganizationCard.spec.tsx

[error] 20-23: Merge conflict marker encountered. The file contains unresolved Git merge conflict markers (<<<<<<< HEAD)

🪛 eslint
src/screens/OrganizationTags/OrganizationTags.spec.tsx

[error] 295-295: Forbidden non-null assertion.

(@typescript-eslint/no-non-null-assertion)


[error] 313-313: Forbidden non-null assertion.

(@typescript-eslint/no-non-null-assertion)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (4)
src/screens/OrganizationTags/OrganizationTags.spec.tsx (2)

Line range hint 277-320: Well-structured test with clear steps and proper async handling!

The test case is well organized with:

  • Clear step-by-step comments
  • Proper use of act() for state updates
  • Appropriate waitFor assertions for async operations
🧰 Tools
🪛 eslint

[error] 295-295: Forbidden non-null assertion.

(@typescript-eslint/no-non-null-assertion)


[error] 313-313: Forbidden non-null assertion.

(@typescript-eslint/no-non-null-assertion)


51-52: Verify if unused toast mocks are needed.

The newly added warn and info toast mocks aren't used in any test cases. Consider removing them if they're not required for upcoming changes.

Run this script to check for usage of these toast types:

src/components/OrganizationCard/OrganizationCard.spec.tsx (2)

39-55: Well-structured test data setup

The defaultProps object is comprehensive and includes all necessary fields for testing the OrganizationCard component, including the new fields required for the Visit button feature.


120-137: Well-implemented Visit button test

The test case properly verifies both the presence of the Visit button and its navigation functionality when clicked.

src/components/OrganizationCard/OrganizationCard.spec.tsx Outdated 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: 0

🧹 Nitpick comments (1)
src/components/OrganizationCard/OrganizationCard.spec.tsx (1)

48-205: Consider adding error case tests

While the happy path scenarios are well covered, consider adding tests for error cases such as:

  • Invalid membership status
  • Network errors when navigating
  • Missing required props

Example test case:

test('handles invalid membership status gracefully', () => {
  render(
    <MockedProvider>
      <I18nextProvider i18n={i18nForTest}>
        <OrganizationCard
          {...defaultProps}
          membershipRequestStatus="invalid_status"
        />
      </I18nextProvider>
    </MockedProvider>,
  );

  // Verify fallback behavior
  expect(screen.getByTestId('joinBtn')).toBeInTheDocument();
});
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 072625f and e27de64.

📒 Files selected for processing (2)
  • src/components/OrganizationCard/OrganizationCard.spec.tsx (2 hunks)
  • src/screens/UserPortal/Organizations/Organizations.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/screens/UserPortal/Organizations/Organizations.tsx
🔇 Additional comments (3)
src/components/OrganizationCard/OrganizationCard.spec.tsx (3)

Line range hint 1-28: LGTM! Clean migration from Jest to Vitest

The test setup and configuration are well-structured with proper imports and mocking.


30-46: LGTM! Well-structured test data

The defaultProps object provides comprehensive test data covering all component properties, including those needed for the new Visit button feature.


111-128: LGTM! Visit button functionality is well tested

The test properly verifies both the rendering and navigation functionality of the Visit button.

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 (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

Line range hint 167-235: Extract duplicate membership status logic into a utility function.

The membership status checking logic is duplicated across different useEffect hooks. This could lead to maintenance issues if the logic needs to be updated.

Consider extracting the logic into a utility function:

const determineOrganizationStatus = (organization: InterfaceOrganization, userId: string) => {
  let membershipRequestStatus = '';
  if (organization.members.find((member: { _id: string }) => member._id === userId)) {
    membershipRequestStatus = 'accepted';
  } else if (
    organization.membershipRequests.find(
      (request: { user: { _id: string } }) => request.user._id === userId,
    )
  ) {
    membershipRequestStatus = 'pending';
  }
  return {
    membershipRequestStatus,
    isJoined: membershipRequestStatus === 'accepted',
  };
};
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e27de64 and 6096a3d.

📒 Files selected for processing (1)
  • src/screens/UserPortal/Organizations/Organizations.tsx (8 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (2)
src/screens/UserPortal/Organizations/Organizations.tsx (2)

69-81: LGTM! Component naming and state management improvements.

The changes follow React best practices with proper component naming and improved type safety through explicit typing of the organizations state.


Line range hint 69-375: Add test coverage for the Organizations component.

The PR objectives mention failed tests, and there's no test coverage visible for this component. Consider adding tests for:

  • Organization filtering functionality
  • Pagination behavior
  • Responsive drawer behavior
  • Different organization modes (all, joined, created)

Let me check for existing test files:

Would you like me to help create the test suite for this component?

src/screens/UserPortal/Organizations/Organizations.tsx Outdated Show resolved Hide resolved
src/screens/UserPortal/Organizations/Organizations.tsx Outdated Show resolved Hide resolved
@gkbishnoi07
Copy link
Author

@palisadoes, I’ve added this function and it’s working well. I passed all the test cases in my local setup. However, I’m currently facing an issue with the GitHub test, where the formatting lint test is failing. I will find the issue and quickly resolve that. I also ran npx prettier --check . locally and got the message "All matched files use Prettier code style!" but the test still failed on GitHub.

coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

Line range hint 167-188: Refactor duplicate membership status logic.

The membership status checking logic is duplicated between the two useEffect hooks. Consider extracting this logic into a utility function.

+const determineMembershipStatus = (organization: InterfaceOrganization, userId: string) => {
+  let membershipRequestStatus = '';
+  if (organization.members.find((member: { _id: string }) => member._id === userId)) {
+    membershipRequestStatus = 'accepted';
+  } else if (
+    organization.membershipRequests.find(
+      (request: { user: { _id: string } }) => request.user._id === userId
+    )
+  ) {
+    membershipRequestStatus = 'pending';
+  }
+  return {
+    membershipRequestStatus,
+    isJoined: membershipRequestStatus === 'accepted'
+  };
+};

Then use it in both useEffect hooks:

-let membershipRequestStatus = '';
-if (organization.members.find((member: { _id: string }) => member._id === userId))
-  membershipRequestStatus = 'accepted';
-else if (organization.membershipRequests.find((request: { user: { _id: string } }) => request.user._id === userId))
-  membershipRequestStatus = 'pending';
+const { membershipRequestStatus, isJoined } = determineMembershipStatus(organization, userId);

Also applies to: 191-235

🧰 Tools
🪛 GitHub Actions: PR Workflow

[error] Missing TSDoc comment documentation

♻️ Duplicate comments (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

244-244: 🛠️ Refactor suggestion

Fix potential state update race conditions in click handlers.

The click handlers directly use the previous state value in the toggle operation, which could lead to incorrect state updates if multiple clicks occur rapidly.

-onClick={(): void => setHideDrawer(!hideDrawer)}
+onClick={(): void => setHideDrawer((prev) => !prev)}

Also applies to: 252-252

🧰 Tools
🪛 GitHub Actions: PR Workflow

[error] Missing TSDoc comment documentation

🧹 Nitpick comments (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

325-355: Simplify conditional rendering logic.

The nested conditional rendering could be simplified for better readability.

-              {loadingOrganizations ? (
-                <div className="d-flex flex-row justify-content-center">
-                  <HourglassBottomIcon /> <span>Loading...</span>
-                </div>
-              ) : organizations && organizations.length > 0 ? (
-                (rowsPerPage > 0
-                  ? organizations.slice(
-                      page * rowsPerPage,
-                      page * rowsPerPage + rowsPerPage,
-                    )
-                  : organizations
-                ).map((organization: InterfaceOrganization) => {
+              {loadingOrganizations && (
+                <div className="d-flex flex-row justify-content-center">
+                  <HourglassBottomIcon /> <span>Loading...</span>
+                </div>
+              )}
+              {!loadingOrganizations && organizations.length === 0 && (
+                <span>{t('nothingToShow')}</span>
+              )}
+              {!loadingOrganizations && organizations.length > 0 && (
+                <>
+                  {(rowsPerPage > 0
+                    ? organizations.slice(
+                        page * rowsPerPage,
+                        page * rowsPerPage + rowsPerPage,
+                      )
+                    : organizations
+                  ).map((organization: InterfaceOrganization) => {
🧰 Tools
🪛 GitHub Actions: PR Workflow

[error] Missing TSDoc comment documentation

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6096a3d and f7b878f.

📒 Files selected for processing (3)
  • src/screens/OrganizationTags/OrganizationTags.spec.tsx (2 hunks)
  • src/screens/UserPortal/Organizations/Organizations.tsx (8 hunks)
  • talawa-admin (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • talawa-admin
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/screens/OrganizationTags/OrganizationTags.spec.tsx
🧰 Additional context used
🪛 GitHub Actions: PR Workflow
src/screens/UserPortal/Organizations/Organizations.tsx

[error] Missing TSDoc comment documentation

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

113-125: LGTM! Well-implemented resize handler.

The resize handler implementation follows React best practices:

  • Uses functional state updates to prevent race conditions
  • Properly cleans up event listeners in the useEffect cleanup function
🧰 Tools
🪛 GitHub Actions: PR Workflow

[error] Missing TSDoc comment documentation

src/screens/UserPortal/Organizations/Organizations.tsx Outdated 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: 1

🔭 Outside diff range comments (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

Line range hint 205-224: Extract duplicate organization mapping logic.

The organization mapping logic is duplicated in two useEffect hooks. Consider extracting it into a utility function:

+const mapOrganizationWithMembershipStatus = (
+  organization: InterfaceOrganization,
+  userId: string,
+  includeIsJoined = false
+) => {
+  let membershipRequestStatus = '';
+  if (
+    organization.members.find(
+      (member: { _id: string }) => member._id === userId,
+    )
+  )
+    membershipRequestStatus = 'accepted';
+  else if (
+    organization.membershipRequests.find(
+      (request: { user: { _id: string } }) =>
+        request.user._id === userId,
+    )
+  )
+    membershipRequestStatus = 'pending';
+  
+  return {
+    ...organization,
+    membershipRequestStatus,
+    ...(includeIsJoined && { isJoined: membershipRequestStatus === 'accepted' }),
+  };
+};

 useEffect(() => {
   if (data) {
-    const orgs = data.organizationsConnection.map(
-      // ... current mapping logic
-    );
+    const orgs = data.organizationsConnection.map((org) =>
+      mapOrganizationWithMembershipStatus(org, userId)
+    );
     setOrganizations(orgs);
   }
 }, [data, userId]);

 useEffect(() => {
   if (mode === 0 && data) {
-    const orgs = data.organizationsConnection.map(
-      // ... current mapping logic
-    );
+    const orgs = data.organizationsConnection.map((org) =>
+      mapOrganizationWithMembershipStatus(org, userId, true)
+    );
     setOrganizations(orgs);
   }
   // ... rest of the effect
 }, [mode, data, joinedOrganizationsData, createdOrganizationsData, userId]);

Also applies to: 229-254

🧰 Tools
🪛 eslint

[error] 196-196: 'handleSearchByBtnClick' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

🧹 Nitpick comments (2)
src/components/OrganizationCard/OrganizationCard.spec.tsx (1)

54-80: Enhance image rendering test coverage.

Consider adding assertions to verify the image source attribute:

   expect(screen.getByRole('img')).toBeInTheDocument();
+  const imgElement = screen.getByRole('img');
+  expect(imgElement).toHaveAttribute('src', defaultProps.image);
🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code style issues found. File needs to be formatted using Prettier.

src/screens/UserPortal/Organizations/Organizations.tsx (1)

Line range hint 21-47: Consider consolidating duplicate interface properties.

The InterfaceOrganizationCardProps and InterfaceOrganization interfaces share identical properties. Consider creating a base interface to avoid duplication.

+interface BaseOrganization {
+  id: string;
+  name: string;
+  image: string;
+  description: string;
+  admins: [];
+  members: [];
+  address: {
+    city: string;
+    countryCode: string;
+    line1: string;
+    postalCode: string;
+    state: string;
+  };
+  membershipRequestStatus: string;
+  userRegistrationRequired: boolean;
+  membershipRequests: {
+    _id: string;
+    user: {
+      _id: string;
+    };
+  }[];
+}

-interface InterfaceOrganizationCardProps {
-  // ... current properties
-}
+interface InterfaceOrganizationCardProps extends BaseOrganization {}

-interface InterfaceOrganization {
-  // ... current properties
-}
+interface InterfaceOrganization extends BaseOrganization {}
🧰 Tools
🪛 eslint

[error] 24-24: 'InterfaceOrganizationCardProps' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f7b878f and a025661.

📒 Files selected for processing (2)
  • src/components/OrganizationCard/OrganizationCard.spec.tsx (1 hunks)
  • src/screens/UserPortal/Organizations/Organizations.tsx (7 hunks)
🧰 Additional context used
🪛 eslint
src/screens/UserPortal/Organizations/Organizations.tsx

[error] 78-78: tsdoc-malformed-inline-tag: Expecting a TSDoc tag starting with "{@"

(tsdoc/syntax)


[error] 78-78: tsdoc-escape-right-brace: The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag

(tsdoc/syntax)


[error] 85-85: 'hideDrawer' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 86-86: 'page' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 87-87: 'rowsPerPage' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 88-88: 'organizations' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 92-92: 'setMode' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 144-144: tsdoc-param-tag-with-invalid-type: The @param block should not include a JSDoc-style '{type}'

(tsdoc/syntax)


[error] 145-145: tsdoc-param-tag-with-invalid-type: The @param block should not include a JSDoc-style '{type}'

(tsdoc/syntax)


[error] 157-157: tsdoc-param-tag-with-invalid-type: The @param block should not include a JSDoc-style '{type}'

(tsdoc/syntax)


[error] 159-159: 'handleChangeRowsPerPage' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 170-170: tsdoc-param-tag-with-invalid-type: The @param block should not include a JSDoc-style '{type}'

(tsdoc/syntax)


[error] 182-182: tsdoc-param-tag-with-invalid-type: The @param block should not include a JSDoc-style '{type}'

(tsdoc/syntax)


[error] 196-196: 'handleSearchByBtnClick' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

src/components/OrganizationCard/OrganizationCard.spec.tsx

[error] 13-13: Delete ·

(prettier/prettier)

🪛 GitHub Actions: PR Workflow
src/components/OrganizationCard/OrganizationCard.spec.tsx

[warning] Code style issues found. File needs to be formatted using Prettier.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (3)
src/components/OrganizationCard/OrganizationCard.spec.tsx (2)

1-29: LGTM! Clean transition from Jest to Vitest.

The migration from Jest to Vitest is well-implemented with proper mocking setup for react-router-dom.

🧰 Tools
🪛 eslint

[error] 13-13: Delete ·

(prettier/prettier)

🪛 GitHub Actions: PR Workflow

[warning] Code style issues found. File needs to be formatted using Prettier.


31-47: LGTM! Well-structured test data setup.

The defaultProps object provides comprehensive test data covering all required props with realistic values.

🧰 Tools
🪛 GitHub Actions: PR Workflow

[warning] Code style issues found. File needs to be formatted using Prettier.

src/screens/UserPortal/Organizations/Organizations.tsx (1)

277-277: ⚠️ Potential issue

Implementation appears incomplete.

The component has several issues:

  1. Unused state variables: hideDrawer, page, rowsPerPage, organizations
  2. Unused state setter: setMode
  3. Unused handlers: handleChangeRowsPerPage, handleSearchByBtnClick
  4. Empty return statement with only a placeholder comment

Please either implement the missing functionality or remove unused code.


/**
* This file contains unit tests for the `OrganizationCard` component.
*
* The tests cover:
*
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 formatting to pass pipeline checks.

Remove the whitespace from the empty line to resolve the Prettier formatting issue.

- * 
+ *
📝 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
*
*
🧰 Tools
🪛 eslint

[error] 13-13: Delete ·

(prettier/prettier)

🪛 GitHub Actions: PR Workflow

[warning] Code style issues found. File needs to be formatted using Prettier.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a025661 and a142f66.

📒 Files selected for processing (1)
  • package.json (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: PR Workflow
package.json

[error] Unauthorized file modification. This file is protected and requires the 'ignore-sensitive-files-pr' label to modify or delete.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyse Code With CodeQL (javascript)

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

🔭 Outside diff range comments (1)
src/screens/UserPortal/Organizations/Organizations.tsx (1)

Line range hint 71-90: Add error handling and loading states for data fetching.

The data transformation logic lacks error handling and loading state management.

Consider adding error and loading states:

+  const [error, setError] = useState<Error | null>(null);
+  const [isLoading, setIsLoading] = useState(true);
+
   useEffect(() => {
+    setIsLoading(true);
     if (data) {
       const orgs = data.organizationsConnection.map(
         // ... existing transformation
       );
       setOrganizations(orgs);
+      setIsLoading(false);
+    } else if (error) {
+      setError(error);
+      setIsLoading(false);
     }
-  }, [data, userId]);
+  }, [data, error, userId]);
🧹 Nitpick comments (2)
src/components/OrganizationCard/OrganizationCard.spec.tsx (1)

171-207: Consider using test.each for membership status tests

The membership status tests could be refactored to reduce duplication using test.each.

const membershipStatusTests = [
  { status: '', expectedButton: 'joinBtn' },
  { status: 'accepted', expectedButton: 'manageBtn' },
  { status: 'pending', expectedButton: 'withdrawBtn' }
];

test.each(membershipStatusTests)(
  'displays correct button when status is "$status"',
  ({ status, expectedButton }) => {
    render(
      <MockedProvider>
        <I18nextProvider i18n={i18nForTest}>
          <OrganizationCard
            {...defaultProps}
            membershipRequestStatus={status}
          />
        </I18nextProvider>
      </MockedProvider>
    );
    expect(screen.getByTestId(expectedButton)).toBeInTheDocument();
  }
);
src/screens/UserPortal/Organizations/Organizations.tsx (1)

Line range hint 11-35: Enhance interface documentation with property descriptions.

The interface documentation should include descriptions for each property to improve code maintainability.

Add TSDoc comments for each property:

 /**
  * Interface for the organization object.
+ * @property _id - Unique identifier for the organization
+ * @property name - Name of the organization
+ * @property image - URL of the organization's image
+ * @property description - Detailed description of the organization
+ * @property admins - List of organization administrators
+ * @property members - List of organization members
+ * @property address - Physical address details of the organization
+ * @property membershipRequestStatus - Current status of user's membership request
+ * @property userRegistrationRequired - Whether registration is required to join
+ * @property membershipRequests - List of pending membership requests
  */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a142f66 and d2150ba.

📒 Files selected for processing (2)
  • src/components/OrganizationCard/OrganizationCard.spec.tsx (1 hunks)
  • src/screens/UserPortal/Organizations/Organizations.tsx (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test Application
🔇 Additional comments (7)
src/components/OrganizationCard/OrganizationCard.spec.tsx (5)

13-13: Fix formatting to pass pipeline checks

Remove the trailing whitespace from the empty line.

- * 
+ *

1-29: LGTM! Clean migration from Jest to Vitest

The framework migration is well-implemented with proper async/await pattern for mocking.


31-47: LGTM! Well-structured test data

The defaultProps object is comprehensive and properly structured, covering all necessary fields for thorough testing.


54-81: LGTM! Thorough visual element testing

The tests effectively verify the rendering of both image and non-image scenarios with appropriate assertions.

Also applies to: 83-98


100-144: LGTM! Comprehensive button state testing

The tests effectively verify the correct button rendering for different membership states (empty, accepted, pending).

src/screens/UserPortal/Organizations/Organizations.tsx (2)

40-49: Enhance component documentation with more details.

The component documentation should include more details about its functionality and props.

Expand the TSDoc documentation:

 /**
- * Component to render the organizations of a user with pagination and filtering.
+ * Organizations component handles the display and management of organizations.
+ * It provides filtering and different view modes for all, joined, and created organizations.
+ * 
+ * @remarks
+ * The component fetches organizations data using three different queries:
+ * - USER_ORGANIZATION_CONNECTION for all organizations
+ * - USER_JOINED_ORGANIZATIONS for joined organizations
+ * - USER_CREATED_ORGANIZATIONS for created organizations
+ * 
  * @returns {JSX.Element} The Organizations component.
  */

119-130: Verify routing implementation for the Visit button.

Ensure that the routing implementation for the Visit button aligns with the application's routing system.

Run the following script to verify the routing implementation:

Comment on lines +119 to +130
/>
<InputGroup.Text
className={`${styles.colorPrimary} ${styles.borderNone}`}
style={{ cursor: 'pointer' }}
onClick={handleSearchByBtnClick}
data-testid="searchBtn"
>
<SearchOutlined className={`${styles.colorWhite}`} />
</InputGroup.Text>
</InputGroup>
<Dropdown drop="down-centered">
<Dropdown.Toggle
className={`${styles.colorPrimary} ${styles.borderNone}`}
variant="success"
id="dropdown-basic"
data-testid={`modeChangeBtn`}
>
{modes[mode]}
</Dropdown.Toggle>
<Dropdown.Menu>
{modes.map((value, index) => {
return (
<Dropdown.Item
key={index}
data-testid={`modeBtn${index}`}
onClick={(): void => setMode(index)}
>
{value}
</Dropdown.Item>
);
})}
</Dropdown.Menu>
</Dropdown>
</div>

<div
className={`d-flex flex-column justify-content-between ${styles.content}`}
>
<div
className={`d-flex flex-column ${styles.gap} ${styles.paddingY}`}
>
{loadingOrganizations ? (
<div className={`d-flex flex-row justify-content-center`}>
<HourglassBottomIcon /> <span>Loading...</span>
</div>
) : (
<>
{' '}
{organizations && organizations.length > 0 ? (
(rowsPerPage > 0
? organizations.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage,
)
: /* istanbul ignore next */
organizations
).map((organization: InterfaceOrganization, index) => {
const cardProps: InterfaceOrganizationCardProps = {
name: organization.name,
image: organization.image,
id: organization._id,
description: organization.description,
admins: organization.admins,
members: organization.members,
address: organization.address,
membershipRequestStatus:
organization.membershipRequestStatus,
userRegistrationRequired:
organization.userRegistrationRequired,
membershipRequests: organization.membershipRequests,
};
return <OrganizationCard key={index} {...cardProps} />;
})
) : (
<span>{t('nothingToShow')}</span>
)}
</>
)}
</div>
<table>
<tbody>
<tr>
<PaginationList
count={
/* istanbul ignore next */
organizations ? organizations.length : 0
}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</tr>
</tbody>
</table>
</div>
</div>
</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.

⚠️ Potential issue

Implement the Visit button feature and enhance UI components.

The current implementation doesn't include the Visit button feature mentioned in the PR objectives and lacks proper UI components.

Consider implementing the following improvements:

   return (
-    <div>
+    <div className="organizations-container">
+      {isLoading ? (
+        <LoadingSpinner />
+      ) : error ? (
+        <ErrorMessage error={error} />
+      ) : organizations.length > 0 ? (
         organizations.map((org) => (
-          <div key={org._id}>
-            <h3>{org.name}</h3>
-            <p>{org.description}</p>
+          <div key={org._id} className="organization-card">
+            <div className="organization-info">
+              <h3>{org.name}</h3>
+              <p>{org.description}</p>
+            </div>
+            <button
+              className="visit-button"
+              onClick={() => window.location.href = `/organization/${org._id}`}
+            >
+              Visit
+            </button>
           </div>
         ))
       ) : (
-        <p>No organizations found</p>
+        <div className="empty-state">
+          <p>No organizations found</p>
+        </div>
       )}
     </div>
   );

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

Comment on lines 94 to +116
useEffect(() => {
if (mode === 0) {
if (data) {
const organizations = data.organizationsConnection.map(
(organization: InterfaceOrganization) => {
let membershipRequestStatus = '';
if (
organization.members.find(
(member: { _id: string }) => member._id === userId,
)
)
membershipRequestStatus = 'accepted';
else if (
organization.membershipRequests.find(
(request: { user: { _id: string } }) =>
request.user._id === userId,
)
)
membershipRequestStatus = 'pending';
return { ...organization, membershipRequestStatus };
},
);
setOrganizations(organizations);
}
} else if (mode === 1) {
if (joinedOrganizationsData && joinedOrganizationsData.users.length > 0) {
const organizations =
joinedOrganizationsData.users[0]?.user?.joinedOrganizations || [];
setOrganizations(organizations);
}
} else if (mode === 2) {
if (
createdOrganizationsData &&
createdOrganizationsData.users.length > 0
) {
const organizations =
createdOrganizationsData.users[0]?.appUserProfile
?.createdOrganizations || [];
setOrganizations(organizations);
}
if (joinedOrganizationsData?.users?.length > 0) {
const orgs =
joinedOrganizationsData.users[0]?.user?.joinedOrganizations.map(
(org: InterfaceOrganization) => ({
...org,
membershipRequestStatus: 'accepted',
isJoined: true,
}),
) || [];
setOrganizations(orgs);
} else if (createdOrganizationsData?.users?.length > 0) {
const orgs =
createdOrganizationsData.users[0]?.appUserProfile?.createdOrganizations.map(
(org: InterfaceOrganization) => ({
...org,
membershipRequestStatus: 'accepted',
isJoined: true,
}),
) || [];
setOrganizations(orgs);
}
}, [mode, data, joinedOrganizationsData, createdOrganizationsData, userId]);
}, [joinedOrganizationsData, createdOrganizationsData, userId]);
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

Resolve potential state conflicts in useEffect hooks.

Multiple useEffect hooks setting the organizations state could lead to race conditions and inconsistent state updates.

Consider consolidating the data handling:

-  useEffect(() => {
-    if (joinedOrganizationsData?.users?.length > 0) {
-      const orgs = // ... existing transformation
-      setOrganizations(orgs);
-    } else if (createdOrganizationsData?.users?.length > 0) {
-      const orgs = // ... existing transformation
-      setOrganizations(orgs);
-    }
-  }, [joinedOrganizationsData, createdOrganizationsData, userId]);
+  useEffect(() => {
+    const getOrganizations = () => {
+      if (joinedOrganizationsData?.users?.length > 0) {
+        return joinedOrganizationsData.users[0]?.user?.joinedOrganizations.map(
+          (org: InterfaceOrganization) => ({
+            ...org,
+            membershipRequestStatus: 'accepted',
+            isJoined: true,
+          }),
+        ) || [];
+      }
+      if (createdOrganizationsData?.users?.length > 0) {
+        return createdOrganizationsData.users[0]?.appUserProfile?.createdOrganizations.map(
+          (org: InterfaceOrganization) => ({
+            ...org,
+            membershipRequestStatus: 'accepted',
+            isJoined: true,
+          }),
+        ) || [];
+      }
+      return [];
+    };
+    
+    setOrganizations(getOrganizations());
+  }, [joinedOrganizationsData, createdOrganizationsData, userId]);
📝 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 (mode === 0) {
if (data) {
const organizations = data.organizationsConnection.map(
(organization: InterfaceOrganization) => {
let membershipRequestStatus = '';
if (
organization.members.find(
(member: { _id: string }) => member._id === userId,
)
)
membershipRequestStatus = 'accepted';
else if (
organization.membershipRequests.find(
(request: { user: { _id: string } }) =>
request.user._id === userId,
)
)
membershipRequestStatus = 'pending';
return { ...organization, membershipRequestStatus };
},
);
setOrganizations(organizations);
}
} else if (mode === 1) {
if (joinedOrganizationsData && joinedOrganizationsData.users.length > 0) {
const organizations =
joinedOrganizationsData.users[0]?.user?.joinedOrganizations || [];
setOrganizations(organizations);
}
} else if (mode === 2) {
if (
createdOrganizationsData &&
createdOrganizationsData.users.length > 0
) {
const organizations =
createdOrganizationsData.users[0]?.appUserProfile
?.createdOrganizations || [];
setOrganizations(organizations);
}
if (joinedOrganizationsData?.users?.length > 0) {
const orgs =
joinedOrganizationsData.users[0]?.user?.joinedOrganizations.map(
(org: InterfaceOrganization) => ({
...org,
membershipRequestStatus: 'accepted',
isJoined: true,
}),
) || [];
setOrganizations(orgs);
} else if (createdOrganizationsData?.users?.length > 0) {
const orgs =
createdOrganizationsData.users[0]?.appUserProfile?.createdOrganizations.map(
(org: InterfaceOrganization) => ({
...org,
membershipRequestStatus: 'accepted',
isJoined: true,
}),
) || [];
setOrganizations(orgs);
}
}, [mode, data, joinedOrganizationsData, createdOrganizationsData, userId]);
}, [joinedOrganizationsData, createdOrganizationsData, userId]);
useEffect(() => {
const getOrganizations = () => {
if (joinedOrganizationsData?.users?.length > 0) {
return joinedOrganizationsData.users[0]?.user?.joinedOrganizations.map(
(org: InterfaceOrganization) => ({
...org,
membershipRequestStatus: 'accepted',
isJoined: true,
}),
) || [];
}
if (createdOrganizationsData?.users?.length > 0) {
return createdOrganizationsData.users[0]?.appUserProfile?.createdOrganizations.map(
(org: InterfaceOrganization) => ({
...org,
membershipRequestStatus: 'accepted',
isJoined: true,
}),
) || [];
}
return [];
};
setOrganizations(getOrganizations());
}, [joinedOrganizationsData, createdOrganizationsData, userId]);

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.

3 participants