Skip to content

Conversation

@mathieubouhelier
Copy link
Contributor

@mathieubouhelier mathieubouhelier commented Oct 28, 2025

Acceptance Criteria

As a User, on the web app,I would like to have the ability to delete my account directly from the app, In order to maintain control over my personal data.

Description

Add an option for users to delete their account

Place the "Delete Account" option under the Settings or Profile

Include a confirmation step before deletion is executed to prevent accidental removal

Display a clear message explaining that deletion is permanent and what data will be affected

We normally don't permanently delete accounts, we rather inactivate them however to comply with Apple's guidelines this story needs to enable the permanent account deletion when Users opt for it

Upon confirmation, trigger backend process to delete or anonymize user data

Update frontend to reflect account removal (e.g., navigate to Sign In screen after deletion)

Ensure deletion logs are properly captured for audit purposes

Acceptance Criteria

Given the user is logged in and navigates to the Settings/Profile, when they select “Delete Account,” then they should see a confirmation screen explaining the consequences

Given the user confirms deletion, when the deletion process completes, then the user account and related data are permanently deleted or anonymized according to policy

Given the deletion is completed, when the user tries to access the app again, then they should be redirected to the Sign In screen and be unable to log in with the deleted credentials

Given the feature is reviewed by App Store, when account deletion is checked, then the option is visible and functional within the app

Validation Rules

User must confirm deletion before it is processed

Deleted account credentials must not allow login

Deleted user ID must be removed from active user lists in backend

Business Rules
Comply with App Store policy that requires in-app account deletion if account creation is supported

Notes

Removed from the story
Ensure data deletion meets privacy regulations (e.g., GDPR or CCPA)

Summary by CodeRabbit

  • New Features

    • Added visual indicator for deleted user avatars across activity logs, messages, and comments components.
    • Added ability to disable comment reply button based on user and comment status.
  • Design System Updates

    • New deleted user avatar icon added for consistent presentation of deleted accounts.

@changeset-bot
Copy link

changeset-bot bot commented Oct 28, 2025

⚠️ No Changeset found

Latest commit: ca39ccd

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 Oct 28, 2025

Walkthrough

The changes implement visual representation for deleted users across multiple components by introducing a new AvatarDeletedUserIcon component, updating avatar wrappers to conditionally display this icon when user profiles are null or undefined, and adding controls to disable the comment reply button when appropriate. Activity logs, messages, and comments now handle deleted user scenarios consistently.

Changes

Cohort / File(s) Summary
New Icon Component and Export
packages/design-system/components/web/icons/AvatarDeletedUserIcon/index.tsx, packages/design-system/components/web/icons/index.ts
Introduces AvatarDeletedUserIcon component—a 40px MUI SvgIcon with action.active color and inline SVG paths. Exports added to icon barrel file.
Avatar Components Updated for Deleted Users
packages/design-system/components/web/avatars/AvatarWithPlaceholder/index.tsx, packages/design-system/components/web/avatars/AvatarWithPlaceholder/types.ts, packages/design-system/components/web/avatars/ClickableAvatar/index.tsx
Added showDeletedUser?: boolean prop to AvatarWithPlaceholder; renders AvatarDeletedUserIcon when true and no children provided. ClickableAvatar replaces fallback icon with AvatarDeletedUserIcon when deletedUser is true.
Activity Log Component
packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx
Reordered component props (logGroups moved after LoadingState). Added renderAvatar() helper that returns AvatarDeletedUserIcon when user is null, otherwise returns Avatar with user data.
Messages Component
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx
Added isProfileNullOrUndefined check and refined isFirstMessageAtTheTop logic. Updated canShowAvatar to factor in deleted-user status. Passes showDeletedUser={isProfileNullOrUndefined} to AvatarWithPlaceholder and displays "Deleted User" as name when profile is null/undefined.
Comments Components
packages/components/modules/comments/web/CommentItem/CommentReplyButton/index.tsx, packages/components/modules/comments/web/CommentItem/CommentReplyButton/types.ts, packages/components/modules/comments/web/CommentItem/index.tsx
Added isDisabled?: boolean prop to CommentReplyButton (defaults to false). In CommentItem, button is disabled when no user exists and totalCommentsCount is 0.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Design-system icon creation: Verify SVG paths render correctly and styling matches expected appearance
  • Deleted user detection logic in UserMessage: Ensure null/undefined profile checks handle all edge cases and message grouping logic remains intact
  • CommentReplyButton disable state: Confirm the disable condition (no user + zero comment count) aligns with intended behavior
  • Prop order change in LogGroups: Verify no consumers depend on positional arguments (likely safe with destructuring)

