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

Ba 2266 report profile #249

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Ba 2266 report profile #249

wants to merge 8 commits into from

Conversation

luciobj
Copy link
Collaborator

@luciobj luciobj commented Mar 28, 2025

✅ Social - Report Profile
Description

As a User, on the BaseApp Profile Page,I would like to View an option to report a profile from the profile page., In order to Begin the process of reporting inappropriate behavior..

Acceptance Criteria
BaseApp Profile Page

For Desktop, tablet, and mobile

Given I am on a user's profile page and there is a 3-dots menu, when I click on the 3-dots menu, then I should see an option labeled "Report Profile."

When I click on "Report Profile," then a dialog should open showing the reasons to report the profile.

The reasons should include

    Scam or Fraud

    Adult Content

    Violence, Hate or Exploitation

    Bullying or Unwanted Contact

    Other

When I select "Adult Content" as a Reason to Report, a submenu should appear displaying these additional options

    Pornography

    Child Abuse

    Prostitution

The submenu should allow me to select a specific sub-reason before proceeding to the text input step.

If I select any category without available subcategories, I should directly proceed to the text input step, as they do not have submenus currently.

Given I am in the report profile dialog, when I select a reason, then I should see a text box to elaborate on my report.

When I enter additional details in the text box and confirm the submission, then my report should be recorded in the system.

The system should save both the selected reason and the additional details as part of the report.

Given I have selected a reason and provided additional details, when I confirm the submission, then I should see a confirmation dialog summarizing my report details.

When I submit the confirmation, then I should see a success message indicating the report was submitted successfully.

Tying the report profile flow to block profile flow will be covered in a follow-up story, but keep in mind for future implementation

Backend

Backend should handle editable categories and subcategories for each

Categories can have no subcategories as well

Reports are logged on Backend

    User that submitted report 

    Profile Reported

    Date and Time of report 

Design Link: https://www.figma.com/design/XRD6wSl1m8Kz6XUcAy5CLp/BaseApp---WEB?node-id=3768-79982&node-type=section&t=7l8Nbem4bL7a0USV-0

Demo: https://www.loom.com/share/03ac73145fff4e12a513ee421d0d00b5

Summary by CodeRabbit

  • New Features

    • Introduced a new reporting interface in the profile menu, offering a guided multi-step dialog for reporting issues.
    • Enhanced blocking functionality with tailored interactions for menu versus standard button contexts.
    • Added an updated notification icon to improve visual feedback.
  • Refactor

    • Consolidated profile menu options to streamline share, block, and report actions for a more intuitive experience.
  • Documentation

    • Expanded icon documentation in Storybook for clearer design system insights.

Copy link

changeset-bot bot commented Mar 28, 2025

⚠️ No Changeset found

Latest commit: e85a6c7

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

Copy link

coderabbitai bot commented Mar 28, 2025

Walkthrough

This pull request introduces multiple new features and modifications. A new GraphQL mutation (ReportCreateMutationQuery) and related custom hook are added to create reports, alongside a query for fetching report types. The Profile components now support a multi-step reporting dialog and improved conditional rendering for block actions. Additionally, GraphQL schema updates provide enhanced report and chat room fields, while design system updates add a new icon component and Storybook documentation for icons.

Changes

