Skip to content

Conversation

@hpmoreira05
Copy link
Contributor

@hpmoreira05 hpmoreira05 commented Apr 4, 2025

Acceptance Criteria
Context:
The MessageRoom component, along with its subcomponents (MessagesList, MessagesGroup, MessageItem, and SendMessage), provides the core functionality for a messaging feature. These component should be added in Storybook

Acceptance Criteria:

Create Storybook Stories for:

MessageRoom

MessagesList

MessagesGroup

MessageItem

Create MDX Documentation:

Add an MDX file for each component (MessageRoom, MessagesList, MessagesGroup, MessageItem, and SendMessage).

Create a missing MDX file for SendMessage.

Follow the standard format for component documentation as outlined in https://app.tettra.co/teams/TSL/pages/frontend-documentation-guide

GraphQL Mocking with MSW:

Use MSW to mock GraphQL operations for all stories, especially where pagination or live updates are involved.

Mocking Examples:

https://github.com/silverlogic/baseapp-frontend/blob/master/packages/components/modules/comments/CommentsList/__storybook__/mockResolvers.ts

https://github.com/silverlogic/baseapp-frontend/blob/master/packages/components/modules/comments/Comments/__tests__/__mocks__/requests.ts

Approvd
https://app.approvd.io/projects/BA/stories/36579

Summary by CodeRabbit

  • New Features
    • Introduced enhanced chat interface components that dynamically display chat rooms, grouped messages, and individual chat messages across various states, including scenarios for group, private, and system messages.
  • Documentation
    • Expanded interactive Storybook examples and guidelines for key chat components, offering comprehensive overviews and usage scenarios to facilitate a clearer and more engaging chat experience.

@changeset-bot
Copy link

changeset-bot bot commented Apr 4, 2025

⚠️ No Changeset found

Latest commit: c86619a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Apr 4, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request adds comprehensive Storybook documentation and new Relay-powered components within the messaging module. It introduces components for rendering chat rooms, message items, message groups, and message lists that fetch data via GraphQL. Alongside these components, mock resolvers and a broad set of Storybook stories have been introduced to simulate various chat scenarios and UI states. The documentation files provide details on use cases, props, and behavior for each component.

Changes

File(s) Change Summary
packages/.../ChatRoom/__storybook__/ChatRoom.mdx
packages/.../ChatRoom/__storybook__/ChatRoomWithQuery/index.tsx
packages/.../ChatRoom/__storybook__/mockResolvers.ts
packages/.../ChatRoom/__storybook__/stories.tsx
Introduces ChatRoom documentation, a Relay-based ChatRoomWithQuery component, its mock resolvers, and Storybook stories for various chat scenarios.
packages/.../MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItem.mdx
packages/.../MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItemWithQuery/index.tsx
packages/.../MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/mockResolvers.ts
packages/.../MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx
Adds MessageItem documentation, a Relay-powered MessageItemWithQuery component, corresponding mock resolvers, and stories showcasing different message states.
packages/.../MessagesList/MessagesGroup/__storybook__/MessagesGroup.mdx
packages/.../MessagesList/MessagesGroup/__storybook__/MessagesGroupWithQuery/index.tsx
packages/.../MessagesList/MessagesGroup/__storybook__/mockResolvers.ts
packages/.../MessagesList/MessagesGroup/__storybook__/stories.tsx
Provides documentation and a Relay-based MessagesGroupWithQuery component along with its mock data and Storybook stories, detailing grouped message rendering.
packages/.../MessagesList/__storybook__/MessageList.mdx
packages/.../MessagesList/__storybook__/MessageListWithQuery/index.tsx
packages/.../MessagesList/__storybook__/mockResolvers.ts
packages/.../MessagesList/__storybook__/stories.tsx
Introduces documentation for the MessagesList component, a Relay-powered MessageListWithQuery component, mock resolvers to simulate chat room messages, and Storybook stories to test infinite scrolling and grouping.
packages/components/CHANGELOG.md Adds patch version 1.0.35 entry documenting the addition of Storybook stories for MessageList, MessageItem, ChatRoom, and MessagesGroup components.
packages/components/package.json Updates package version from 1.0.34 to 1.0.35 without other changes.

Sequence Diagram(s)