Possibly related PRs

Suggested labels

needs changes

Suggested reviewers

  • priscilladeroode
  • deboracosilveira
  • anicioalexandre
  • luciobj
  • nossila

Poem

🐰 A ghostly user icon joins the fray,
Through avatars and logs, deleted ones display,
With buttons disabled when needed most,
The UI now honors the vanished host! 👻

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The pull request title '[FE - package] Account Deletion - Android & WebApp' is misleading and does not accurately represent the actual changes in the codebase. The PR summary indicates this should implement account deletion functionality with UI, confirmation screens, and backend integration, but the raw summary shows only icon component changes, avatar rendering updates, and a disabled button prop—no account deletion features are present. The title describes features not implemented in the changeset. Update the PR title to accurately reflect the actual changes, such as '[FE - package] Add AvatarDeletedUserIcon and update avatar/button components for deleted users' or similar, to truthfully represent the refactoring of avatar handling for deleted user states rather than implying full account deletion feature implementation.
Description check ⚠️ Warning The pull request description does not follow the repository's template structure and is largely incomplete. The template requires a package name and version format (e.g., '- __package_name__ package update - v __package_version__' with changelog items), but the provided description contains acceptance criteria and business requirements instead. Additionally, the description claims to implement full account deletion functionality (settings UI, confirmation flows, backend deletion, navigation), which does not match the actual code changes that are limited to component and icon updates for deleted user display states. Rewrite the description to follow the repository template format with package name, version, and concise changelog items that accurately reflect the actual changes: icon exports, avatar component updates with showDeletedUser prop, and CommentReplyButton enhancements. Alternatively, clarify that this PR is a preparatory step and attach it to a larger feature branch that implements the full account deletion flow described in the acceptance criteria.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/delete-account/BA-2686-FE-package-Account-Deletion-Android-WebApp

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🧹 Nitpick comments (1)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (1)

24-24: Simplify null/undefined check.

The check == null || === undefined is redundant. The loose equality operator == null already matches both null and undefined.

Apply this diff:

-  const isProfileNullOrUndefined = message?.profile == null || message?.profile === undefined
+  const isProfileNullOrUndefined = message?.profile == null
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 171f751 and 4fd1bd4.

