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

feat(web): members setting #1186

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open

feat(web): members setting #1186

wants to merge 41 commits into from

Conversation

ZTongci
Copy link
Contributor

@ZTongci ZTongci commented Oct 22, 2024

Overview

What I've done

Add member's page for workspace.

What I haven't done

How I tested

Which point I want you to review particularly

Memo

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced member management functionalities, including adding, updating, and removing members from workspaces.
    • Added a search feature for users by name or email within the workspace.
    • New Members component for managing workspace members.
    • Enhanced workspace settings with improved role management for members.
    • New icons added for better visual representation in the UI.
  • Bug Fixes

    • Improved error handling for workspace operations to ensure valid input is checked before execution.
  • Documentation

    • Updated English translations for user roles and workspace management terms, enhancing user experience.
    • Added new entries related to workspace operations and user management feedback.
  • Chores

    • Removed the disabled state from the "members" tab, enabling user interaction.

Copy link

coderabbitai bot commented Oct 22, 2024

Walkthrough

The changes in this pull request enhance the functionality of workspace and member management within the application. Key modifications include the introduction of new functions for updating member roles and searching for users, as well as improvements to error handling in existing workspace operations. A new Members component is added to the UI for managing workspace members, and various translations related to user roles and workspace management are introduced. Additionally, the disabled property for the "members" tab is removed, allowing for user interaction.

Changes

File Path Change Summary
web/src/beta/features/WorkspaceSetting/hooks.ts - Updated WorkspacePayload to make name optional.
- Added handleUpdateMemberOfWorkspace and handleSearchUser functions.
- Modified existing functions for error handling.
web/src/beta/features/WorkspaceSetting/index.tsx - Added handleAddMemberToWorkspace, handleSearchUser, handleUpdateMemberOfWorkspace, and handleRemoveMemberFromWorkspace.
- Conditionally rendered <Members /> component for member management.
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx - Introduced Members component for managing workspace members, including search and role management functionalities.
web/src/beta/hooks/useAccountSettingsTabs.ts - Removed disabled property from the "members" tab in accountSettingTabs.
web/src/beta/lib/reearth-ui/components/Icon/icons.ts - Added new icon memberAdd and corrected import typo for PencilLine.
web/src/services/api/meApi.ts - Added GET_USER_BY_SEARCH query and useSearchUser function for searching users.
web/src/services/i18n/translations/en.yml - Added new translation keys related to user roles and workspace management.
web/src/services/i18n/translations/ja.yml - Cleared existing translations, preparing for new entries.
web/src/services/state/index.ts - Updated members type in Workspace from any[] to TeamMember[].
web/src/beta/features/Dashboard/type.ts - Updated members type in Workspace from Member[] to TeamMember[].
web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx - Updated member prop type from Member to TeamMember.

Possibly related PRs

Suggested labels

server

Suggested reviewers

  • mkumbobeaty
  • airslice
  • pyshx

🐰 In the workspace, we hop and play,
Adding members, brightening the day!
Search and update, all in a row,
With each new feature, our teamwork will grow!
So let’s celebrate, with joy and cheer,
For the changes that bring us all 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.

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

netlify bot commented Oct 22, 2024

Deploy Preview for reearth-web ready!

Name Link
🔨 Latest commit f013644
🔍 Latest deploy log https://app.netlify.com/sites/reearth-web/deploys/671a0b52acd4d50008d9d3ee
😎 Deploy Preview https://deploy-preview-1186--reearth-web.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@ZTongci ZTongci marked this pull request as draft October 22, 2024 08:37
@ZTongci ZTongci changed the title Feat(web): members setting feat(web): members setting Oct 22, 2024
@ZTongci ZTongci marked this pull request as ready for review October 24, 2024 02:47
Copy link

@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: 11

🧹 Outside diff range and nitpick comments (9)
web/src/beta/features/WorkspaceSetting/index.tsx (1)

9-9: Consider simplifying the Members component path.

The path ./innerPages/Members/Members contains a redundant "Members". Consider moving the component to ./innerPages/Members/index.tsx to maintain a cleaner import structure.

web/src/beta/features/WorkspaceSetting/hooks.ts (1)

141-160: Fix grammatical and consistency issues in member update handler.

  1. Fix grammatical error in success message
  2. Make error message consistent with other handlers
 if (status === "success") {
-  console.log("Member update successfully");
+  console.log("Member updated successfully");
 }
} catch (error) {
-  console.error("Failed to update member from workspace:", error);
+  console.error("Failed to update member in workspace:", error);
}
web/src/beta/lib/reearth-ui/components/Icon/icons.ts (1)

Line range hint 262-262: Fix PencilLine import/usage mismatch

There's a mismatch between the imported variable name and the SVG file:

  • Import uses PencilLilne (with typo)
  • SVG file is named PencilLine.svg

Apply this fix:

-  pencilLine: PencilLilne,
+  pencilLine: PencilLine,

And update the import statement:

-import PencilLilne from "./Icons/PencilLine.svg?react";
+import PencilLine from "./Icons/PencilLine.svg?react";
web/src/services/i18n/translations/en.yml (1)

Line range hint 471-476: Standardize workspace-related message formats.

The workspace-related messages have inconsistent formatting and varying levels of detail.

Consider standardizing the messages:

-Failed to create workspace.: ''
-Successfully created workspace!: ''
-Failed to delete workspace.: ''
-Successfully deleted workspace!: ''
-Failed to update workspace.: ''
-Successfully updated workspace!: ''
+Failed to create workspace.: 'Unable to create workspace. Please try again.'
+Successfully created workspace!: 'Workspace "{name}" has been created successfully!'
+Failed to delete workspace.: 'Unable to delete workspace. Please try again.'
+Successfully deleted workspace!: 'Workspace has been permanently deleted.'
+Failed to update workspace.: 'Unable to update workspace settings. Please try again.'
+Successfully updated workspace!: 'Workspace settings have been updated successfully!'

This standardization:

  1. Adds more context to error messages
  2. Makes success messages more specific
  3. Maintains consistent punctuation
  4. Uses placeholder for dynamic content where applicable
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (5)

313-313: Localize the placeholder text

The placeholder text "[email protected]" is hardcoded in English. To support localization, wrap it with the t function.

Apply this diff to fix:

<TextInput
-  placeholder="[email protected]"
+  placeholder={t("[email protected]")}
  value={memberSearchInput}
  onChange={(input) => {
    setMemberSearchInput(input);
  }}
/>

318-323: Capture input value before clearing it

In the onKeyDown handler, you're setting memberSearchInput to an empty string before using its value for setDebouncedInput. Since state updates are asynchronous, capture the trimmed input in a variable before clearing the input field to avoid inconsistencies.

Apply this diff to fix:

onKeyDown={(e) => {
  if (e.key === "Enter" && memberSearchInput.trim() !== "") {
+   const trimmedInput = memberSearchInput.trim();
    setMemberSearchInput("");
-   setDebouncedInput(memberSearchInput.trim());
+   setDebouncedInput(trimmedInput);
  }
}}

337-362: Simplify conditional rendering with optional chaining

You can simplify the conditional rendering by using optional chaining (?.), which makes the code more concise and readable.

Apply this diff to simplify the code:

-              {memberSearchResults &&
-                memberSearchResults.map((memberSearchResult) => (
+              {memberSearchResults?.map((memberSearchResult) => (
                  <ItemContainer key={memberSearchResult.id}>
                    <UserInfo>
                      <span>{memberSearchResult.userName}</span>
                      <span style={{ color: theme.content.weak }}>
                        {memberSearchResult.email}
                      </span>
                    </UserInfo>
                    <DeleteIcon
                      icon="trash"
                      size="normal"
                      hasBorder={false}
                      appearance="simple"
                      onClick={() => {
                        setMemberSearchInput("");
                        setDebouncedInput("");
                        setMemberSearchResults(
                          memberSearchResults.filter(
                            (element) => element.id !== memberSearchResult.id
                          ),
                        );
                      }}
                    />
                  </ItemContainer>
-                ))}
+              ))}
🧰 Tools
🪛 Biome

[error] 337-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


214-214: Use Role enum instead of string literals

You're comparing user.role to string literals like "OWNER". For type safety and consistency, consider using the Role enum.

Apply this diff to fix:

{
  icon: "arrowLeftRight",
  id: "changeRole",
  title: t("Change Role"),
- disabled: user.role === "OWNER",
+ disabled: user.role === Role.Owner,
  onClick: () => {
    setActiveEditIndex((prevIndex) =>
      prevIndex === index ? null : index,
    );
  },
},
{
  icon: "close",
  id: "remove",
  title: t("Remove"),
- disabled: user.role === "OWNER",
+ disabled: user.role === Role.Owner,
  onClick: () => {
    if (currentWorkspace?.id) {
      handleRemoveMemberFromWorkspace({
        teamId: currentWorkspace?.id,
        userId: user.id,
      });
    }
    setWorkspaceMembers(
      workspaceMembers.filter(
        (workspaceMember) => workspaceMember.id !== user.id,
      ),
    );
  },
},

Also applies to: 225-225


334-334: Consistent use of apostrophes in translated strings