File(s) Change Summary
.../graphql/mutations/ReportCreate.ts
.../graphql/queries/ReportTypeList.ts
Added new GraphQL mutation for report creation with a custom hook (useReportCreateMutation) and a query (ReportTypeListQuery) for fetching report types.
.../ProfileComponent/BlockButtonWithDialog/index.tsx
.../ProfileComponent/ReportButtonWithDialog/index.tsx
.../ProfileComponent/ReportButtonWithDialog/styled.tsx
.../ProfileComponent/ReportButtonWithDialog/types.ts
.../ProfileComponent/index.tsx
Updated block button rendering and introduced a new multi-step ReportButtonWithDialog component with associated styling and types, integrated into the profile menu.
packages/components/schema.graphql Modified GraphQL schema: removed a field from ActivityLog, updated chat room types, added delete node mutation types, and revised report-related types on Profile and Report.
.../icons/FlagIcon/index.tsx
.../icons/__storybook__/Iconography.mdx
.../icons/index.ts
Introduced a new UnreadIcon component, added Storybook documentation for icons, and updated the export index for icons.
packages/design-system/components/common/index.ts Removed a descriptive comment without changing functionality.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant RB as ReportButtonWithDialog
    participant GQ as GraphQL Server
    participant MC as useReportCreateMutation

    U->>RB: Click "Report" menu item
    RB->>RB: Open multi-step report dialog
    U->>RB: Select report type/subtype & enter details
    RB->>GQ: Fetch report types (ReportTypeListQuery)
    GQ-->>RB: Return report types
    U->>RB: Submit report details
    RB->>MC: Commit mutation (ReportCreateMutation)
    MC->>GQ: Execute mutation with provided input
    GQ-->>MC: Return success or error response
    MC-->>RB: Callback with mutation result
    alt Success
        RB->>U: Show confirmation message
    else Error
        RB->>U: Display error toast via sendToast
    end
Loading

Suggested reviewers

  • Ronan-Fernandes
  • anicioalexandre
  • deboracosilveira

Poem

I hopped through lines of code today,
With queries and mutations leading the way,
Dialogs and buttons in a rhythmic dance,
Each change a new hop, a fresh chance,
In this garden of code, I nibble with delight 🐇✨.

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/profiles/web/ProfileComponent/BlockButtonWithDialog/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)
packages/components/modules/profiles/common/graphql/mutations/ReportCreate.ts

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/profiles/web/ProfileComponent/ReportButtonWithDialog/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)
  • 7 others
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (7)
packages/design-system/components/common/icons/__storybook__/Iconography.mdx (1)

2-2: Fix import path syntax

There's a syntax issue with the import path that may cause confusion.

-import * as AllIcons from '..' 
+import * as AllIcons from '..'
🧰 Tools
🪛 LanguageTool

[typographical] ~2-~2: Two consecutive dots
Context: ...book/blocks' import * as AllIcons from '..' <Meta title="@baseapp-frontend | des...

(DOUBLE_PUNCTUATION)

packages/components/modules/profiles/web/ProfileComponent/index.tsx (1)

120-120: Ensure targetId is always defined

While there's a conditional check for profile existence, it would be safer to ensure that the targetId is always defined when passed to ReportButtonWithDialog.

-{profile && <ReportButtonWithDialog handleClose={handleClose} targetId={profile?.id} />}
+{profile && profile.id && <ReportButtonWithDialog handleClose={handleClose} targetId={profile.id} />}
packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/index.tsx (1)

74-111: Enhanced conditional rendering for menu vs. button contexts

The updated implementation provides clear visual distinction between menu item and standalone button presentations. The error color styling is consistently applied, improving user experience.

Consider refactoring the duplicated conditional logic for block/unblock states into a shared helper function to reduce repetition and improve maintainability.