sequenceDiagram
    participant SB as Storybook
    participant CRQ as ChatRoomWithQuery
    participant RL as Relay Query
    participant SC as SuspendedChatRoom
    SB->>CRQ: Render ChatRoomWithQuery
    CRQ->>RL: Execute GraphQL Query ("room-123")
    RL-->>CRQ: Return chat room data
    alt Data missing
        CRQ->>SB: Display "Room not found" message
    else Data present
        CRQ->>SC: Render SuspendedChatRoom with room data
    end
Loading
sequenceDiagram
    participant SB as Storybook
    participant MLQ as MessageListWithQuery
    participant RL as Relay Query
    participant ML as MessagesList
    SB->>MLQ: Render MessageListWithQuery
    MLQ->>RL: Execute GraphQL Query ("room-123")
    RL-->>MLQ: Return chat room data (MessagesListFragment)
    MLQ->>ML: Render MessagesList with roomRef prop
Loading

Possibly related PRs

  • BA-2190-fe-storybook-messages #252: Adds Storybook documentation, stories, mock resolvers, and query-based components for the ChatRoom and related messaging subcomponents, closely related in scope and implementation.
  • BA-1904 Display Chat Header #148: Implements the ChatRoomHeader component integrated into ChatRoom, which is referenced in the current PR’s documentation and stories.

Suggested labels

approved

Suggested reviewers

  • Hercilio1
  • priscilladeroode
  • anicioalexandre
  • deboracosilveira

Poem

I'm just a rabbit, hopping in code delight,
New stories and queries make my heart so light.
Carrots of data fetched on a Relay trail,
Mocks and stories ensure no detail goes stale.
In this garden of changes, every hop feels right!
🐇💻

Warning

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

🔧 ESLint

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

packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: Cannot read config file: /packages/components/.eslintrc.js
Error: Cannot find module '@baseapp-frontend/config/.eslintrc-with-restricted-paths.js'
Require stack:

  • /packages/components/.eslintrc.js
  • /node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/cli-engine/cli-engine.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/eslint/eslint.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/eslint/index.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/cli.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/bin/eslint.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Module._load (node:internal/modules/cjs/loader:1074:27)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:217:24)
    at Module.require (node:internal/modules/cjs/loader:1339:12)
    at require (node:internal/modules/helpers:135:16)
    at Object. (/packages/components/.eslintrc.js:1:18)
    at Module._compile (node:internal/modules/cjs/loader:1546:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1691:10)
    at Module.load (node:internal/modules/cjs/loader:1317:32)
packages/components/modules/messages/web/MessagesList/__storybook__/stories.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: Cannot read config file: /packages/components/.eslintrc.js
Error: Cannot find module '@baseapp-frontend/config/.eslintrc-with-restricted-paths.js'
Require stack:

  • /packages/components/.eslintrc.js
  • /node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/cli-engine/cli-engine.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/eslint/eslint.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/eslint/index.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/cli.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/bin/eslint.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Module._load (node:internal/modules/cjs/loader:1074:27)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:217:24)
    at Module.require (node:internal/modules/cjs/loader:1339:12)
    at require (node:internal/modules/helpers:135:16)
    at Object. (/packages/components/.eslintrc.js:1:18)
    at Module._compile (node:internal/modules/cjs/loader:1546:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1691:10)
    at Module.load (node:internal/modules/cjs/loader:1317:32)
packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroupWithQuery/index.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

Error: Cannot read config file: /packages/components/.eslintrc.js
Error: Cannot find module '@baseapp-frontend/config/.eslintrc-with-restricted-paths.js'
Require stack:

  • /packages/components/.eslintrc.js
  • /node_modules/.pnpm/@eslint+eslintrc@2.1.4/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/cli-engine/cli-engine.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/eslint/eslint.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/eslint/index.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/lib/cli.js
  • /node_modules/.pnpm/eslint@8.57.1/node_modules/eslint/bin/eslint.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Module._load (node:internal/modules/cjs/loader:1074:27)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:217:24)
    at Module.require (node:internal/modules/cjs/loader:1339:12)
    at require (node:internal/modules/helpers:135:16)
    at Object. (/packages/components/.eslintrc.js:1:18)
    at Module._compile (node:internal/modules/cjs/loader:1546:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1691:10)
    at Module.load (node:internal/modules/cjs/loader:1317:32)

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5426cfb and c86619a.