The string "Didn’t find the user" uses a typographic apostrophe (). For consistency and to avoid encoding issues, consider using a standard apostrophe (').

Apply this diff to fix:

{t("Didn't find the user")}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b922fbb and 6c38de6.

⛔ Files ignored due to path filters (1)
  • web/src/beta/lib/reearth-ui/components/Icon/Icons/MemberAdd.svg is excluded by !**/*.svg
📒 Files selected for processing (8)
  • web/src/beta/features/WorkspaceSetting/hooks.ts (6 hunks)
  • web/src/beta/features/WorkspaceSetting/index.tsx (3 hunks)
  • web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
  • web/src/beta/hooks/useAccountSettingsTabs.ts (1 hunks)
  • web/src/beta/lib/reearth-ui/components/Icon/icons.ts (2 hunks)
  • web/src/services/api/meApi.ts (3 hunks)
  • web/src/services/i18n/translations/en.yml (2 hunks)
  • web/src/services/i18n/translations/ja.yml (7 hunks)
✅ Files skipped from review due to trivial changes (1)
  • web/src/services/i18n/translations/ja.yml
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx

[error] 337-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (11)
web/src/beta/hooks/useAccountSettingsTabs.ts (2)

23-23: LGTM! Path follows RESTful conventions.

The path /settings/workspaces/:workspaceId/members follows RESTful conventions and maintains consistency with other workspace-related routes.


22-24: Verify the Members component implementation.

The removal of the disabled property from the members tab suggests this feature is now ready for use. Please ensure that:

  1. The corresponding Members component is fully implemented
  2. Proper access controls are in place
  3. The route is correctly configured in the router
✅ Verification successful

Let me gather more information about the Members component implementation and access controls by checking its contents.

This will help us verify:

  1. The actual implementation of the Members component
  2. Workspace-specific access control mechanisms
  3. Route protection implementation for the members page

Let me check one more thing about the routing and authentication setup since the previous type-specific searches failed.

This will help us verify the routing setup and authentication mechanisms in place.


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

The Members component implementation is complete and properly secured

The verification shows that:

  1. The Members component is fully implemented with proper CRUD operations for workspace members
  2. Access control is in place through:
    • The useAuth hook which enforces authentication
    • Role-based permissions (OWNER, MAINTAINER, WRITER, READER)
    • Proper restrictions on member management (e.g., OWNER role cannot be removed)
  3. The route /settings/workspaces/:workspaceId/members is correctly configured in useAccountSettingsTabs.ts

The removal of the disabled property is justified as the feature appears production-ready with all necessary security controls and functionality in place.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the Members component implementation and routing

# Test 1: Check if Members component exists
echo "Checking for Members component..."
fd -e tsx -e ts "Members\.(tsx|ts)$"

# Test 2: Check router configuration for the members path
echo "Checking router configuration..."
rg -l "/settings/workspaces/.+/members"

# Test 3: Check for access control implementation
echo "Checking access control implementation..."
rg -l "useAuth|isAuthorized|checkPermission"

Length of output: 1186


Script:

#!/bin/bash
# Check the Members component implementation
echo "Members component implementation:"
cat "web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx"

# Check for workspace-specific access controls
echo -e "\nWorkspace access control checks:"
rg -A 5 "workspace.*permission|workspace.*access" --type ts --type tsx

# Check for any route protection mechanisms
echo -e "\nRoute protection mechanisms:"
rg -A 5 "ProtectedRoute|RequireAuth|authGuard" --type ts --type tsx

Length of output: 14194


Script:

#!/bin/bash
# Check routing and authentication setup
echo "Checking route configuration and auth protection:"
rg -A 10 "Route.*settings/workspaces|/settings/workspaces" 

# Check workspace-related hooks and auth
echo -e "\nChecking workspace auth hooks:"
cat "web/src/services/auth/useAuth.ts"

# Check if the workspace route is protected
echo -e "\nChecking workspace route protection:"
rg -C 5 "workspaces/:workspaceId/members" --type-not test

Length of output: 5004

web/src/beta/features/WorkspaceSetting/index.tsx (1)

21-25: Verify handler implementations and type definitions.

The new member management handlers look well-organized. Let's verify their implementations and type definitions.

#!/bin/bash
# Description: Check handler implementations and type definitions

# Check the hook implementation
echo "Checking hook implementation:"
ast-grep --pattern 'const useWorkspaceHook = () => {
  $$$
  return {
    $$$
    handleAddMemberToWorkspace,
    handleSearchUser,
    handleUpdateMemberOfWorkspace,
    handleRemoveMemberFromWorkspace,
    $$$
  };
}'

# Check for TypeScript type definitions
echo -e "\nChecking type definitions:"
rg -A 2 "type\s+(?:Add|Search|Update|Remove)Member" --type typescript
web/src/services/api/meApi.ts (3)

5-6: LGTM: Import statements are properly organized.

The new imports are correctly added and used within the file.


132-132: LGTM: Export is properly added.

The new hook is correctly exported and maintains the alphabetical order in the returned object.


81-104: Verify the integration with workspace settings.

Let's ensure the GraphQL query and its usage in workspace settings are properly implemented.

✅ Verification successful

Let me gather more information about the GraphQL query implementation and workspace settings integration.


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

Integration with workspace settings is properly implemented

The verification shows:

  • The GraphQL query GET_USER_BY_SEARCH is correctly defined in user.ts with the required fields (id, name, email)
  • The useSearchUser hook is properly integrated in WorkspaceSetting/hooks.ts with:
    • Proper error handling
    • Skip condition for empty search
    • Status handling for the search results
  • The hook's return values (user and status) are correctly consumed in the workspace settings implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the GraphQL query implementation and its usage

# Test 1: Check the GraphQL query definition
echo "Checking GraphQL query definition..."
rg -l "GET_USER_BY_SEARCH" --type ts

# Test 2: Check the usage of useSearchUser hook
echo "Checking useSearchUser hook usage..."
rg "useSearchUser" --type ts

# Test 3: Check for any related test files
echo "Checking for related test files..."
fd -e test.ts -e test.tsx

Length of output: 1848


Script:

#!/bin/bash
# Check the GraphQL query definition and its structure
echo "Checking GraphQL query definition..."
rg -A 5 "GET_USER_BY_SEARCH" web/src/services/gql/queries/user.ts

# Check the workspace settings implementation
echo "Checking workspace settings implementation..."
rg -A 10 "useSearchUser" web/src/beta/features/WorkspaceSetting/hooks.ts

# Check if there are any workspace settings related test files
echo "Checking workspace settings tests..."
fd "WorkspaceSetting" -e test.ts -e test.tsx

Length of output: 1364

web/src/beta/features/WorkspaceSetting/hooks.ts (2)

188-190: LGTM!

The exports are complete and properly ordered.


6-6: Verify the optional name property in WorkspacePayload.

Making name optional in WorkspacePayload seems inconsistent with its usage in handleCreateWorkspace where it's required. Consider keeping it required or document why it's optional.

✅ Verification successful

Based on the search results, I can now generate a final response as I have enough context to verify the optionality of the name property in WorkspacePayload.

The optional name property in WorkspacePayload is correctly implemented

The optionality of the name property in WorkspacePayload is justified as this type is used across different contexts:

  • In handleCreateWorkspace and handleUpdateWorkspace, the code properly checks for the presence of name before proceeding:
    if (name) {
      const { status } = await useCreateWorkspace(name);
      // ...
    }
  • The same type is reused for member management operations (handleAddMemberToWorkspace, handleRemoveMemberFromWorkspace) where name is not required.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all usages of WorkspacePayload to verify the optionality of name
rg -A 5 "WorkspacePayload" 

Length of output: 6369

web/src/beta/lib/reearth-ui/components/Icon/icons.ts (1)

90-90: LGTM: MemberAdd icon addition

The addition of the MemberAdd icon and its export is well-structured and aligns with the workspace member management feature being implemented.

Also applies to: 249-249

web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (2)

180-181: Ensure consistent typing for 'role'

When updating the member's role, ensure that roleValue is of the correct type and consistent with the Role enum. This prevents type mismatches and potential runtime errors.

Confirm that roleValue is of type Role or cast it appropriately if necessary.


318-323: ⚠️ Potential issue

Handle potential empty input on 'Enter' key press

When the user presses the 'Enter' key, you should ensure that the trimmed input is not empty before proceeding. This avoids unnecessary state updates.

Apply this diff to fix:

onKeyDown={(e) => {
  if (e.key === "Enter") {
    const trimmedInput = memberSearchInput.trim();
+   if (trimmedInput === "") return;
    setMemberSearchInput("");
    setDebouncedInput(trimmedInput);
  }
}}

Likely invalid or redundant comment.

web/src/beta/features/WorkspaceSetting/index.tsx Outdated Show resolved Hide resolved
web/src/services/api/meApi.ts Show resolved Hide resolved
web/src/beta/features/WorkspaceSetting/hooks.ts Outdated Show resolved Hide resolved
web/src/services/i18n/translations/en.yml Show resolved Hide resolved
web/src/services/i18n/translations/en.yml Show resolved Hide resolved
web/src/services/i18n/translations/en.yml Show resolved Hide resolved
Copy link

codecov bot commented Oct 24, 2024

Codecov Report

Attention: Patch coverage is 1.78571% with 550 lines in your changes missing coverage. Please review.

Project coverage is 18.82%. Comparing base (e33d88e) to head (8c01682).
Report is 21 commits behind head on main.

Files with missing lines Patch % Lines
...es/WorkspaceSetting/innerPages/Members/Members.tsx 0.00% 447 Missing ⚠️
web/src/beta/features/WorkspaceSetting/hooks.ts 0.00% 62 Missing ⚠️
web/src/beta/features/WorkspaceSetting/index.tsx 0.00% 20 Missing ⚠️
web/src/services/api/meApi.ts 28.57% 20 Missing ⚠️
web/src/beta/hooks/useAccountSettingsTabs.ts 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1186      +/-   ##
==========================================
+ Coverage   13.85%   18.82%   +4.97%     
==========================================
  Files         595      591       -4     
  Lines       64056    64917     +861     
  Branches      660      596      -64     
==========================================
+ Hits         8873    12220    +3347     
+ Misses      55183    52697    -2486     
Flag Coverage Δ
web 18.82% <1.78%> (+4.97%) ⬆️
web-beta 18.82% <1.78%> (+4.97%) ⬆️
web-classic 18.82% <1.78%> (+4.97%) ⬆️
web-utils 18.82% <1.78%> (+4.97%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...b/src/beta/lib/reearth-ui/components/Icon/icons.ts 100.00% <100.00%> (+100.00%) ⬆️
web/src/beta/hooks/useAccountSettingsTabs.ts 0.00% <0.00%> (ø)
web/src/beta/features/WorkspaceSetting/index.tsx 0.00% <0.00%> (ø)
web/src/services/api/meApi.ts 40.00% <28.57%> (-8.24%) ⬇️
web/src/beta/features/WorkspaceSetting/hooks.ts 0.00% <0.00%> (ø)
...es/WorkspaceSetting/innerPages/Members/Members.tsx 0.00% <0.00%> (ø)

... and 90 files with indirect coverage changes

Copy link

@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 (1)
web/src/beta/features/WorkspaceSetting/index.tsx (1)

Line range hint 22-58: Consider wrapping with an error boundary.

Since this component handles critical workspace operations, consider implementing an error boundary to gracefully handle and report any unexpected errors.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6c38de6 and 8c01682.

📒 Files selected for processing (3)
  • web/src/beta/features/WorkspaceSetting/hooks.ts (6 hunks)
  • web/src/beta/features/WorkspaceSetting/index.tsx (2 hunks)
  • web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx

[error] 337-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (3)
web/src/beta/features/WorkspaceSetting/index.tsx (2)

17-20: Great implementation of the TABS enum!

The centralization of tab values using an enum improves type safety and maintainability.


27-30: Verify error handling in member management operations.

Let's ensure proper error handling is implemented for these critical operations.

✅ Verification successful

Based on the results, I can now generate the final response since we have clear evidence of error handling implementation.

Error handling is properly implemented for all member management operations

The verification shows comprehensive error handling across all workspace member operations:

  • All operations are wrapped in try-catch blocks
  • Errors are properly logged with descriptive messages
  • Error states are captured and returned where appropriate
  • Consistent error handling pattern is maintained across all member management functions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check error handling implementation in workspace hooks

# Check for try-catch blocks in member management operations
echo "Checking error handling in member management operations:"
rg -A 10 "(handleAddMemberToWorkspace|handleUpdateMemberOfWorkspace|handleRemoveMemberFromWorkspace|handleSearchUser)\s*=\s*async" ./web/src/beta/features/WorkspaceSetting/hooks.ts

# Check for error state management
echo -e "\nChecking error state management:"
rg "(?i)(error|catch|try)" ./web/src/beta/features/WorkspaceSetting/hooks.ts

Length of output: 1580

web/src/beta/features/WorkspaceSetting/hooks.ts (1)

6-6: ⚠️ Potential issue

Review type safety for optional name property.

The name property is marked as optional in WorkspacePayload, but it's required in functions like handleCreateWorkspace. This mismatch could lead to runtime errors.

Consider using separate types for different operations:

type CreateWorkspacePayload = {
  name: string;  // required
  teamId: string;
};

type UpdateWorkspacePayload = {
  name?: string;  // optional
  teamId: string;
};

Copy link

@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 and nitpick comments (5)
web/src/services/i18n/translations/en.yml (2)

298-298: Improve user search feedback message.

The current message "Didn't find the user" is informal and could be more helpful.

Consider this improvement:

-Didn't find the user: ''
+No matching users found. Please try a different search term.: ''

Line range hint 299-310: Fix grammar and punctuation consistency in workspace messages.

Several workspace-related messages need attention for grammar and punctuation consistency.

Apply these improvements:

-This process will remove this workspace: ''
+This process will remove this workspace.: ''
-'This action cannot be undone. ': ''
+'This action cannot be undone.': ''
-Please to make sure you don't have any projects in your workspace, then you can continue.: ''
+Please make sure you don't have any projects in your workspace before continuing.: ''
web/src/services/i18n/translations/ja.yml (3)

Line range hint 3-84: Missing translations for core UI elements

A large number of core UI elements have their translations reset to empty strings. This will cause the UI to fall back to English for Japanese users, degrading their experience.

Please provide Japanese translations for these basic UI elements. For reference, some previous translations were:

  • Name: '名前'
  • Password: 'パスワード'
  • Description: '説明'

Line range hint 299-310: Add Japanese translations for workspace management

Workspace management strings are missing translations:

Suggested translations based on common Japanese software localizations:

-Workspace: ''
-Workspace Name: ''
-Remove this workspace: ''
-This process will remove this workspace: ''
-Remove workspace: ''
-Delete workspace: ''
-I am sure I want to delete this workspace.: ''
-'This action cannot be undone. ': ''
-This will permanently delete the workspace and all related projects, assets and datasets for all team members.: ''
-Please type your workspace name to continue.: ''
-You are going to delete a workspace.: ''
-Please to make sure you don't have any projects in your workspace, then you can continue.: ''
+Workspace: 'ワークスペース'
+Workspace Name: 'ワークスペース名'
+Remove this workspace: 'このワークスペースを削除'
+This process will remove this workspace: 'このワークスペースを削除します'
+Remove workspace: 'ワークスペースを削除'
+Delete workspace: 'ワークスペースを削除'
+I am sure I want to delete this workspace.: 'このワークスペースを削除することを確認しました'
+'This action cannot be undone. ': 'この操作は取り消すことができません。'
+This will permanently delete the workspace and all related projects, assets and datasets for all team members.: 'このワークスペースと、全てのチームメンバーに関連するプロジェクト、アセット、データセットが完全に削除されます。'
+Please type your workspace name to continue.: '続行するにはワークスペース名を入力してください。'
+You are going to delete a workspace.: 'ワークスペースを削除しようとしています。'
+Please to make sure you don't have any projects in your workspace, then you can continue.: 'ワークスペースにプロジェクトがないことを確認してから、続行してください。'

Line range hint 455-464: Add Japanese translations for workspace member management messages

Success/failure messages for workspace member operations are missing translations:

Suggested translations based on common Japanese software localizations:

-Failed to add member to workspace.: ''
-Successfully added member to workspace!: ''
-Failed to remove member from workspace.: ''
-Successfully removed member from workspace!: ''
-Failed to update member in workspace.: ''
-Successfully updated member in workspace!: ''
+Failed to add member to workspace.: 'ワークスペースへのメンバー追加に失敗しました。'
+Successfully added member to workspace!: 'ワークスペースへメンバーを追加しました。'
+Failed to remove member from workspace.: 'ワークスペースからのメンバー削除に失敗しました。'
+Successfully removed member from workspace!: 'ワークスペースからメンバーを削除しました。'
+Failed to update member in workspace.: 'ワークスペースのメンバー情報の更新に失敗しました。'
+Successfully updated member in workspace!: 'ワークスペースのメンバー情報を更新しました。'
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8c01682 and 7a80757.

📒 Files selected for processing (3)
  • web/src/beta/lib/reearth-ui/components/Icon/icons.ts (2 hunks)
  • web/src/services/i18n/translations/en.yml (2 hunks)
  • web/src/services/i18n/translations/ja.yml (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/beta/lib/reearth-ui/components/Icon/icons.ts
🔇 Additional comments (1)
web/src/services/i18n/translations/ja.yml (1)

Line range hint 1-464: Verify translations with a native Japanese speaker

While the suggested translations follow common software localization patterns, it's recommended to have them reviewed by a native Japanese speaker to ensure natural language usage and proper context.

✅ Verification successful

Let me try a different approach to verify the translations.

This will help us:

  1. Find any existing Japanese text in the codebase to compare translation patterns
  2. Locate all translation files to understand the localization structure

Based on the executed scripts, I can now provide a final response regarding the Japanese translations verification:

Japanese translations appear to be consistent with existing patterns in the codebase

The executed scripts revealed extensive Japanese translations throughout the codebase, particularly in UI elements, system messages, and configuration settings. The translations in the file under review follow the same style and quality as the existing translations, showing:

  • Consistent use of Japanese characters (Hiragana, Katakana, and Kanji)
  • Professional and natural language usage in system messages
  • Proper technical term translations matching the existing patterns (e.g., "プロジェクト" for "Project", "公開" for "Publish")
  • Appropriate formality level in user-facing messages
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing Japanese translations in the codebase that could be reused
rg -g '*.yml' -g '*.json' "ワークスペース|メンバー" 

Length of output: 42


Script:

#!/bin/bash
# Check for all Japanese translations in the codebase
fd -e yml -e json -x cat {} | grep -E "[ぁ-んァ-ン一-龯]"

# Also check specifically for translation files
fd "translations|i18n" -e yml -e json

Length of output: 27752

web/src/services/i18n/translations/ja.yml Show resolved Hide resolved
web/src/services/i18n/translations/ja.yml Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (5)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (5)

28-59: Consider improving type definitions with JSDoc comments and specific error types.

Add JSDoc comments to document the Props interface and use a more specific error type instead of unknown.

+/**
+ * Props for the Members component
+ */
 type Props = {
+  /** Adds a new member to the workspace */
   handleAddMemberToWorkspace: ({
     teamId,
     userId,
     role
   }: WorkspacePayload) => Promise<void>;
+  /** Searches for a user by name or email */
   handleSearchUser: (nameOrEmail: string) =>
     | {
         searchUser: {
           __typename?: "User";
           id: string;
           name: string;
           email: string;
         } | null;
         searchUserStatus: string;
         error?: undefined;
       }
     | {
-        error: unknown;
+        error: Error;
         searchUser?: undefined;
         searchUserStatus?: undefined;
       };
   // ... rest of the props
 };

125-142: Add cleanup for search results state.

Consider adding a cleanup function to reset the search results when the component unmounts or when the search input is cleared.

 useEffect(() => {
   if (
     searchUser &&
     "name" in searchUser &&
     !memberSearchResults.find(
       (memberSearchResult) => memberSearchResult.id === searchUser.id
     )
   ) {
     setMemberSearchResults([
       ...memberSearchResults,
       {
         userName: searchUser.name,
         email: searchUser.email,
         id: searchUser.id
       }
     ]);
   }
+  return () => {
+    setMemberSearchResults([]);
+  };
 }, [memberSearchResults, searchUser]);

160-165: Add ARIA labels for better accessibility.

The table headers should have proper ARIA labels for better screen reader support.

-<Table>
+<Table role="table" aria-label={t("Workspace members")}>
-  <TableHeader>{t("User Name")}</TableHeader>
+  <TableHeader role="columnheader">{t("User Name")}</TableHeader>
-  <TableHeader>{t("Email")}</TableHeader>
+  <TableHeader role="columnheader">{t("Email")}</TableHeader>
-  <TableHeader>{t("Role")}</TableHeader>
+  <TableHeader role="columnheader">{t("Role")}</TableHeader>
-  <TableHeader />
+  <TableHeader role="columnheader" aria-label={t("Actions")} />

314-326: Add loading state feedback for search input.

The search input should provide visual feedback when the search is in progress.

 <TextInput
   placeholder="[email protected]"
   value={memberSearchInput}
+  loading={searchUserStatus === "loading"}
   onChange={(input) => {
     setMemberSearchInput(input);
   }}
   onKeyDown={(e) => {
     if (e.key === "Enter" && memberSearchInput.trim() !== "") {
       setMemberSearchInput("");
       setDebouncedInput(memberSearchInput.trim());
     }
   }}
 />

436-442: Use theme variables for DeleteIcon colors and add hover transition.

Replace hardcoded colors with theme variables and add a smooth transition for the hover effect.

-const DeleteIcon = styled(IconButton)(() => ({
+const DeleteIcon = styled(IconButton)(({ theme }) => ({
   cursor: "pointer",
-  color: "#fff",
+  color: theme.content.main,
+  transition: "color 0.2s ease-in-out",
   "&:hover": {
-    color: "red"
+    color: theme.danger.main
   }
 }));
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7a80757 and 20d4a34.

📒 Files selected for processing (2)
  • web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
  • web/src/services/state/index.ts (2 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx

[error] 339-364: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
web/src/services/state/index.ts (2)

4-4: LGTM: Clean type import addition

The TeamMember type import is well-placed and properly supports the type enhancement in the Workspace interface.


54-54: Type enhancement improves safety, verify usage

The change from any[] to TeamMember[] improves type safety and reduces potential runtime errors. However, as this is a breaking change, we should verify all usages of workspace.members have been updated accordingly.

Let's verify all usages of workspace.members:

✅ Verification successful

Let me try a different approach to search for usages of the members property.

This should help us find:

  1. All occurrences of "members" in TypeScript files with context
  2. The Workspace interface definition to understand the full context
  3. By analyzing the context of these results, we can determine if there are any compatibility issues with the type change

Let me try one more time with a different search strategy.

This should help us:

  1. Confirm we can find TypeScript files
  2. Find occurrences of "members" with context
  3. Find usage of the Workspace type to understand the impact

Based on the search results, I can see that the members property is extensively used throughout the codebase in the context of workspaces/teams. The type change from any[] to TeamMember[] is properly handled as:

  1. The GraphQL schema already defines members with proper typing (TeamMember type with user, userId, and role fields)
  2. All usages of workspace.members in components like Members, WorkspaceSettings, etc. expect and handle the TeamMember type
  3. The mutations (AddMemberToWorkspace, RemoveMemberFromWorkspace, etc.) all work with the properly typed TeamMember structure
  4. The state management and hooks are consistently using the TeamMember type

Type enhancement is safe and properly integrated

The change from any[] to TeamMember[] aligns with the existing codebase implementation and improves type safety without breaking existing functionality, as all consumers are already working with the TeamMember structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of workspace.members to ensure compatibility with the new type

# Search for direct member access patterns
echo "Checking direct workspace.members access:"
rg -l "workspace\.members" --type ts --type tsx

# Search for destructured member access patterns
echo -e "\nChecking destructured members access:"
rg -l "const.*\{.*members.*\}.*=.*workspace" --type ts --type tsx

Length of output: 357


Script:

#!/bin/bash
# Search for any mentions of members in TypeScript files
echo "Searching for workspace members usage:"
rg "members" --type typescript -C 2

# Search for Workspace interface usage
echo -e "\nSearching for Workspace interface usage:"
ast-grep --pattern 'interface Workspace {
  $$$
}'

Length of output: 307


Script:

#!/bin/bash
# Search for files with .ts extension first
echo "TypeScript files in the repository:"
fd ".*\.ts$"

# Then search for members usage in those files
echo -e "\nSearching for members usage:"
rg "members" -t ts -C 2

# Look for Workspace type usage
echo -e "\nSearching for Workspace type usage:"
rg "Workspace" -t ts -C 2

Length of output: 258609

Copy link

@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: 6

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 20d4a34 and 24296d6.

📒 Files selected for processing (1)
  • web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx

[error] 340-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +437 to +443
const DeleteIcon = styled(IconButton)(() => ({
cursor: "pointer",
color: "#fff",
"&:hover": {
color: "red"
}
}));
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use theme colors for DeleteIcon

The DeleteIcon uses hardcoded color values instead of theme colors.

-const DeleteIcon = styled(IconButton)(() => ({
+const DeleteIcon = styled(IconButton)(({ theme }) => ({
   cursor: "pointer",
-  color: "#fff",
+  color: theme.content.main,
   "&:hover": {
-    color: "red"
+    color: theme.danger.main
   }
}));
📝 Committable suggestion

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

Suggested change
const DeleteIcon = styled(IconButton)(() => ({
cursor: "pointer",
color: "#fff",
"&:hover": {
color: "red"
}
}));
const DeleteIcon = styled(IconButton)(({ theme }) => ({
cursor: "pointer",
color: theme.content.main,
"&:hover": {
color: theme.danger.main
}
}));

Comment on lines +273 to +282
disabled={
workspaceMembers?.some(
//existed user || no searchResult
(member) =>
memberSearchResults.find(
(memberSearchResult) =>
memberSearchResult.email === member.email
)
) || memberSearchResults.length === 0
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify disabled state logic

The disabled state logic for the Add button could be simplified and made more readable.

disabled={
-  workspaceMembers?.some(
-    (member) =>
-      memberSearchResults.find(
-        (memberSearchResult) =>
-          memberSearchResult.email === member.email
-      )
-  ) || memberSearchResults.length === 0
+  memberSearchResults.length === 0 ||
+  memberSearchResults.some(result =>
+    workspaceMembers?.some(member => member.email === result.email)
+  )
}
📝 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
disabled={
workspaceMembers?.some(
//existed user || no searchResult
(member) =>
memberSearchResults.find(
(memberSearchResult) =>
memberSearchResult.email === member.email
)
) || memberSearchResults.length === 0
}
disabled={
memberSearchResults.length === 0 ||
memberSearchResults.some(result =>
workspaceMembers?.some(member => member.email === result.email)
)
}

Comment on lines +58 to +60
if (status === "success") {
console.log("Workspace created successfully");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't need this console.log here, even when we need one we should handle it on api code.

Comment on lines +75 to +77
if (status === "success") {
console.log("Workspace updated successfully");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above

Comment on lines +92 to +94
if (status === "success") {
console.log("Workspace deleted successfully");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above

Comment on lines +144 to +157
try {
if (userId && role) {
const { status } = await useUpdateMemberOfWorkspace(
teamId,
userId,
role
);
if (status === "success") {
console.log("Member update successfully");
}
}
} catch (error) {
console.error("Failed to update member from workspace:", error);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above, i think api hooks already handled the errors and notifications, we don't need to to these again where we use the api hooks.

Copy link

@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 and nitpick comments (5)
web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx (1)

Type compatibility verified with potential issue found

The type verification reveals a potential issue with the email field access. In the User type definition, email is marked as optional (email?: string), which matches with the component's safe optional chaining usage (member.user?.email). However, there's a risk of displaying empty content when email is undefined.

  • Consider adding a fallback value or conditional rendering when member.user?.email is undefined
  • All other accessed properties are correctly defined:
    • role is a required field in TeamMember
    • user is optional in TeamMember (correctly accessed with ?.)
    • name is a required string in User type
    • email is an optional string in User type
🔗 Analysis chain

Line range hint 6-31: Verify type compatibility with TeamMember interface

The component implementation looks good, but let's verify that all accessed properties are defined in the TeamMember interface.


Let me verify the User type definition to ensure it has the required fields (name and email) that are being accessed in the component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the TeamMember interface contains all required fields
# Expected fields: user.name, user.email, role

# Search for TeamMember type definition
ast-grep --pattern 'type TeamMember = {
  $$$
}'

# Alternative: Search for TeamMember interface definition
ast-grep --pattern 'interface TeamMember {
  $$$
}'

Length of output: 504


Script:

#!/bin/bash
# Search for User type definition to verify name and email fields
ast-grep --pattern 'type User = {
  $$$
}'

# Also search for Role type/enum since it's used in TeamMember
ast-grep --pattern 'enum Role {
  $$$
}'

Length of output: 754

web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (4)

28-59: Improve type safety and readability of Props interface

Consider these improvements to the Props interface:

  1. Type the role parameter explicitly as Role enum
  2. Consider inlining the WorkspacePayload type for better readability
type Props = {
  handleAddMemberToWorkspace: ({
    teamId,
    userId,
-   role
+   role: Role,
+   name?: string
  }: WorkspacePayload) => Promise<void>;
  // ... other handlers
};

61-66: Improve MembersData type definition

The type could be more specific and clearer:

-type MembersData = {
+interface Member {
+  id: string;
+  role: Role;
+  username: string; // Make required
+  email: string; // Make required
+}
+
+type MembersData = Member[];
-}[];

161-166: Improve table accessibility

The table structure needs proper ARIA roles and labels for better accessibility.

-<Table>
+<Table role="table" aria-label={t("Workspace members")}>
-  <TableHeader>{t("User Name")}</TableHeader>
+  <TableHeader role="columnheader">{t("User Name")}</TableHeader>
-  <TableHeader>{t("Email")}</TableHeader>
+  <TableHeader role="columnheader">{t("Email")}</TableHeader>
-  <TableHeader>{t("Role")}</TableHeader>
+  <TableHeader role="columnheader">{t("Role")}</TableHeader>
-  <TableHeader />
+  <TableHeader role="columnheader" aria-label={t("Actions")} />

373-380: Add reduced motion support for animations

Consider users who prefer reduced motion for accessibility reasons.

+const reducedMotion = keyframes`
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+`;
+
 const zoomIn = keyframes`
   from {
     opacity: 0;
+    transform: scale(0.95);
   }
   to {
     opacity: 1;
+    transform: scale(1);
   }
 `;
+
+const getAnimation = () => css`
+  @media (prefers-reduced-motion: no-preference) {
+    animation: ${zoomIn} 0.2s ease-in-out;
+  }
+  @media (prefers-reduced-motion: reduce) {
+    animation: ${reducedMotion} 0.2s ease-in-out;
+  }
+`;

Then update the components using the animation:

 const TableRow = styled("div")(({ theme }) => ({
   // ...other styles
-  animation: `${zoomIn} 0.2s ease-in-out`
+  ...getAnimation()
 }));

 const UserInfo = styled.div`
   // ...other styles
-  animation: ${zoomIn} 0.2s ease-in-out;
+  ${getAnimation()};
 `;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d878fa6 and f013644.

📒 Files selected for processing (2)
  • web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx (1 hunks)
  • web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx

[error] 340-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx (2)

2-2: LGTM: Proper typing from GraphQL schema

The import of TeamMember from the GraphQL services ensures type safety and consistency with the backend schema.


Line range hint 33-62: LGTM: Well-structured styled components

The styled components are well-organized and follow good practices:

  • Proper use of theme variables
  • Semantic naming
  • Responsive grid layout
  • Appropriate handling of text overflow

Comment on lines +126 to +143
useEffect(() => {
if (
searchUser &&
"name" in searchUser &&
!memberSearchResults.find(
(memberSearchResult) => memberSearchResult.id === searchUser.id
)
) {
setMemberSearchResults([
...memberSearchResults,
{
userName: searchUser.name,
email: searchUser.email,
id: searchUser.id
}
]);
}
}, [memberSearchResults, searchUser]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential infinite loop in useEffect

The effect has memberSearchResults in its dependency array while also updating it, which could cause an infinite loop. Additionally, the search results update logic could be optimized.

 useEffect(() => {
   if (
     searchUser &&
     "name" in searchUser &&
-    !memberSearchResults.find(
+    !memberSearchResults.some(
       (memberSearchResult) => memberSearchResult.id === searchUser.id
     )
   ) {
     setMemberSearchResults((prevResults) => [
-      ...memberSearchResults,
+      ...prevResults,
       {
         userName: searchUser.name,
         email: searchUser.email,
         id: searchUser.id
       }
     ]);
   }
-}, [memberSearchResults, searchUser]);
+}, [searchUser]);
📝 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 (
searchUser &&
"name" in searchUser &&
!memberSearchResults.find(
(memberSearchResult) => memberSearchResult.id === searchUser.id
)
) {
setMemberSearchResults([
...memberSearchResults,
{
userName: searchUser.name,
email: searchUser.email,
id: searchUser.id
}
]);
}
}, [memberSearchResults, searchUser]);
useEffect(() => {
if (
searchUser &&
"name" in searchUser &&
!memberSearchResults.some(
(memberSearchResult) => memberSearchResult.id === searchUser.id
)
) {
setMemberSearchResults((prevResults) => [
...prevResults,
{
userName: searchUser.name,
email: searchUser.email,
id: searchUser.id
}
]);
}
}, [searchUser]);

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

Successfully merging this pull request may close these issues.

2 participants