+  const renderBlockContent = (isMenuItem = false) => {
+    const iconColor = isMenuItem ? 'error.main' : (isBlockedByMe ? 'inherit' : 'error.main');
+    return isBlockedByMe ? (
+      <>
+        <UnblockIcon sx={{ color: iconColor, marginRight: '5px' }} />
+        {isMenuItem ? 'Unblock profile' : 'Unblock'}
+      </>
+    ) : (
+      <>
+        <BlockIcon sx={{ color: 'error.main', marginRight: '5px' }} />
+        Block profile
+      </>
+    );
+  };

   return (
     <>
       {isMenu ? (
         <MenuItem onClick={handleOpen} disableRipple>
           <Typography variant="body2" color="error.main" noWrap>
-            {isBlockedByMe ? (
-              <>
-                <UnblockIcon sx={{ color: 'error.main', marginRight: '5px' }} />
-                Unblock profile
-              </>
-            ) : (
-              <>
-                <BlockIcon sx={{ color: 'error.main', marginRight: '5px' }} />
-                Block profile
-              </>
-            )}
+            {renderBlockContent(true)}
           </Typography>
         </MenuItem>
       ) : (
         <Button
           variant="contained"
           onClick={handleOpen}
           sx={{ justifyContent: 'center' }}
           size="medium"
         >
           <Typography variant="body2" color="inherit" noWrap>
-            {isBlockedByMe ? (
-              <>
-                <UnblockIcon sx={{ color: 'inherit', marginRight: '5px' }} />
-                Unblock
-              </>
-            ) : (
-              <>
-                <BlockIcon sx={{ color: 'error.main', marginRight: '5px' }} />
-                Block profile
-              </>
-            )}
+            {renderBlockContent()}
           </Typography>
         </Button>
       )}
packages/components/modules/profiles/web/ProfileComponent/ReportButtonWithDialog/index.tsx (2)

24-42: Consider resetting form state when dialog opens/closes

The component initializes state but doesn't reset it when the dialog is reopened, which could lead to stale data.

  const onClose = () => {
    handleClose()
    setCurrentStep('report')
+   setReportType(undefined)
+   setReportSubType(undefined)
+   setReportText('')
  }

+ const handleOpen = () => {
+   setReportType(undefined)
+   setReportSubType(undefined)
+   setReportText('')
+   setCurrentStep('report')
+   setIsReportModalOpen(true)
+ }

And update the MenuItem click handler:

-      <MenuItem onClick={() => setIsReportModalOpen(true)} disableRipple>
+      <MenuItem onClick={handleOpen} disableRipple>

74-196: Enhance the step navigation with back buttons

The multi-step dialog doesn't provide a way to go back to previous steps, forcing users to cancel and restart if they make a mistake.

Add a function to handle going back:

const handleBack = () => {
  switch (currentStep) {
    case 'subTypes':
      setCurrentStep('report')
      setReportType(undefined)
      break
    case 'reportText':
      if (reportType?.subTypes?.edges?.length) {
        setCurrentStep('subTypes')
        setReportSubType(undefined)
      } else {
        setCurrentStep('report')
        setReportType(undefined)
      }
      setReportText('')
      break
    case 'summary':
      setCurrentStep('reportText')
      break
    default:
      break
  }
}

Then add back buttons to the appropriate steps, for example in the reportText step:

        <>
          <Typography variant="h5">How would you describe the problem?</Typography>
          <Typography variant="body2">
            Use the text field below to explain what the problem you are reporting is.
          </Typography>
          <Divider />
          <TextField
            fullWidth
            multiline
            rows={4}
            value={reportText}
            onChange={(e) => setReportText(e.target.value)}
            placeholder="I find the post to be offensive..."
          />
+         <Box display="flex" justifyContent="space-between">
+           <Button onClick={handleBack}>Back</Button>
-         <Button onClick={() => setCurrentStep('summary')}>Confirm</Button>
+           <Button 
+             onClick={() => setCurrentStep('summary')} 
+             disabled={!reportText.trim()}
+           >
+             Confirm
+           </Button>
+         </Box>
        </>
packages/components/schema.graphql (1)

1657-1669: Expanded ReportsCount with detailed categories

The ReportsCount type now includes specific categories for different types of reports, which enables more detailed reporting analytics.

However, there appears to be two spelling errors:

  • Line 1665: "bulling" should be "bullying"
  • Line 1668: "prostituition" should be "prostitution"
-  bulling: Int
+  bullying: Int
-  prostituition: Int
+  prostitution: Int
packages/design-system/components/common/icons/FlagIcon/index.tsx (1)

1-36: Naming inconsistency: Component named UnreadIcon in FlagIcon directory

There's a naming mismatch between the component name (UnreadIcon) and the directory/file name (FlagIcon). This could cause confusion for other developers. Consider renaming either the component or the directory to ensure consistency.

Additionally, the icon appears to be a flag (based on the SVG paths), but is named UnreadIcon. The naming should reflect the icon's visual appearance and purpose.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 39bf260 and e85a6c7.

📒 Files selected for processing (12)
  • packages/components/modules/profiles/common/graphql/mutations/ReportCreate.ts (1 hunks)
  • packages/components/modules/profiles/common/graphql/queries/ReportTypeList.ts (1 hunks)
  • packages/components/modules/profiles/web/ProfileComponent/BlockButtonWithDialog/index.tsx (2 hunks)
  • packages/components/modules/profiles/web/ProfileComponent/ReportButtonWithDialog/index.tsx (1 hunks)
  • packages/components/modules/profiles/web/ProfileComponent/ReportButtonWithDialog/styled.tsx (1 hunks)
  • packages/components/modules/profiles/web/ProfileComponent/ReportButtonWithDialog/types.ts (1 hunks)
  • packages/components/modules/profiles/web/ProfileComponent/index.tsx (3 hunks)
  • packages/components/schema.graphql (15 hunks)
  • packages/design-system/components/common/icons/FlagIcon/index.tsx (1 hunks)
  • packages/design-system/components/common/icons/__storybook__/Iconography.mdx (1 hunks)
  • packages/design-system/components/common/icons/index.ts (1 hunks)
  • packages/design-system/components/common/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/design-system/components/common/index.ts
🧰 Additional context used
🪛 LanguageTool
packages/design-system/components/common/icons/__storybook__/Iconography.mdx

[typographical] ~2-~2: Two consecutive dots
Context: ...book/blocks' import * as AllIcons from '..' <Meta title="@baseapp-frontend | des...

(DOUBLE_PUNCTUATION)

🔇 Additional comments (18)
packages/components/modules/profiles/common/graphql/queries/ReportTypeList.ts (1)

3-27: Well-structured GraphQL query for report types

This query is well-designed, fetching both top-level report types and their sub-types with the necessary fields for building a reporting UI. The parameters are appropriate for filtering by top-level only and for specifying a target object.

packages/design-system/components/common/icons/__storybook__/Iconography.mdx (1)

8-14: Clean implementation of dynamic icon gallery

The implementation elegantly displays all icons with proper formatting of their names by inserting spaces before uppercase letters and removing the "Icon" suffix. The primary color styling provides good visual consistency.

packages/components/modules/profiles/web/ProfileComponent/index.tsx (1)

106-122: Good refactoring of menu options into a reusable fragment

The creation of a menuOptions fragment that's used in both desktop and mobile views improves code maintainability. The conditional rendering for the BlockButtonWithDialog and ReportButtonWithDialog components is a good practice.

packages/components/modules/profiles/common/graphql/mutations/ReportCreate.ts (2)

1-22: GraphQL mutation is well-structured with proper type selections

The mutation is properly defined with the required field selections for creating reports. It returns the target's reports with primary key and creation date, which provides sufficient data for confirmation.


24-49: Clean mutation hook with proper error handling

The hook implementation follows best practices by:

  1. Properly typing the return tuple
  2. Using the notification system for error handling
  3. Preserving the original config callbacks

This ensures errors are visible to the user while still allowing component-specific handling.

packages/components/modules/profiles/web/ProfileComponent/ReportButtonWithDialog/index.tsx (1)

1-23: Types are properly defined for GraphQL response data

Good use of NonNullable to ensure type safety when working with potentially nullable GraphQL response data.

packages/components/schema.graphql (10)

204-204: New field added for tracking added participants

Good addition to improve tracking of chat room updates.


328-328: Consistent field addition across types

Adding the same field to both ChatRoomOnRoomUpdate and ChatRoomUpdatePayload types maintains consistency in the API.


501-512: Well-defined generic node deletion types

The new DeleteNodeInput and DeleteNodePayload types are well-structured for generic node deletion operations.


1144-1144: Profile type now implements ReportsInterface

This change properly integrates the reporting functionality into the Profile type.


1153-1153: ReportsCount type update for Profile

The field type change from JSONString to ReportsCount provides stronger typing and better structure.


1225-1226: Added report-related fields to Profile

These fields enable querying reports associated with a profile and the current user's reports.


1616-1616: Updated Report.reportType to use new ReportType type

This change from an enum to a structured type provides more flexibility for representing report types.


1634-1634: Updated ReportCreateInput to use reportTypeId

This change aligns with the new ReportType structure, using IDs for references instead of enum values.


1680-1707: Well-structured ReportType and connection types

The new ReportType implementation includes all necessary fields and supports hierarchical report types through the parentType and subTypes fields.


1413-1417: New query fields for report types

The addition of reportTypes and allReportTypes queries provides the necessary endpoints for fetching report type data.

packages/design-system/components/common/icons/index.ts (1)

1-3: Good implementation of a barrel file for icon exports.

The 'use client' directive is appropriately placed for client-side rendering, and the export pattern makes imports cleaner throughout the application.

packages/design-system/components/common/icons/FlagIcon/index.tsx (1)

5-34: The SVG implementation follows good practices

The component correctly utilizes Material-UI's SvgIcon, properly handles props spreading, and uses currentColor for flexibility. The default styling is also well defined.

Comment on lines +4 to +14
export const TypeButton = styled(Button)(({ theme }) => ({
variant: 'text',
borderRadius: 0,
justifyContent: 'space-between',
color: theme.palette.text.primary,
backgroundColor: 'transparent',
'&:hover': {
backgroundColor: theme.palette.background.neutral,
boxShadow: 'none',
},
}))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect usage of variant property in styled component

The variant property is incorrectly placed within the styling object. In Material-UI's styled components, component props like variant should be set when using the component, not in the styling definition.

Fix the styled component by removing the variant from the styling object:

export const TypeButton = styled(Button)(({ theme }) => ({
-  variant: 'text',
  borderRadius: 0,
  justifyContent: 'space-between',
  color: theme.palette.text.primary,
  backgroundColor: 'transparent',
  '&:hover': {
    backgroundColor: theme.palette.background.neutral,
    boxShadow: 'none',
  },
}))

Then when using the component, set the variant as a prop:

<TypeButton variant="text">Button Text</TypeButton>

Comment on lines +198 to +216
return (
<>
<MenuItem onClick={() => setIsReportModalOpen(true)} disableRipple>
<Typography variant="body2" color="error.main" noWrap>
<FlagIcon sx={{ color: 'error.main', marginRight: '5px' }} />
Report profile
</Typography>
</MenuItem>
<Dialog open={isReportModalOpen} onClose={onClose}>
<Box display="flex" flexDirection="column" padding={4} gap={2}>
<Typography variant="subtitle1">
{currentStep === 'confirmation' ? 'Check Report' : 'Report'}
</Typography>
{steps?.find((step) => step.name === currentStep)?.content}
</Box>
</Dialog>
</>
)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add ARIA attributes for accessibility

The dialog is missing important accessibility attributes to ensure it's usable by all users, including those with screen readers.

      <Dialog 
        open={isReportModalOpen} 
        onClose={onClose}
+       aria-labelledby="report-dialog-title"
+       aria-describedby="report-dialog-description"
      >
        <Box display="flex" flexDirection="column" padding={4} gap={2}>
-         <Typography variant="subtitle1">
+         <Typography variant="subtitle1" id="report-dialog-title">
            {currentStep === 'confirmation' ? 'Check Report' : 'Report'}
          </Typography>
-         {steps?.find((step) => step.name === currentStep)?.content}
+         <div id="report-dialog-description">
+           {steps?.find((step) => step.name === currentStep)?.content}
+         </div>
        </Box>
      </Dialog>
📝 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
return (
<>
<MenuItem onClick={() => setIsReportModalOpen(true)} disableRipple>
<Typography variant="body2" color="error.main" noWrap>
<FlagIcon sx={{ color: 'error.main', marginRight: '5px' }} />
Report profile
</Typography>
</MenuItem>
<Dialog open={isReportModalOpen} onClose={onClose}>
<Box display="flex" flexDirection="column" padding={4} gap={2}>
<Typography variant="subtitle1">
{currentStep === 'confirmation' ? 'Check Report' : 'Report'}
</Typography>
{steps?.find((step) => step.name === currentStep)?.content}
</Box>
</Dialog>
</>
)
}
return (
<>
<MenuItem onClick={() => setIsReportModalOpen(true)} disableRipple>
<Typography variant="body2" color="error.main" noWrap>
<FlagIcon sx={{ color: 'error.main', marginRight: '5px' }} />
Report profile
</Typography>
</MenuItem>
<Dialog
open={isReportModalOpen}
onClose={onClose}
aria-labelledby="report-dialog-title"
aria-describedby="report-dialog-description"
>
<Box display="flex" flexDirection="column" padding={4} gap={2}>
<Typography variant="subtitle1" id="report-dialog-title">
{currentStep === 'confirmation' ? 'Check Report' : 'Report'}
</Typography>
<div id="report-dialog-description">
{steps?.find((step) => step.name === currentStep)?.content}
</div>
</Box>
</Dialog>
</>
)
}