📒 Files selected for processing (2)
  • packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (4 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (1)
packages/components/modules/activity-log/common/types.ts (1)
  • LogGroup (7-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Component Test Packages
  • GitHub Check: Build and Lint Packages
🔇 Additional comments (5)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (3)

52-58: Verify the isRead === null condition for top message detection.

The logic assumes previousMessage?.isRead === null indicates the first message at the top. Ensure this assumption holds across all message states and that isRead being null is exclusively used as a boundary marker and won't occur in other contexts (e.g., unread messages where isRead might be false instead).


66-67: Avatar visibility logic refined for deleted users.

The updated logic now requires isFirstGroupedMessage to be true for deleted users to show their avatar, which is more consistent with message grouping behavior. This prevents avatars from appearing on every message from a deleted user within the same group.


95-99: Proper handling of deleted user names.

The fallback to "Deleted User" when profile is null/undefined correctly addresses the account deletion requirement.

packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (2)

3-3: Clean import addition for deleted user avatar handling.

The AvatarWithPlaceholder import supports the new deleted user functionality.


40-43: Good deleted user handling with helper functions.

The renderUserName and renderAvatar helpers cleanly centralize deleted user logic, showing "Deleted User" text and placeholder avatar when user is null. This aligns with the PR objectives for account deletion.

Also applies to: 67-70

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

♻️ Duplicate comments (1)
packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (1)

44-54: The issues from the previous review are still unresolved.

The renderAvatar function still contains the same critical issues that were identified in the previous review:

  1. Line 49: sizes="small" is not a valid MUI Avatar prop (it's for responsive image srcSet, not sizing)
  2. Line 48: Using style instead of sx is inconsistent with MUI best practices
  3. The Avatar lacks explicit dimensions, creating visual inconsistency with the AvatarDeleteUserIcon

Apply the previously suggested fix:

   const renderAvatar = (group: LogGroup) => {
-    if (group.logs[0]?.user == null) return <AvatarDeleteUserIcon />
+    if (group.logs[0]?.user == null) return <AvatarDeleteUserIcon sx={{ fontSize: 44 }} />
     return (
       <Avatar
-        style={{ marginBottom: '4px' }}
-        sizes="small"
+        sx={{ marginBottom: '4px', width: 44, height: 44 }}
         src={group.logs[0]?.user?.avatar?.url ?? ''}
         alt={group.logs[0]?.user?.fullName ?? 'User activity log avatar'}
       />
     )
   }

Note: Also added explicit fontSize: 44 to AvatarDeleteUserIcon for size consistency.

🧹 Nitpick comments (1)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (1)

25-25: Remove redundant undefined check.

The check message?.profile == null already covers both null and undefined (using loose equality), making the additional || message?.profile === undefined check redundant.

Apply this diff:

-  const isProfileNullOrUndefined = message?.profile == null || message?.profile === undefined
+  const isProfileNullOrUndefined = message?.profile == null
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fd1bd4 and d3e805c.

📒 Files selected for processing (4)
  • packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (4 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (4 hunks)
  • packages/design-system/components/web/icons/AvatarDeleteUserIcon/index.tsx (1 hunks)
  • packages/design-system/components/web/icons/index.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (1)
packages/components/modules/activity-log/common/types.ts (1)
  • LogGroup (7-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Component Test Packages
  • GitHub Check: Build and Lint Packages
🔇 Additional comments (3)
packages/design-system/components/web/icons/index.ts (1)

6-6: LGTM!

The export follows the established pattern and is correctly positioned alphabetically.

packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (2)

77-87: Good sizing consistency with AvatarWithPlaceholder.

The conditional avatar rendering correctly handles the deleted user case, and the fontSize: 32 override on AvatarDeleteUserIcon ensures it matches the 32×32 dimensions of AvatarWithPlaceholder.


53-53: The review comment is incorrect. The === null check is intentional and correct.

The evidence shows isRead is nullable (Boolean | null):

  • GraphQL schema allows null return values
  • Mock data explicitly demonstrates three states: true (read), false (unread), and null (system-generated messages)
  • In the codebase, system messages set isRead: null (e.g., storybook mockResolvers line 111)

The strict null check (=== null) correctly distinguishes this scenario: the check identifies when there's no previous message with a read status to determine grouping. Using == null or a falsy check would incorrectly conflate false (unread user messages) with null (system messages), breaking the grouping logic.

Likely an incorrect or invalid review comment.

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

🧹 Nitpick comments (1)
packages/design-system/components/web/avatars/ClickableAvatar/index.tsx (1)

22-28: Update accessibility text to reflect deleted user context.

The titleAccess prop still reads "Avatar Fallback" but should be more specific now that we're using a dedicated deleted-user icon.

Apply this diff to improve accessibility:

-        <AvatarDeleteUserIcon sx={{ fontSize: width }} titleAccess="Avatar Fallback" />
+        <AvatarDeleteUserIcon sx={{ fontSize: width }} titleAccess="Deleted User Avatar" />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3e805c and 38d410f.

📒 Files selected for processing (4)
  • packages/components/modules/comments/web/CommentItem/CommentReplyButton/index.tsx (1 hunks)
  • packages/components/modules/comments/web/CommentItem/CommentReplyButton/types.ts (1 hunks)
  • packages/components/modules/comments/web/CommentItem/index.tsx (2 hunks)
  • packages/design-system/components/web/avatars/ClickableAvatar/index.tsx (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build and Lint Packages
  • GitHub Check: Component Test Packages
🔇 Additional comments (4)
packages/design-system/components/web/avatars/ClickableAvatar/index.tsx (1)

8-8: LGTM! Semantic improvement.

Replacing the generic AvatarUploadFallbackIcon with the specific AvatarDeleteUserIcon improves semantic clarity for deleted user avatars.

packages/components/modules/comments/web/CommentItem/CommentReplyButton/types.ts (1)

6-6: LGTM!

The optional isDisabled property is correctly typed and maintains backward compatibility.

packages/components/modules/comments/web/CommentItem/index.tsx (1)

143-143: Good refactoring for reusability.

Extracting totalCommentsCount into a local variable improves readability and avoids repeated property access.

packages/components/modules/comments/web/CommentItem/CommentReplyButton/index.tsx (1)

15-15: LGTM!

The isDisabled prop is correctly implemented with a sensible default value and properly forwarded to the IconButton.

Also applies to: 19-19

@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 3, 2025

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

🧹 Nitpick comments (3)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (3)

24-24: Simplify null/undefined check.

The loose equality check == null already matches both null and undefined, so the explicit === undefined check is redundant.

Apply this diff to simplify:

-  const isProfileNullOrUndefined = message?.profile == null || message?.profile === undefined
+  const isProfileNullOrUndefined = message?.profile == null

66-67: Simplify avatar visibility logic.

The boolean expression can be factored to reduce duplication of isFirstGroupedMessage.

Apply this diff:

-  const canShowAvatar =
-    (isProfileNullOrUndefined && isFirstGroupedMessage) || (isFirstGroupedMessage && !isOwnMessage)
+  const canShowAvatar = isFirstGroupedMessage && (isProfileNullOrUndefined || !isOwnMessage)

98-98: Internationalize "Deleted User" string.

The hard-coded "Deleted User" string will not adapt to different locales. Consider using your i18n framework to support multiple languages.

For example, if using react-intl or similar:

{isProfileNullOrUndefined ? t('messages.deletedUser') : message?.profile?.name}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38d410f and ca39ccd.

📒 Files selected for processing (8)
  • packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (4 hunks)
  • packages/components/modules/comments/web/CommentItem/index.tsx (2 hunks)
  • packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (3 hunks)
  • packages/design-system/components/web/avatars/AvatarWithPlaceholder/index.tsx (2 hunks)
  • packages/design-system/components/web/avatars/AvatarWithPlaceholder/types.ts (1 hunks)
  • packages/design-system/components/web/avatars/ClickableAvatar/index.tsx (2 hunks)
  • packages/design-system/components/web/icons/AvatarDeletedUserIcon/index.tsx (1 hunks)
  • packages/design-system/components/web/icons/index.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-02-11T13:55:04.375Z
Learnt from: pt-tsl
Repo: silverlogic/baseapp-frontend PR: 212
File: packages/components/modules/messages/MessagesList/index.tsx:80-80
Timestamp: 2025-02-11T13:55:04.375Z
Learning: Avoid using non-null assertions (!.) in TypeScript code unless there's absolute certainty about non-nullability. Instead, prefer handling null types inside the relevant functions/hooks and use optional chaining (?.) for safer access.

Applied to files:

  • packages/components/modules/comments/web/CommentItem/index.tsx
🧬 Code graph analysis (1)
packages/components/modules/activity-log/web/ActivityLogComponent/LogGroups/index.tsx (1)
packages/components/modules/activity-log/common/types.ts (1)
  • LogGroup (7-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build and Lint Packages
  • GitHub Check: Component Test Packages
🔇 Additional comments (1)
packages/components/modules/messages/web/MessagesList/MessagesGroup/UserMessage/index.tsx (1)

52-52: Verify the logic for determining first message at the top.

Using previousMessage?.isRead === null as the condition to identify the first message at the top seems unusual. This assumes that isRead: null has a special semantic meaning (e.g., messages above the read marker). Please confirm this logic is correct and aligns with your message-read tracking model.

If this is indeed the intended behavior, consider adding a comment explaining why isRead === null indicates the first message at the top, as it's not immediately obvious:

// isRead is null for messages above the read marker, indicating the top of the unread section
const isFirstMessageAtTheTop = previousMessage?.isRead === null

Copy link
Collaborator

@anicioalexandre anicioalexandre left a comment

Choose a reason for hiding this comment

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

friendly reminder to version this PR before merging!

@mathieubouhelier mathieubouhelier merged commit ef7029c into master Nov 11, 2025
8 checks passed
@mathieubouhelier mathieubouhelier deleted the feature/delete-account/BA-2686-FE-package-Account-Deletion-Android-WebApp branch November 11, 2025 15:19
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.

4 participants