📒 Files selected for processing (5)
  • packages/components/CHANGELOG.md (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroupWithQuery/index.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/__storybook__/stories.tsx (1 hunks)
  • packages/components/package.json (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

@hpmoreira05 hpmoreira05 requested a review from Hercilio1 April 4, 2025 12:45
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

🧹 Nitpick comments (19)
packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/mockResolvers.ts (1)

1-22: Consider enhancing the mock data for comprehensive testing

The mock resolver provides a good starting point for testing the Message component in Storybook. To improve test coverage, consider:

  1. Providing a default image URL instead of an empty string on line 17, which could cause UI issues if components don't handle empty images gracefully
  2. Using a fixed date string for the created field instead of new Date().toISOString() to ensure deterministic testing results
  3. Creating additional mock messages with different states (e.g., deleted messages, read messages) to test various component states
export const mockResolvers = {
  Node: () => ({
    __typename: 'Message',
    id: 'msg-1',
    content: 'Hello',
-   created: new Date().toISOString(),
+   created: '2023-05-15T10:30:00.000Z',
    deleted: false,
    extraData: null,
    inReplyTo: null,
    isRead: false,
    pk: 1,
    verb: 'SENT_MESSAGE',
    profile: {
      id: 'profile-123',
      name: 'Você',
      image: {
-       url: '',
+       url: 'https://via.placeholder.com/48',
      },
    },
    messageType: 'USER_MESSAGE',
  }),
}
packages/components/modules/messages/web/MessagesList/__storybook__/MessageListWithQuery/index.tsx (2)

7-20: Handle loading and error states for a complete Storybook demonstration

The component currently doesn't handle loading or error states from useLazyLoadQuery. For a more comprehensive Storybook demonstration, consider adding these states to show how the component behaves during data fetching and error conditions.

const MessageListWithQuery = () => {
+  const [variables] = useState({});
  const data = useLazyLoadQuery<Query>(
    graphql`
      query MessageListWithQuery @relay_test_operation {
        chatRoom(id: "room-123") {
          ...MessagesListFragment
        }
      }
    `,
-    {},
+    variables,
+    {
+      fetchPolicy: 'store-or-network',
+    }
  )

+  if (!data.chatRoom) {
+    return <div>Chat room not found</div>
+  }

  return <MessagesList roomRef={data.chatRoom as MessagesListFragment$key} />
}

19-19: Avoid type casting when possible

The type cast data.chatRoom as MessagesListFragment$key suggests a type mismatch. Instead of using type assertion, consider ensuring proper type alignment in the GraphQL query or properly typing the component.

- return <MessagesList roomRef={data.chatRoom as MessagesListFragment$key} />
+ return data.chatRoom ? <MessagesList roomRef={data.chatRoom} /> : null
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItemWithQuery/index.tsx (2)

13-27: Handle loading and error states for a complete Storybook demonstration

Similar to the MessageListWithQuery component, this component doesn't handle loading or error states from useLazyLoadQuery. For a more comprehensive Storybook demonstration, consider adding these states.

const MessageItemWithQuery = ({ isGroup = false, isFirstGroupedMessage = true }: Props) => {
+  const [isLoading, setIsLoading] = useState(false);
  const data = useLazyLoadQuery<Query>(
    graphql`
      query MessageItemWithQuery @relay_test_operation {
        node(id: "msg-1") {
          ... on Message {
            ...MessageItemFragment
            profile {
              id
            }
          }
        }
      }
    `,
    {},
+    {
+      fetchPolicy: 'store-or-network',
+      onComplete: () => setIsLoading(false),
+    }
  )

+  if (isLoading) {
+    return <div>Loading message...</div>
+  }
+
+  if (!data.node) {
+    return <div>Message not found</div>
+  }

31-31: Avoid type casting when possible

The type cast data.node as MessageItemFragment$key suggests a type mismatch. Consider ensuring proper type alignment in the GraphQL query.

- messageRef={data.node as MessageItemFragment$key}
+ messageRef={data.node}
packages/components/modules/messages/web/ChatRoom/__storybook__/ChatRoomWithQuery/index.tsx (3)

7-32: Well-implemented but consider parameterizing the room ID.

The component properly fetches and renders the chat room data. However, the room ID "room-123" is hardcoded, which works for Storybook but limits flexibility. Consider accepting roomId as a prop to make this component more reusable across different stories.

-const ChatRoomWithQuery = () => {
+const ChatRoomWithQuery = ({ roomId = "room-123" }) => {
  const data = useLazyLoadQuery<Query>(
    graphql`
      query ChatRoomWithQuery @relay_test_operation {
-        chatRoom(id: "room-123") {
+        chatRoom(id: $roomId) {
          id
          isArchived
          participantsCount
          ...TitleFragment
          ...MessagesListFragment
        }
      }
    `,
-    {},
+    { roomId },
  )

23-23: Add a more descriptive error message.

The current "Room not found" message is functional but could be more informative to help with debugging during development.

-  if (!data.chatRoom) return <div>Room not found</div>
+  if (!data.chatRoom) return <div>Chat room with ID "room-123" not found</div>

28-29: Consider extracting the alert to a configurable callback.

Using an inline alert for the onDisplayGroupDetailsClicked handler works for demonstration purposes, but consider making this configurable to allow for more sophisticated behavior in stories.

-      onDisplayGroupDetailsClicked={() => alert('Group details clicked')}
+      onDisplayGroupDetailsClicked={props?.onDisplayGroupDetailsClicked || (() => alert('Group details clicked'))}
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItem.mdx (2)

19-21: Add TypeScript interface reference for messageRef prop.

The messageRef prop is documented as MessageFragment, but it would be helpful to add a reference to the actual TypeScript interface or type definition to make it easier for developers to understand the expected structure.

- **messageRef** (`MessageFragment`): A Relay fragment reference containing the message data.
+ **messageRef** (`MessageFragment$key`): A Relay fragment reference containing the message data. See `MessageFragment.graphql.ts` for the complete type definition.

31-37: Example usage could be enhanced with more context.

The provided example is good, but could be enhanced to show how to obtain the messageRef from a parent component or query.

```tsx
-const MyComponent = () => {
+import { useLazyLoadQuery, graphql } from 'react-relay';
+import { MyComponentQuery } from './__generated__/MyComponentQuery.graphql';
+
+const MyComponent = () => {
+  const data = useLazyLoadQuery<MyComponentQuery>(
+    graphql`
+      query MyComponentQuery {
+        message(id: "msg-123") {
+          ...MessageFragment
+        }
+      }
+    `,
+    {}
+  );
+  
+  if (!data.message) return null;
+  
-  return <MessageItem messageRef={message} isGroup={true} isFirstGroupedMessage={true} />
+  return <MessageItem messageRef={data.message} isGroup={true} isFirstGroupedMessage={true} />
}

export default MyComponent

</blockquote></details>
<details>
<summary>packages/components/modules/messages/web/MessagesList/__storybook__/mockResolvers.ts (1)</summary><blockquote>

`14-29`: **Use varying timestamps for a more realistic message history.**

All messages currently have the same creation timestamp (`new Date().toISOString()`), which doesn't reflect a real conversation flow. Consider using staggered timestamps to show a more realistic message history.

```diff
- created: new Date().toISOString(),
+ created: new Date(Date.now() - 5 * 60000).toISOString(), // 5 minutes ago

- created: new Date().toISOString(),
+ created: new Date(Date.now() - 10 * 60000).toISOString(), // 10 minutes ago

- created: new Date().toISOString(),
+ created: new Date(Date.now() - 15 * 60000).toISOString(), // 15 minutes ago

Also applies to: 34-49, 54-69

packages/components/modules/messages/web/MessagesList/__storybook__/stories.tsx (1)

34-48: Consider adding additional story variants.

The default story is well configured, but consider adding more variants to showcase different states of the MessageList component (e.g., empty state, loading state, error state).

export const EmptyList: Story = {
  name: 'Empty Message List',
  parameters: {
    mockResolvers: {
      ChatRoom: () => ({
        id: 'room-123',
        isGroup: true,
        unreadMessages: { count: 0, markedUnread: false },
        allMessages: { totalCount: 0, edges: [], pageInfo: { hasNextPage: false, endCursor: null } },
      }),
    },
    initialProfile: {
      id: 'profile-123',
      name: 'Profile Name',
      image: '',
      urlPath: 'profile',
    },
    chatRoom: { id: 'room-123' },
  },
}
packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroupWithQuery/index.tsx (2)

1-32: GraphQL query implementation looks good, but consider error handling

The GraphQL query is properly implemented with useLazyLoadQuery, retrieving the necessary data for the MessagesGroup component. The query correctly fetches all required fields.

Consider adding error handling for the query result, as the component currently assumes that data.node will always be available and of the expected type. You could implement a simple conditional check or use Suspense/ErrorBoundary.

- const data = useLazyLoadQuery<Query>(
+ const data = useLazyLoadQuery<Query>(
    graphql`
      query MessagesGroupWithQuery @relay_test_operation {
        node(id: "msg-1") {
          __typename
          ... on Message {
            id
            messageType
            created
            profile {
              id
              name
              image(width: 32, height: 32) {
                url
              }
            }
            isRead
            ...MessageItemFragment
          }
        }
      }
    `,
    {},
+   { fetchPolicy: 'store-or-network' }
  )
+ 
+ if (!data.node) {
+   return <div>Message not found</div>
+ }

33-47: Message array construction is functional but could be more robust

The allMessages array is constructed with a hardcoded message and the fetched message. This works for demonstration purposes.

Consider adding type safety to ensure the data.node is treated as a Message type:

  const allMessages = [
    {
-     ...data.node,
+     ...(data.node as NonNullable<typeof data.node>),
      id: 'msg-0',
      messageType: MESSAGE_TYPE.user,
      created: new Date().toISOString(),
      profile: {
        id: 'profile-456',
        name: 'Alice',
        image: { url: '' },
      },
      isRead: true,
    },
-   data.node,
+   data.node as NonNullable<typeof data.node>,
  ]
packages/components/modules/messages/web/ChatRoom/__storybook__/mockResolvers.ts (2)

45-49: Fix inconsistent ID format in mock data

The message ID TWVzc2FnZToxOQ==DKS on line 45 appears to have an inconsistent format compared to other IDs in the mock data (which use a standard base64 format without the DKS suffix).

-            id: 'TWVzc2FnZToxOQ==DKS',
+            id: 'TWVzc2FnZToxOQ==',

1-265: Consider using realistic dates in mock data

All the message dates in the mock resolvers are set in 2025, which is in the future. While this doesn't affect functionality, using past or present dates would make the mock data more realistic and intuitive for developers working with the stories.

packages/components/modules/messages/web/ChatRoom/__storybook__/ChatRoom.mdx (1)

26-32: Consider adding links to related components

The "Related Components" section mentions other components but doesn't provide links to their documentation. Consider adding links to enhance navigation between related component docs.

- **Related Components**:
-  - `MessagesList` – Renders the message timeline inside the chat.
-  - `SendMessage` – Handles input and sending of messages.
-  - `ChatRoomHeader` – Displays chat participants, title, and group options.
+ **Related Components**:
+  - [`MessagesList`](?path=/docs/baseapp-frontend-components-messages-messageslist--docs) – Renders the message timeline inside the chat.
+  - [`SendMessage`](?path=/docs/baseapp-frontend-components-messages-sendmessage--docs) – Handles input and sending of messages.
+  - [`ChatRoomHeader`](?path=/docs/baseapp-frontend-components-messages-chatroomheader--docs) – Displays chat participants, title, and group options.
packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/stories.tsx (1)

11-11: Consider using theme variables for styling

Instead of hardcoding the background color with rgba values, consider using theme variables for better maintainability and consistency with the design system.

-      <div style={{ padding: 20, background: 'rgba(145, 158, 171, 0.12)' }}>
+      <div style={{ padding: 20, background: 'var(--color-background-secondary)' }}>

If your design system doesn't have appropriate variables, consider creating them or using more semantic names in a constant.

packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx (1)

11-11: Consider using theme variables for styling

Similar to the MessagesGroup stories, consider using theme variables for the background color instead of hardcoded rgba values to improve maintainability.

-      <div style={{ padding: 20, background: 'rgba(145, 158, 171, 0.12)' }}>
+      <div style={{ padding: 20, background: 'var(--color-background-secondary)' }}>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between cffe402 and 5426cfb.

📒 Files selected for processing (16)
  • packages/components/modules/messages/web/ChatRoom/__storybook__/ChatRoom.mdx (1 hunks)
  • packages/components/modules/messages/web/ChatRoom/__storybook__/ChatRoomWithQuery/index.tsx (1 hunks)
  • packages/components/modules/messages/web/ChatRoom/__storybook__/mockResolvers.ts (1 hunks)
  • packages/components/modules/messages/web/ChatRoom/__storybook__/stories.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItem.mdx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItemWithQuery/index.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/mockResolvers.ts (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroup.mdx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroupWithQuery/index.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/mockResolvers.ts (1 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/stories.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/__storybook__/MessageList.mdx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/__storybook__/MessageListWithQuery/index.tsx (1 hunks)
  • packages/components/modules/messages/web/MessagesList/__storybook__/mockResolvers.ts (1 hunks)
  • packages/components/modules/messages/web/MessagesList/__storybook__/stories.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (3)
packages/components/modules/messages/web/MessagesList/__storybook__/stories.tsx (2)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx (1)
  • Default (22-27)
packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/stories.tsx (1)
  • Default (22-31)
packages/components/modules/messages/web/MessagesList/__storybook__/mockResolvers.ts (2)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/mockResolvers.ts (1)
  • mockResolvers (1-15)
packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/mockResolvers.ts (1)
  • mockResolvers (1-22)
packages/components/modules/messages/web/ChatRoom/__storybook__/stories.tsx (1)
packages/components/modules/messages/web/ChatRoom/__storybook__/mockResolvers.ts (2)
  • mockResolverGroup (1-130)
  • mockResolverPrivate (132-265)
🔇 Additional comments (17)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItemWithQuery/index.tsx (1)

7-10: Good use of props for flexible Storybook stories

The component properly accepts props for controlling its behavior (isGroup and isFirstGroupedMessage), which enhances its flexibility for use in different Storybook stories.

packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/MessageItem.mdx (1)

1-38: Well-structured documentation!

The documentation is comprehensive, covering purpose, behavior, use cases, props, and providing an example. It effectively explains the component's role in the messaging system.

packages/components/modules/messages/web/MessagesList/__storybook__/stories.tsx (3)

10-14: Good use of Zustand for state management.

The mock store implementation is clean and appropriate for Storybook's context.


19-27: Well-structured decorator setup.

The decorator properly provides the ChatRoomContext and applies appropriate styling for the story visualization.


1-49: Implement MSW for GraphQL operations as per PR requirements.

The PR acceptance criteria specifically mentioned using Mock Service Worker (MSW) to simulate GraphQL operations. While the current implementation with mockResolvers works, consider enhancing it to use MSW for better alignment with the requirements.

import { graphql } from 'msw'

// Define MSW handlers for GraphQL operations
const handlers = [
  graphql.query('ChatRoomWithQuery', (req, res, ctx) => {
    return res(
      ctx.data({
        chatRoom: {
          id: 'room-123',
          // Include other chat room data here
        }
      })
    )
  }),
  // Add other handlers as needed
]

// Add MSW parameters to the story
export const Default: Story = {
  // Existing parameters...
  parameters: {
    // Existing parameters...
    msw: {
      handlers,
    },
  },
}

Could you verify if your team has already set up MSW for Storybook in the project? This implementation assumes MSW is configured properly in the Storybook environment.

packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroup.mdx (1)

1-56: Well-structured MessagesGroup documentation that follows project standards

The documentation provides comprehensive information about the MessagesGroup component, including its purpose, expected behavior, use cases, props, and example usage. The documentation is clear and follows the format outlined in the PR objectives.

packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/MessagesGroupWithQuery/index.tsx (1)

49-61: Component rendering looks good

The MessagesGroup component is properly rendered with all the necessary props from the queried data.

packages/components/modules/messages/web/MessagesList/__storybook__/MessageList.mdx (1)

1-41: Well-structured MessageList documentation

The documentation provides clear and concise information about the MessagesList component, including its purpose, behavior, use cases, props, related components, and example usage. The documentation follows the project standards.

packages/components/modules/messages/web/ChatRoom/__storybook__/stories.tsx (4)

1-7: Good import structure and organization

All necessary imports for the ChatRoom stories are properly organized, including providers and mock resolvers.


8-27: Well-structured Storybook meta configuration

The meta configuration follows Storybook best practices with appropriate decorators that wrap the component with necessary providers and styling.


28-38: Group chat story implementation with MSW mock resolvers

The GroupChat story is well-configured with appropriate mock resolvers for a group chat scenario, fulfilling the PR requirement to use Mock Service Worker for GraphQL operations.


40-50: Private chat story implementation with MSW mock resolvers

The PrivateChat story is well-configured with appropriate mock resolvers for a private chat scenario, meeting the PR requirement for using MSW to simulate GraphQL operations.

packages/components/modules/messages/web/ChatRoom/__storybook__/mockResolvers.ts (1)

1-265: Good job creating comprehensive mock resolvers

The mock resolvers are well-structured and provide realistic data for both group and private chat scenarios. They include various message types, user profiles, and interaction states which will be valuable for testing component behavior in Storybook.

packages/components/modules/messages/web/ChatRoom/__storybook__/ChatRoom.mdx (1)

1-47: Well-structured component documentation

The documentation is comprehensive and follows best practices. It clearly explains the component's purpose, expected behavior, use cases, props, and provides a practical usage example.

packages/components/modules/messages/web/MessagesList/MessagesGroup/__storybook__/stories.tsx (1)

1-68: Good coverage of different message scenarios

The stories effectively demonstrate the different states of the MessagesGroup component, covering own messages, messages from other users, and system-generated messages.

packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/__storybook__/stories.tsx (2)

1-119: Comprehensive coverage of message states

The stories provide excellent coverage of different message states including regular messages, deleted messages, grouped messages, and own messages. This will be very helpful for testing and documentation.


71-77:

❓ Verification inconclusive

Ensure initialProfile matches the profile in mock data

For consistency, make sure the initialProfile IDs in the story parameters match the message profile IDs in your mock resolvers when testing "own message" scenarios. This will help ensure the component correctly identifies messages from the current user.


🏁 Script executed:

#!/bin/bash
# Check if initialProfile IDs in stories match profile IDs in mock resolvers
rg -A 5 "initialProfile" packages/components/modules/messages/web/MessagesList
echo "---"
rg -A 5 "profile: {" packages/components/modules/messages/web/MessagesList

Length of output: 4669


ACTION: Verify that the profile IDs in your mock resolvers match the initialProfile values in your story files.

The shell script confirmed that all story files in the MessagesList package define an initialProfile with id: 'profile-123'. However, our attempt to locate corresponding mock resolver definitions using the pattern profile: { encountered a regex error, so we couldn’t auto-verify that the resolver data uses the same ID.

Please ensure that for "own message" scenarios, the mock resolvers indeed use id: 'profile-123' so the component correctly identifies messages from the current user. A manual check or an adjusted search with correct escaping (e.g., using a fixed string search for "profile: {") is recommended.

@anicioalexandre anicioalexandre requested a review from Copilot April 10, 2025 15:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 12 out of 16 changed files in this pull request and generated 1 comment.

Files not reviewed (4)
  • packages/components/modules/messages/web/ChatRoom/storybook/ChatRoom.mdx: Language not supported
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/MessageItem/storybook/MessageItem.mdx: Language not supported
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/storybook/MessagesGroup.mdx: Language not supported
  • packages/components/modules/messages/web/MessagesList/storybook/MessageList.mdx: Language not supported
Comments suppressed due to low confidence (1)

packages/components/modules/messages/web/MessagesList/MessagesGroup/storybook/MessagesGroupWithQuery/index.tsx:33

  • [nitpick] Consider ensuring that the combined allMessages array is sorted by creation time, as merging queried data with manually created message objects may lead to inconsistent ordering in the UI.
const allMessages = [

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
14.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@hpmoreira05 hpmoreira05 merged commit 25921df into master Apr 15, 2025
6 of 7 checks passed
@nossila nossila deleted the BA-2190-fe-storybook-messages branch May 26, 2025 21:14
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