Comment on lines +44 to +72
const onClose = () => {
handleClose()
setCurrentStep('report')
}

const handleReport = () => {
if (isMutationInFlight || !targetId) {
return
}
commitMutation({
variables: {
input: {
reportSubject: reportText,
reportTypeId: reportType?.id,
targetObjectId: targetId,
},
},
onCompleted: (_, errors) => {
if (!errors) {
setCurrentStep('confirmation')
return
}
onClose()
},
onError: () => {
onClose()
},
})
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for report submission

The handleReport function doesn't validate if a report type is selected or if report text is provided.

  const handleReport = () => {
-   if (isMutationInFlight || !targetId) {
+   if (isMutationInFlight || !targetId || !reportType) {
      return
    }
    commitMutation({
      variables: {
        input: {
          reportSubject: reportText,
          reportTypeId: reportType?.id,
          targetObjectId: targetId,
        },
      },
      onCompleted: (_, errors) => {
        if (!errors) {
          setCurrentStep('confirmation')
          return
        }
        onClose()
      },
      onError: () => {
        onClose()
      },
    })
  }
📝 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 onClose = () => {
handleClose()
setCurrentStep('report')
}
const handleReport = () => {
if (isMutationInFlight || !targetId) {
return
}
commitMutation({
variables: {
input: {
reportSubject: reportText,
reportTypeId: reportType?.id,
targetObjectId: targetId,
},
},
onCompleted: (_, errors) => {
if (!errors) {
setCurrentStep('confirmation')
return
}
onClose()
},
onError: () => {
onClose()
},
})
}
const onClose = () => {
handleClose()
setCurrentStep('report')
}
const handleReport = () => {
if (isMutationInFlight || !targetId || !reportType) {
return
}
commitMutation({
variables: {
input: {
reportSubject: reportText,
reportTypeId: reportType?.id,
targetObjectId: targetId,
},
},
onCompleted: (_, errors) => {
if (!errors) {
setCurrentStep('confirmation')
return
}
onClose()
},
onError: () => {
onClose()
},
})
}

Comment on lines +1 to +4
export interface ReportButtonWithDialogProps {
targetId?: string
handleClose: () => void
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Interface looks good, but should targetId be optional?

The interface is clean and well-defined. However, I'm curious about the optionality of targetId. If a report always needs a target, it might be better to make this required. Otherwise, ensure the component has logic to handle the case when targetId is undefined.


🏁 Script executed:

#!/bin/bash
# Search for usages of ReportButtonWithDialog to see how targetId is handled
rg -A 5 "ReportButtonWithDialog" --type=tsx

Length of output: 71


🏁 Script executed:

#!/bin/bash
# Re-run the search for usages of ReportButtonWithDialog specifically in .tsx files 
rg -A 5 "ReportButtonWithDialog" -g "*.tsx"

Length of output: 3130


Action: Clarify the targetId Requirement

The interface is defined as follows:

export interface ReportButtonWithDialogProps {
  targetId?: string
  handleClose: () => void
}

After verifying the usage in packages/components/modules/profiles/web/ProfileComponent/index.tsx, we see that the component is rendered conditionally—only when profile exists—and targetId is passed as profile?.id. This indicates that when the component is rendered, a target ID is always provided. To avoid any accidental misuse of ReportButtonWithDialog where a report might lack a target, it would be more robust to make targetId a required prop.

Recommendations:

  • If the button is always meant to report on an entity: Adjust the interface so that targetId is required.

    export interface ReportButtonWithDialogProps {
      targetId: string
      handleClose: () => void
    }
  • If there’s a valid use case for rendering the component without an associated target: Ensure that the component has proper logic to handle the scenario when targetId is undefined.

Please review and confirm which approach best matches the intended behavior of the reporting feature.

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.

1 participant