Skip to content

draft UX: Improve operation feedback using SnackBars#100

Merged
omatheusmesmo merged 7 commits intoomatheusmesmo:developfrom
matheusandre1:issue37
Mar 13, 2026
Merged

draft UX: Improve operation feedback using SnackBars#100
omatheusmesmo merged 7 commits intoomatheusmesmo:developfrom
matheusandre1:issue37

Conversation

@matheusandre1
Copy link
Copy Markdown
Collaborator

@matheusandre1 matheusandre1 commented Mar 6, 2026

draft, which closes #37

I'll put this up for review after some of the pull requests that were made have been merged, so we don't have to manually resolve conflicts.

Summary by CodeRabbit

  • Improvements
    • Confirmation dialogs now appear when deleting items, categories, shopping lists, and units, requiring explicit confirmation before deletion.
    • Notification system redesigned with distinct visual styling for success and error messages, improving feedback clarity and user experience.

@github-actions github-actions Bot changed the base branch from main to develop March 6, 2026 01:47
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 Attention @matheusandre1! Only the repository owner can target the 'main' branch directly. I've automatically updated your PR to target 'develop' instead. Thank you! 🚀

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 Hi @matheusandre1, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 I'm sorry @matheusandre1, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 Hi @matheusandre1, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 I'm sorry @matheusandre1, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 Hi @matheusandre1, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 6, 2026

🤖 I'm sorry @matheusandre1, but I was unable to process your request. Please see the logs for more details.

@matheusandre1 matheusandre1 marked this pull request as ready for review March 7, 2026 03:19
@omatheusmesmo omatheusmesmo self-requested a review March 7, 2026 19:57
@omatheusmesmo
Copy link
Copy Markdown
Owner

@coderabbitai check this PR.

@matheusandre1 , please check the conflicts.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

@omatheusmesmo: Sure! I'll kick off a review of this PR now. I've also noted that @matheusandre1 has been asked to look into the conflicts.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR replaces native browser confirm() dialogs and direct MatSnackBar usage with two new centralized services: ConfirmDialogService (wrapping Material Dialog) for styled confirmations and FeedbackService (wrapping MatSnackBar) for consistent success/error messaging. The changes affect 12 feature components, 2 shared components, and introduce new dialog and styling components.

Changes

Cohort / File(s) Summary
New Services
frontend/src/app/shared/services/confirm-dialog.service.ts, frontend/src/app/shared/services/feedback.service.ts
New ConfirmDialogService opens confirmation dialogs via Material Dialog API, returning Observable<boolean>. New FeedbackService wraps MatSnackBar with success() and error() methods for consistent feedback styling.
Confirmation Dialog Component
frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts, frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.html
New standalone Angular component ConfirmDialogComponent with exported ConfirmDialogData interface. Renders dialog title, message, and action buttons with default Portuguese labels; closes dialog with boolean result.
List Management Components
frontend/src/app/list/components/categories-management/categories-management.component.ts, frontend/src/app/list/components/items-management/items-management.component.ts, frontend/src/app/list/components/shopping-list/shopping-list.component.ts, frontend/src/app/list/components/units-management/units-management.component.ts
Inject ConfirmDialogService and FeedbackService; replace window.confirm() with async dialog flow and MatSnackBar calls with feedback service methods for all CRUD operations.
Dialog Components
frontend/src/app/list/components/category-dialog/category-dialog.component.ts, frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts, frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts, frontend/src/app/list/components/shopping-list-dialog/shopping-list-dialog.component.ts, frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts
Replace MatSnackBar with FeedbackService for error/success notifications; update error messages with localized text. In unit-dialog, extend duplicateNameValidator() signature to accept optional originalName parameter.
List Details Component
frontend/src/app/list/components/list-details/list-details.component.ts
Replace browser confirm() with ConfirmDialogService; route all item lifecycle feedback (status toggle, add, update, remove) through FeedbackService instead of MatSnackBar.
Shared Components
frontend/src/app/shared/components/category/category.component.ts, frontend/src/app/shared/components/item/item.component.ts, frontend/src/app/shared/components/list-item/list-item.component.ts, frontend/src/app/shared/components/unit/unit.component.ts
Remove MatSnackBar from constructors; inject ConfirmDialogService and FeedbackService via inject(). Replace sync confirm() and snackbar calls with async confirmation dialogs and feedback service methods; update messages to Portuguese.
Snackbar Theming
frontend/src/styles.scss
Add .success-snackbar and .error-snackbar CSS classes with Material/MDC theming properties for styled feedback messages.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Comp as Component
    participant CDS as ConfirmDialogService
    participant MD as MatDialog
    participant CDC as ConfirmDialogComponent
    participant API as API Service
    participant FB as FeedbackService

    User->>Comp: Trigger delete action
    Comp->>CDS: open({title, message})
    CDS->>MD: open(ConfirmDialogComponent)
    MD->>CDC: Display dialog
    CDC-->>User: Show dialog UI
    User->>CDC: Click confirm
    CDC-->>MD: Close with true
    MD-->>CDS: Dialog closed
    CDS-->>Comp: Observable<true>
    Comp->>API: Delete resource
    alt Success
        API-->>Comp: Success response
        Comp->>FB: success(message)
        FB-->>User: Show success snackbar
    else Error
        API-->>Comp: Error response
        Comp->>FB: error(message)
        FB-->>User: Show error snackbar
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A rabbit hops through dialogs neat,
Confirmations styled, feedback complete!
No more native windows pop—
Material magic makes users stop.
Success and errors, all aligned,
Better UX, beautifully designed!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning Title mentions improving feedback using SnackBars, but the actual changes primarily replace SnackBars with a new FeedbackService abstraction. Update the title to reflect the actual implementation, such as 'Refactor feedback mechanism to use centralized FeedbackService' or 'Replace MatSnackBar with abstracted FeedbackService for improved UX feedback'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed All coding requirements from issue #37 are met: native confirm() calls replaced with ConfirmDialogService dialogs, and consistent FeedbackService used for all CRUD operation feedback.
Out of Scope Changes check ✅ Passed All changes directly support the linked issue objectives by replacing native confirm dialogs and implementing consistent feedback mechanisms across components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @coderabbitai[bot], I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

@omatheusmesmo: Thanks for the heads-up! The review is now in progress. You can monitor the workflow run in the logs. The review results will be posted once the run completes.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

## 📋 Review Summary

O Pull Request implementa uma melhoria significativa na experiência do usuário ao substituir os diálogos de confirmação nativos do navegador por componentes do Angular Material e centralizar o feedback de operações via SnackBars. A arquitetura proposta com os serviços ConfirmDialogService e FeedbackService é sólida e promove o reuso de código.

🔍 General Feedback

  • Consistência de Linguagem: Notei que algumas mensagens foram alteradas para português, o que parece ser o padrão do projeto, mas houve algumas regressões ortográficas (faltando acentos em "excluída", "validação", "unidade", etc.) em vários componentes.
  • Limpeza de Código: Foram adicionados arquivos vazios (SCSS) que podem ser removidos.
  • Prática Recomendada: Em futuras iterações, considere utilizar o operador take(1) ou first() em subscrições de diálogos, embora o afterClosed() do Material complete automaticamente, é uma prática defensiva comum em Angular.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts (1)

97-105: ⚠️ Potential issue | 🟡 Minor

Block save when duplicate-name validation cannot be initialized.

If getAllItems() fails here, the dialog only shows feedback and keeps the form submittable without duplicateNameValidator, so duplicate item names can slip through. Set a blocking form/control error or otherwise prevent save until this bootstrap call succeeds.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts`
around lines 97 - 105, The loadItems error path currently only shows feedback
but leaves the form submittable; update the error handler in loadItems (which
calls this.itemService.getAllItems() and then this.updateNameValidator()) to
block saves until duplicate-name validation is available by either disabling the
dialog form (e.g., call this.form.disable()) or setting a control-level error on
the name control (e.g., this.nameControl.setErrors({validationUnavailable:
true})), and ensure any submit logic that checks this.form.valid or
this.nameControl.hasError('validationUnavailable') prevents saving; keep
references to existingItems and updateNameValidator unchanged so success still
initializes duplicateNameValidator.
frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts (1)

81-89: ⚠️ Potential issue | 🟡 Minor

Do not keep the dialog saveable after unit-name validation bootstrap fails.

When getAllUnits() errors, the form still allows submission without the duplicate-name validator being installed. Please surface the error and block save until the validator can be initialized again.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts`
around lines 81 - 89, The loadUnits() error handler currently logs an error but
leaves the dialog saveable; modify the error branch in loadUnits() (which calls
unitService.getAllUnits(), existingUnits.set(), updateNameValidator()) to both
surface the error and block saves until validation can be reinitialized — e.g.,
after feedback.error('...') set the component state that prevents submission
(disable the FormGroup or set a saveEnabled/saveBlocked flag used by the save
button and onSave logic) so the dialog cannot be submitted until
updateNameValidator() successfully runs again.
🧹 Nitpick comments (9)
frontend/src/app/shared/services/feedback.service.ts (1)

10-21: Factor the repeated snackbar setup into one helper.

Both methods repeat the same config, which makes future UX tweaks easier to miss in one branch.

♻️ Proposed refactor
 export class FeedbackService {
   private readonly snackBar = inject(MatSnackBar);

+  private open(message: string, panelClass: string): void {
+    this.snackBar.open(message, 'Fechar', {
+      duration: 3000,
+      panelClass: [panelClass],
+    });
+  }
+
   success(message: string): void {
-    this.snackBar.open(message, 'Fechar', {
-      duration: 3000,
-      panelClass: ['success-snackbar'],
-    });
+    this.open(message, 'success-snackbar');
   }

   error(message: string): void {
-    this.snackBar.open(message, 'Fechar', {
-      duration: 3000,
-      panelClass: ['error-snackbar'],
-    });
+    this.open(message, 'error-snackbar');
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/services/feedback.service.ts` around lines 10 - 21,
Both success and error duplicate the same MatSnackBar call; create a single
private helper (e.g., showSnackbar or openToast) that accepts the message and
the panel class (or a type enum) and centralizes snackBar.open(...) with the
shared config (duration: 3000, action 'Fechar', and panelClass) and then have
success(message: string) and error(message: string) call that helper with the
appropriate panelClass (['success-snackbar'] or ['error-snackbar']). This
consolidates the config and keeps only the unique parameter per public method.
frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts (1)

56-56: OnPush compatibility note.

Same recommendation as other components: consider adding ChangeDetectorRef to properly handle isLoading state changes with ChangeDetectionStrategy.OnPush.

Also applies to: 62-63, 70-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`
at line 56, The component uses ChangeDetectionStrategy.OnPush but doesn't inject
ChangeDetectorRef, so updates to isLoading may not trigger view refresh; inject
ChangeDetectorRef into the ListShareDialogComponent constructor and call
markForCheck() (or detectChanges() where appropriate) after any assignment that
changes isLoading (and similar state updates referenced at lines 62-63 and 70)
to ensure the template updates correctly with OnPush.
frontend/src/app/shared/components/item/item.component.ts (1)

50-50: Consider adding ChangeDetectorRef for OnPush compatibility.

This component uses ChangeDetectionStrategy.OnPush but mutates isLoading directly without triggering change detection. Unlike units-management.component.ts which correctly injects ChangeDetectorRef, this component may have stale UI states (e.g., spinner not hiding after load completes).

♻️ Suggested fix
 import {
   ChangeDetectionStrategy,
+  ChangeDetectorRef,
   Component,
   OnInit,
   inject,
 } from '@angular/core';
   private confirmDialog = inject(ConfirmDialogService);
   private feedback = inject(FeedbackService);
+  private cdr = inject(ChangeDetectorRef);

Then call this.cdr.detectChanges() after setting isLoading = false in the subscribe callbacks.

Also applies to: 56-56, 60-61

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/item/item.component.ts` at line 50, This
component uses ChangeDetectionStrategy.OnPush but mutates isLoading directly;
inject Angular's ChangeDetectorRef into the component constructor (e.g., add a
private cdr: ChangeDetectorRef parameter) and import it, then call
this.cdr.detectChanges() immediately after setting this.isLoading = false in the
relevant subscribe callbacks (success, error, or finalize) so the template
updates; reference the isLoading property and the subscribe callbacks where
loading is toggled in item.component.ts when making the change.
frontend/src/app/list/components/shopping-list/shopping-list.component.ts (1)

29-29: Same OnPush + isLoading consideration.

Consider adding ChangeDetectorRef for proper change detection with ChangeDetectionStrategy.OnPush.

Also applies to: 33-33, 35-40

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/list/components/shopping-list/shopping-list.component.ts` at
line 29, The component uses ChangeDetectionStrategy.OnPush but doesn't trigger
detection when isLoading changes; inject ChangeDetectorRef into
ShoppingListComponent (constructor) and call markForCheck() (or detectChanges())
after any updates to the isLoading flag or other async state changes (e.g., in
methods that set isLoading or in subscriptions/async callbacks) so the template
is updated; look for the isLoading property and places where it is toggled and
add cdr.markForCheck() there.
frontend/src/app/shared/components/list-item/list-item.component.ts (1)

51-51: Same OnPush + isLoading issue as item.component.ts.

Consider injecting ChangeDetectorRef and calling detectChanges() after state mutations to ensure the UI updates correctly with ChangeDetectionStrategy.OnPush.

Also applies to: 56-56, 61-62

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/list-item/list-item.component.ts` at line
51, ListItemComponent is set to ChangeDetectionStrategy.OnPush but state flags
like isLoading are mutated without triggering change detection; inject
ChangeDetectorRef into the component (e.g., add private cdr: ChangeDetectorRef
to the constructor) and call this.cdr.detectChanges() (or markForCheck() where
appropriate) immediately after any mutation of isLoading or other view-bound
state in methods that perform async work so the template updates; apply the same
change to other affected spots referenced in the comment (the other blocks
around the OnPush setting at the same component and similar methods).
frontend/src/app/list/components/categories-management/categories-management.component.ts (1)

26-26: OnPush compatibility note applies here as well.

This component uses constructor injection (which is fine), but like the others, it would benefit from ChangeDetectorRef to handle isLoading state changes with ChangeDetectionStrategy.OnPush.

Also applies to: 30-30, 32-37

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/categories-management/categories-management.component.ts`
at line 26, The component uses ChangeDetectionStrategy.OnPush but doesn't
trigger checks when isLoading updates; inject ChangeDetectorRef into the
constructor (e.g., private cdr: ChangeDetectorRef) in
categories-management.component (with ChangeDetectionStrategy.OnPush) and call
this.cdr.markForCheck() or this.cdr.detectChanges() immediately after any
assignment to isLoading (and similar async state updates) so the template
refreshes; apply the same pattern to other usages referenced (lines ~30 and
~32-37) where async state changes occur.
frontend/src/app/shared/components/unit/unit.component.ts (1)

120-140: Same nested subscription pattern as CategoryComponent.

Apply the same flattening approach with switchMap and takeUntilDestroyed() for consistent cleanup across components.

♻️ Proposed refactor
+import { filter, switchMap } from 'rxjs';
+import { DestroyRef, takeUntilDestroyed } from '@angular/core';
+  private destroyRef = inject(DestroyRef);
+
   deleteUnit(id: number): void {
-    this.confirmDialog
-      .open({
-        title: 'Excluir unidade',
-        message: 'Tem certeza que deseja excluir esta unidade?',
-        confirmText: 'Excluir',
-      })
-      .subscribe((confirmed) => {
-        if (!confirmed) return;
-
-        this.unitService.deleteUnit(id).subscribe({
-          next: () => {
-            this.feedback.success('Unidade excluida com sucesso');
-            this.loadUnits();
-          },
-          error: () => {
-            this.feedback.error('Erro ao excluir unidade');
-          },
-        });
-      });
+    this.confirmDialog
+      .open({
+        title: 'Excluir unidade',
+        message: 'Tem certeza que deseja excluir esta unidade?',
+        confirmText: 'Excluir',
+      })
+      .pipe(
+        takeUntilDestroyed(this.destroyRef),
+        filter((confirmed) => confirmed),
+        switchMap(() => this.unitService.deleteUnit(id))
+      )
+      .subscribe({
+        next: () => {
+          this.feedback.success('Unidade excluída com sucesso');
+          this.loadUnits();
+        },
+        error: () => {
+          this.feedback.error('Erro ao excluir unidade');
+        },
+      });
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/unit/unit.component.ts` around lines 120 -
140, Refactor deleteUnit to avoid nested subscriptions: call
this.confirmDialog.open(...) and pipe it with switchMap to only proceed when
confirmed, then switchMap to this.unitService.deleteUnit(id), and subscribe with
takeUntilDestroyed() for automatic cleanup; update success/error handling to run
in the final subscribe (or tap) and call this.loadUnits() on success,
referencing the deleteUnit method, confirmDialog.open, unitService.deleteUnit,
loadUnits, switchMap, and takeUntilDestroyed symbols so the nested subscribe is
replaced by a single flattened observable chain.
frontend/src/app/shared/components/category/category.component.ts (2)

117-137: Nested subscription creates potential memory leak risk.

If the component is destroyed while waiting for the user to confirm, both the outer and inner subscriptions continue. Consider flattening with switchMap or concatMap, and using takeUntilDestroyed() for automatic cleanup.

♻️ Proposed refactor using RxJS operators
+import { filter, switchMap } from 'rxjs';
+import { DestroyRef, takeUntilDestroyed } from '@angular/core';
+  private destroyRef = inject(DestroyRef);
+
   deleteCategory(id: number): void {
-    this.confirmDialog
-      .open({
-        title: 'Excluir categoria',
-        message: 'Tem certeza que deseja excluir esta categoria?',
-        confirmText: 'Excluir',
-      })
-      .subscribe((confirmed) => {
-        if (!confirmed) return;
-
-        this.categoryService.deleteCategory(id).subscribe({
-          next: () => {
-            this.feedback.success('Categoria excluida com sucesso');
-            this.loadCategories();
-          },
-          error: () => {
-            this.feedback.error('Erro ao excluir categoria');
-          },
-        });
-      });
+    this.confirmDialog
+      .open({
+        title: 'Excluir categoria',
+        message: 'Tem certeza que deseja excluir esta categoria?',
+        confirmText: 'Excluir',
+      })
+      .pipe(
+        takeUntilDestroyed(this.destroyRef),
+        filter((confirmed) => confirmed),
+        switchMap(() => this.categoryService.deleteCategory(id))
+      )
+      .subscribe({
+        next: () => {
+          this.feedback.success('Categoria excluída com sucesso');
+          this.loadCategories();
+        },
+        error: () => {
+          this.feedback.error('Erro ao excluir categoria');
+        },
+      });
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/category/category.component.ts` around
lines 117 - 137, The deleteCategory method currently nests subscriptions
(confirmDialog.open(...).subscribe(...) and
categoryService.deleteCategory(...).subscribe(...)) which can leak if the
component is destroyed; refactor deleteCategory to flatten the flow by piping
confirmDialog.open(...) into switchMap or concatMap to call
categoryService.deleteCategory(id) and subscribe once, and add automatic
teardown with takeUntilDestroyed() (or pipe takeUntilDestroyed() on the stream)
so both the confirmation and delete observables are cancelled when the component
is destroyed; keep existing success/error handling
(feedback.success/feedback.error and loadCategories()) inside the single
subscription or via tap/catchError in the pipeline.

48-58: Mixed dependency injection styles are used.

The component uses inject() for ConfirmDialogService and FeedbackService (lines 48-49) while using constructor injection for CategoryService and FormBuilder (lines 52-53). Both approaches are valid in Angular 14+, but consistency improves readability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/category/category.component.ts` around
lines 48 - 58, The component mixes inject() and constructor injection
(confirmDialog, feedback vs CategoryService, fb/FormBuilder) which is
inconsistent; pick one style (prefer constructor injection for readability) and
refactor so all dependencies are injected the same way: add ConfirmDialogService
and FeedbackService as private constructor parameters (e.g., private
confirmDialog: ConfirmDialogService, private feedback: FeedbackService), remove
the top-level inject(...) calls, and ensure usages of confirmDialog, feedback,
CategoryService, fb/FormBuilder and the existing categoryForm initialization
remain correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/app/shared/components/category/category.component.ts`:
- Line 129: The success message in CategoryComponent uses a misspelled
Portuguese word; update the call to this.feedback.success in
category.component.ts to use the correct accented form "Categoria excluída com
sucesso" (replace "excluida" with "excluída") so the displayed message is
orthographically correct.

In `@frontend/src/app/shared/components/unit/unit.component.ts`:
- Line 132: The success message in UnitComponent currently uses a missing accent
("excluida"); update the string passed to this.feedback.success in the
UnitComponent (method containing this.feedback.success call) to use the correct
Portuguese spelling "Unidade excluída com sucesso" so it matches the corrected
form used in CategoryComponent and other messages.

In `@frontend/src/app/shared/services/confirm-dialog.service.ts`:
- Around line 15-23: SignupComponent and LoginComponent still inject MatSnackBar
directly instead of using the centralized FeedbackService; refactor them to
remove MatSnackBar from their constructors and inject FeedbackService (replace
references to MatSnackBar with FeedbackService). Update calls like
snackBar.open(message, action, config) in SignupComponent (previous calls around
the signup success/error flows) and LoginComponent (previous login error flow)
to the appropriate FeedbackService method (e.g., show/notify or the service’s
public API) passing the same message, action and any important config. Ensure
constructor parameter names and imports are updated (replace MatSnackBar
injection with FeedbackService) and run/adjust unit tests if they reference
MatSnackBar directly.

---

Outside diff comments:
In
`@frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts`:
- Around line 97-105: The loadItems error path currently only shows feedback but
leaves the form submittable; update the error handler in loadItems (which calls
this.itemService.getAllItems() and then this.updateNameValidator()) to block
saves until duplicate-name validation is available by either disabling the
dialog form (e.g., call this.form.disable()) or setting a control-level error on
the name control (e.g., this.nameControl.setErrors({validationUnavailable:
true})), and ensure any submit logic that checks this.form.valid or
this.nameControl.hasError('validationUnavailable') prevents saving; keep
references to existingItems and updateNameValidator unchanged so success still
initializes duplicateNameValidator.

In
`@frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts`:
- Around line 81-89: The loadUnits() error handler currently logs an error but
leaves the dialog saveable; modify the error branch in loadUnits() (which calls
unitService.getAllUnits(), existingUnits.set(), updateNameValidator()) to both
surface the error and block saves until validation can be reinitialized — e.g.,
after feedback.error('...') set the component state that prevents submission
(disable the FormGroup or set a saveEnabled/saveBlocked flag used by the save
button and onSave logic) so the dialog cannot be submitted until
updateNameValidator() successfully runs again.

---

Nitpick comments:
In
`@frontend/src/app/list/components/categories-management/categories-management.component.ts`:
- Line 26: The component uses ChangeDetectionStrategy.OnPush but doesn't trigger
checks when isLoading updates; inject ChangeDetectorRef into the constructor
(e.g., private cdr: ChangeDetectorRef) in categories-management.component (with
ChangeDetectionStrategy.OnPush) and call this.cdr.markForCheck() or
this.cdr.detectChanges() immediately after any assignment to isLoading (and
similar async state updates) so the template refreshes; apply the same pattern
to other usages referenced (lines ~30 and ~32-37) where async state changes
occur.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`:
- Line 56: The component uses ChangeDetectionStrategy.OnPush but doesn't inject
ChangeDetectorRef, so updates to isLoading may not trigger view refresh; inject
ChangeDetectorRef into the ListShareDialogComponent constructor and call
markForCheck() (or detectChanges() where appropriate) after any assignment that
changes isLoading (and similar state updates referenced at lines 62-63 and 70)
to ensure the template updates correctly with OnPush.

In `@frontend/src/app/list/components/shopping-list/shopping-list.component.ts`:
- Line 29: The component uses ChangeDetectionStrategy.OnPush but doesn't trigger
detection when isLoading changes; inject ChangeDetectorRef into
ShoppingListComponent (constructor) and call markForCheck() (or detectChanges())
after any updates to the isLoading flag or other async state changes (e.g., in
methods that set isLoading or in subscriptions/async callbacks) so the template
is updated; look for the isLoading property and places where it is toggled and
add cdr.markForCheck() there.

In `@frontend/src/app/shared/components/category/category.component.ts`:
- Around line 117-137: The deleteCategory method currently nests subscriptions
(confirmDialog.open(...).subscribe(...) and
categoryService.deleteCategory(...).subscribe(...)) which can leak if the
component is destroyed; refactor deleteCategory to flatten the flow by piping
confirmDialog.open(...) into switchMap or concatMap to call
categoryService.deleteCategory(id) and subscribe once, and add automatic
teardown with takeUntilDestroyed() (or pipe takeUntilDestroyed() on the stream)
so both the confirmation and delete observables are cancelled when the component
is destroyed; keep existing success/error handling
(feedback.success/feedback.error and loadCategories()) inside the single
subscription or via tap/catchError in the pipeline.
- Around line 48-58: The component mixes inject() and constructor injection
(confirmDialog, feedback vs CategoryService, fb/FormBuilder) which is
inconsistent; pick one style (prefer constructor injection for readability) and
refactor so all dependencies are injected the same way: add ConfirmDialogService
and FeedbackService as private constructor parameters (e.g., private
confirmDialog: ConfirmDialogService, private feedback: FeedbackService), remove
the top-level inject(...) calls, and ensure usages of confirmDialog, feedback,
CategoryService, fb/FormBuilder and the existing categoryForm initialization
remain correct.

In `@frontend/src/app/shared/components/item/item.component.ts`:
- Line 50: This component uses ChangeDetectionStrategy.OnPush but mutates
isLoading directly; inject Angular's ChangeDetectorRef into the component
constructor (e.g., add a private cdr: ChangeDetectorRef parameter) and import
it, then call this.cdr.detectChanges() immediately after setting this.isLoading
= false in the relevant subscribe callbacks (success, error, or finalize) so the
template updates; reference the isLoading property and the subscribe callbacks
where loading is toggled in item.component.ts when making the change.

In `@frontend/src/app/shared/components/list-item/list-item.component.ts`:
- Line 51: ListItemComponent is set to ChangeDetectionStrategy.OnPush but state
flags like isLoading are mutated without triggering change detection; inject
ChangeDetectorRef into the component (e.g., add private cdr: ChangeDetectorRef
to the constructor) and call this.cdr.detectChanges() (or markForCheck() where
appropriate) immediately after any mutation of isLoading or other view-bound
state in methods that perform async work so the template updates; apply the same
change to other affected spots referenced in the comment (the other blocks
around the OnPush setting at the same component and similar methods).

In `@frontend/src/app/shared/components/unit/unit.component.ts`:
- Around line 120-140: Refactor deleteUnit to avoid nested subscriptions: call
this.confirmDialog.open(...) and pipe it with switchMap to only proceed when
confirmed, then switchMap to this.unitService.deleteUnit(id), and subscribe with
takeUntilDestroyed() for automatic cleanup; update success/error handling to run
in the final subscribe (or tap) and call this.loadUnits() on success,
referencing the deleteUnit method, confirmDialog.open, unitService.deleteUnit,
loadUnits, switchMap, and takeUntilDestroyed symbols so the nested subscribe is
replaced by a single flattened observable chain.

In `@frontend/src/app/shared/services/feedback.service.ts`:
- Around line 10-21: Both success and error duplicate the same MatSnackBar call;
create a single private helper (e.g., showSnackbar or openToast) that accepts
the message and the panel class (or a type enum) and centralizes
snackBar.open(...) with the shared config (duration: 3000, action 'Fechar', and
panelClass) and then have success(message: string) and error(message: string)
call that helper with the appropriate panelClass (['success-snackbar'] or
['error-snackbar']). This consolidates the config and keeps only the unique
parameter per public method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8356b381-cf0d-4992-84a9-b6fe9d49a953

📥 Commits

Reviewing files that changed from the base of the PR and between 4bb8b12 and 88ac529.

📒 Files selected for processing (20)
  • frontend/src/app/list/components/categories-management/categories-management.component.ts
  • frontend/src/app/list/components/category-dialog/category-dialog.component.ts
  • frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts
  • frontend/src/app/list/components/items-management/items-management.component.ts
  • frontend/src/app/list/components/list-details/list-details.component.ts
  • frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts
  • frontend/src/app/list/components/shopping-list-dialog/shopping-list-dialog.component.ts
  • frontend/src/app/list/components/shopping-list/shopping-list.component.ts
  • frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts
  • frontend/src/app/list/components/units-management/units-management.component.ts
  • frontend/src/app/shared/components/category/category.component.ts
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.html
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.scss
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts
  • frontend/src/app/shared/components/item/item.component.ts
  • frontend/src/app/shared/components/list-item/list-item.component.ts
  • frontend/src/app/shared/components/unit/unit.component.ts
  • frontend/src/app/shared/services/confirm-dialog.service.ts
  • frontend/src/app/shared/services/feedback.service.ts
  • frontend/src/styles.scss

Comment thread frontend/src/app/shared/components/category/category.component.ts Outdated
Comment thread frontend/src/app/shared/components/unit/unit.component.ts Outdated
Comment on lines +15 to +23
open(data: ConfirmDialogData): Observable<boolean> {
return this.dialog
.open(ConfirmDialogComponent, {
width: '420px',
data,
})
.afterClosed()
.pipe(map((confirmed) => confirmed === true));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\nNative confirm() usages (expected: no matches):\n'
rg -nP '\b(?:window\.)?confirm\s*\(' frontend/src || true

printf '\nDirect MatSnackBar usages outside FeedbackService (expected: no matches):\n'
rg -nP 'MatSnackBar|\bsnackBar\.open\s*\(' frontend/src/app \
  -g '!frontend/src/app/shared/services/feedback.service.ts' || true

Repository: omatheusmesmo/ShoppMate

Length of output: 2955


Complete the feedback service migration in auth components.

The ConfirmDialogService is correctly implemented, but the migration to centralized feedback is incomplete. No native confirm() calls remain, but two components still inject MatSnackBar directly instead of using FeedbackService:

  • frontend/src/app/auth/signup/signup.component.ts (lines 66, 73)
  • frontend/src/app/auth/login/login.component.ts (line 68)

These need to be refactored to use the shared FeedbackService before merge.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/services/confirm-dialog.service.ts` around lines 15 -
23, SignupComponent and LoginComponent still inject MatSnackBar directly instead
of using the centralized FeedbackService; refactor them to remove MatSnackBar
from their constructors and inject FeedbackService (replace references to
MatSnackBar with FeedbackService). Update calls like snackBar.open(message,
action, config) in SignupComponent (previous calls around the signup
success/error flows) and LoginComponent (previous login error flow) to the
appropriate FeedbackService method (e.g., show/notify or the service’s public
API) passing the same message, action and any important config. Ensure
constructor parameter names and imports are updated (replace MatSnackBar
injection with FeedbackService) and run/adjust unit tests if they reference
MatSnackBar directly.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @matheusandre1, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @matheusandre1, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @coderabbitai[bot], I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

@omatheusmesmo: The automated workflow has picked up the request and is processing it. You can track the progress in the logs. The review results will be posted once the run completes.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @coderabbitai[bot], but I was unable to process your request. Please see the logs for more details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

@omatheusmesmo — It looks like the workflow run encountered an error while processing the review. This is likely because the PR is currently in draft status and has unresolved merge conflicts (as noted by @matheusandre1).

Here's what I'd suggest:

  1. Resolve the merge conflicts on the issue37 branch first.
  2. Mark the PR as ready for review (or keep it as a draft if preferred).
  3. Once conflicts are resolved, I can kick off a fresh review.

Would you like me to trigger a new review now, or would you prefer to wait until the conflicts are resolved?

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @matheusandre1, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
frontend/src/app/auth/signup/signup.component.ts (1)

78-82: ⚠️ Potential issue | 🟠 Major

Preserve error styling on the signup failure path.

This call drops the error-snackbar styling, so signup failures will look different from the other error flows. FeedbackService.error() in frontend/src/app/shared/services/feedback.service.ts already defines the error presentation, and this path currently bypasses it. That breaks the PR’s consistency goal.

Suggested fix
          this.feedback.notify(
            'Falha ao realizar cadastro. Tente novamente.',
            'Fechar',
-            { duration: 5000 },
+            {
+              duration: 5000,
+              panelClass: ['error-snackbar'],
+            },
          );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/auth/signup/signup.component.ts` around lines 78 - 82, The
signup failure path is calling this.feedback.notify(...) which bypasses the
standardized error styling; replace that call with the FeedbackService error
method (e.g., this.feedback.error(...)) used elsewhere so the error-snackbar
styling and consistent presentation are preserved. Update the call in
signup.component.ts (the block handling signup failure) to invoke the same
signature/parameters as FeedbackService.error and remove the direct notify usage
so styling/behavior matches other error flows.
frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts (1)

118-129: ⚠️ Potential issue | 🟠 Major

Remove the non-null assertion on user.id.

The User interface defines id as optional, so getAllUsers() can return users without an id. The non-null assertion user.id! bypasses the type system and could send an invalid idUser payload. Add a guard to check if user.id is defined before calling addListPermission.

Suggested fix
       const user = this.users().find((u) => u.email === email);

       if (!user) {
         this.feedback.error('Usuario nao encontrado com este e-mail');
         return;
       }
+
+      if (user.id == null) {
+        this.feedback.error('Usuario selecionado sem identificador valido');
+        return;
+      }

       const request = {
         idList: this.data.listId,
-        idUser: user.id!,
+        idUser: user.id,
         permission: this.shareForm.value.permission,
       };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`
around lines 118 - 129, The code uses a non-null assertion on user.id when
building the request in the ListShareDialog component; instead, guard that id is
present before calling addListPermission: after finding user via users(), check
if user.id is defined, show the existing feedback.error (or a new message) and
return if missing, then build the request using user.id (no !) and call
addListPermission; update any references in the submit/share handler (e.g., the
method that constructs request and calls addListPermission) to perform this
guard so an undefined id is never sent to the API.
frontend/src/app/shared/components/category/category.component.ts (2)

82-100: ⚠️ Potential issue | 🟡 Minor

Capture the edit state before the request starts.

editingCategoryId() is re-read inside the async next handler. If the form state changes before the response returns, the success message can announce the wrong operation even though the API call was correct.

🛠️ Suggested fix
     const categoryData: Category = {
       name: this.categoryForm.value.name,
     };
 
-    if (this.editingCategoryId() !== null) {
-      categoryData.id = this.editingCategoryId()!;
-    }
-
-    const operation =
-      this.editingCategoryId() !== null
-        ? this.categoryService.updateCategory(categoryData)
-        : this.categoryService.addCategory(categoryData);
+    const editingCategoryId = this.editingCategoryId();
+    const isEdit = editingCategoryId !== null;
+
+    if (isEdit) {
+      categoryData.id = editingCategoryId;
+    }
+
+    const operation = isEdit
+      ? this.categoryService.updateCategory(categoryData)
+      : this.categoryService.addCategory(categoryData);
 
     operation.subscribe({
       next: () => {
         this.feedback.success(
-          this.editingCategoryId() !== null
+          isEdit
             ? 'Categoria atualizada com sucesso'
             : 'Categoria criada com sucesso',
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/category/category.component.ts` around
lines 82 - 100, The success message re-evaluates editingCategoryId() inside the
async subscribe next handler which can be different if the form changed before
the response returns; capture the edit state once before making the request
(e.g. const isEditing = this.editingCategoryId() !== null), use that to set
categoryData.id if needed and to decide which service method to call (operation)
and then use isEditing inside the subscribe next callback to pick the correct
success text; update references to editingCategoryId(), categoryData, operation,
and the next handler accordingly.

65-76: ⚠️ Potential issue | 🟠 Major

Separate mutation feedback from the follow-up refresh.

loadCategories() is reused after create/update/delete and always emits Erro ao carregar categorias. If the refetch fails after a successful mutation, users can get both a success message and an error message for the same action, and the list may remain stale. A silent refresh or a refresh-specific error message would keep the UX consistent.

Also applies to: 95-103, 129-131

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/category/category.component.ts` around
lines 65 - 76, loadCategories() currently always shows feedback.error on any
fetch failure which causes confusing UX when it’s used as a follow-up refresh
after a successful create/update/delete; change loadCategories signature to
accept an optional flag (e.g., suppressError?: boolean or silent?: boolean) and
use that flag to avoid showing the global error message on silent refreshes,
only log or show a refresh-specific message when not silent; update all callers
(including the create/update/delete follow-ups referenced at the other
occurrences) to call loadCategories(true) for background refreshes and leave
default behavior for direct user-initiated loads, and ensure
isLoading.set(false) is still executed in both success and error paths.
frontend/src/app/list/components/categories-management/categories-management.component.ts (1)

48-59: ⚠️ Potential issue | 🟠 Major

Separate delete feedback from refresh feedback.

loadCategories() always shows Erro ao carregar categorias. Because the delete success path immediately calls it, a transient refetch failure can produce both a success message and an error message for the same delete action, and the stale category will stay visible until a later refresh succeeds. A silent refresh path, or updating the local signal before refetching, would keep the feedback consistent.

💡 One possible direction
-  loadCategories(): void {
+  loadCategories(showErrorFeedback = true): void {
     this.isLoading.set(true);
     this.categoryService.getAllCategories().subscribe({
       next: (categories) => {
         this.categories.set(categories);
         this.isLoading.set(false);
       },
       error: () => {
-        this.feedback.error('Erro ao carregar categorias');
+        if (showErrorFeedback) {
+          this.feedback.error('Erro ao carregar categorias');
+        }
         this.isLoading.set(false);
       },
     });
   }
@@
           next: () => {
             this.feedback.success('Categoria excluída com sucesso');
-            this.loadCategories();
+            this.categories.update((categories) =>
+              categories.filter((category) => category.id !== id),
+            );
+            this.loadCategories(false);
           },

Also applies to: 99-101

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/categories-management/categories-management.component.ts`
around lines 48 - 59, loadCategories() currently always surfaces an error via
feedback.error when the refetch fails, which causes conflicting UI messages
after a delete that calls loadCategories(); modify the refresh path so delete
success does not trigger user-facing error feedback: either (a) update the local
signal this.categories (or remove the deleted item from this.categories)
immediately in the delete success handler and then call a silent refresh that
suppresses feedback.error from categoryService.getAllCategories() (e.g., add a
boolean silent flag to loadCategories() that skips feedback on error), or (b)
have loadCategories() detect a silent refresh parameter and only set
this.isLoading/feedback on non-silent calls; reference loadCategories(),
categoryService.getAllCategories(), and feedback.error to implement the
silent-refresh or immediate local update approach.
🧹 Nitpick comments (6)
frontend/src/app/shared/components/unit/unit.component.ts (2)

49-55: Consider unifying dependency injection style.

The component mixes inject() function (lines 49-50) with constructor injection (lines 53-54). While both work correctly in Angular 19, using one consistent pattern improves readability.

♻️ Optional: Migrate all dependencies to inject()
-  private confirmDialog = inject(ConfirmDialogService);
-  private feedback = inject(FeedbackService);
+  private readonly unitService = inject(UnitService);
+  private readonly fb = inject(FormBuilder);
+  private readonly confirmDialog = inject(ConfirmDialogService);
+  private readonly feedback = inject(FeedbackService);

-  constructor(
-    private unitService: UnitService,
-    private fb: FormBuilder,
-  ) {
+  constructor() {
     this.unitForm = this.fb.group({
       name: ['', [Validators.required, Validators.minLength(2)]],
       symbol: ['', [Validators.required]],
     });
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/unit/unit.component.ts` around lines 49 -
55, The component mixes inject() calls for confirmDialog and feedback with
constructor-based injection for UnitService and FormBuilder; pick one style and
apply it consistently (either move confirmDialog and feedback into the
constructor or convert unitService and fb to use inject()). Locate the class
where confirmDialog and feedback are declared and the constructor that accepts
UnitService and FormBuilder (e.g., the UnitComponent class) and refactor so all
dependencies use the same approach, updating property declarations accordingly
and removing any now-unused constructor parameters or inject() calls.

121-141: Consider flattening nested subscriptions with RxJS operators.

The nested subscribe calls (dialog result → delete operation) can be refactored using switchMap and filter for cleaner, more idiomatic RxJS code. This avoids the callback pyramid and improves readability.

♻️ Proposed refactor using RxJS operators

Add to imports:

import { filter, switchMap } from 'rxjs';
 deleteUnit(id: number): void {
   this.confirmDialog
     .open({
       title: 'Excluir unidade',
       message: 'Tem certeza que deseja excluir esta unidade?',
       confirmText: 'Excluir',
     })
-    .subscribe((confirmed) => {
-      if (!confirmed) return;
-
-      this.unitService.deleteUnit(id).subscribe({
-        next: () => {
-          this.feedback.success('Unidade excluída com sucesso');
-          this.loadUnits();
-        },
-        error: () => {
-          this.feedback.error('Erro ao excluir unidade');
-        },
-      });
-    });
+    .pipe(
+      filter((confirmed) => confirmed),
+      switchMap(() => this.unitService.deleteUnit(id))
+    )
+    .subscribe({
+      next: () => {
+        this.feedback.success('Unidade excluída com sucesso');
+        this.loadUnits();
+      },
+      error: () => {
+        this.feedback.error('Erro ao excluir unidade');
+      },
+    });
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/unit/unit.component.ts` around lines 121 -
141, Refactor the nested subscribes in deleteUnit to use RxJS operators: have
confirmDialog.open(...) return an observable piped through filter(Boolean) to
only continue when confirmed, then switchMap to unitService.deleteUnit(id) and
subscribe to handle next/error (calling feedback.success, loadUnits,
feedback.error). Import filter and switchMap from 'rxjs' and remove the inner
subscribe; keep function name deleteUnit and calls to confirmDialog.open,
unitService.deleteUnit, loadUnits, feedback.success, and feedback.error
unchanged.
frontend/src/app/list/components/items-management/items-management.component.ts (1)

135-153: Consider using RxJS operators to flatten nested subscriptions.

The current pattern subscribes inside another subscription. While both observables complete (no memory leak), using RxJS operators improves readability and follows reactive best practices.

♻️ Proposed refactor using filter and switchMap
+import { filter, switchMap } from 'rxjs';
 deleteItem(item: ItemResponseDTO): void {
   this.confirmDialog
     .open({
       title: 'Excluir item',
       message: `Tem certeza que deseja excluir o item "${item.name}"?`,
       confirmText: 'Excluir',
     })
-    .subscribe((confirmed) => {
-      if (!confirmed) return;
-
-      this.itemService.deleteItem(item.id).subscribe({
-        next: () => {
-          this.loadData();
-          this.feedback.success('Item excluído com sucesso');
-        },
-        error: () => {
-          this.feedback.error('Erro ao excluir item');
-        },
-      });
+    .pipe(
+      filter((confirmed) => confirmed),
+      switchMap(() => this.itemService.deleteItem(item.id))
+    )
+    .subscribe({
+      next: () => {
+        this.loadData();
+        this.feedback.success('Item excluído com sucesso');
+      },
+      error: () => {
+        this.feedback.error('Erro ao excluir item');
+      },
     });
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/items-management/items-management.component.ts`
around lines 135 - 153, The nested subscription should be flattened: instead of
subscribing inside confirmDialog.open(...).subscribe(...), pipe the
confirmDialog.open(...) observable through operators (e.g., filter to keep only
confirmed results and switchMap to call itemService.deleteItem(item.id)), then
subscribe once to handle next (call loadData and feedback.success) and error
(feedback.error); reference confirmDialog.open, itemService.deleteItem,
loadData, and feedback.success/error when making the change.
frontend/src/app/shared/components/item/item.component.ts (2)

139-159: Consider flattening nested subscriptions with RxJS operators.

The nested subscription pattern (subscribing inside a subscribe callback) can be refactored using RxJS operators for better readability and maintainability. While there's no memory leak here since both observables complete naturally, the flattened approach is more idiomatic RxJS.

♻️ Proposed refactor using filter and switchMap
+import { filter, switchMap } from 'rxjs';
   deleteItem(id: number): void {
     this.confirmDialog
       .open({
         title: 'Excluir item',
         message: 'Tem certeza que deseja excluir este item?',
         confirmText: 'Excluir',
       })
-      .subscribe((confirmed) => {
-        if (!confirmed) return;
-
-        this.itemService.deleteItem(id).subscribe({
-          next: () => {
-            this.feedback.success('Item excluído com sucesso');
-            this.loadInitialData();
-          },
-          error: () => {
-            this.feedback.error('Erro ao excluir item');
-          },
-        });
+      .pipe(
+        filter((confirmed) => confirmed),
+        switchMap(() => this.itemService.deleteItem(id)),
+      )
+      .subscribe({
+        next: () => {
+          this.feedback.success('Item excluído com sucesso');
+          this.loadInitialData();
+        },
+        error: () => {
+          this.feedback.error('Erro ao excluir item');
+        },
       });
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/item/item.component.ts` around lines 139 -
159, The deleteItem method currently nests a subscription inside the
confirmDialog.open callback; refactor to flatten the stream by returning
confirmDialog.open(...) and piping it through RxJS operators (e.g., filter to
pass only confirmed values and switchMap/concatMap to call
itemService.deleteItem(id)), then subscribe once to handle next/error and call
feedback.success/feedback.error and loadInitialData from that single
subscription; update references: deleteItem, confirmDialog.open,
itemService.deleteItem, loadInitialData, feedback.success, feedback.error.

61-75: Consider using consistent dependency injection pattern.

The component mixes inject() function (lines 61-62) with constructor injection (lines 65-68). Both patterns work correctly, but using a consistent approach improves readability. The inject() pattern is the modern Angular style.

♻️ Optional: Migrate all dependencies to inject()
-  private confirmDialog = inject(ConfirmDialogService);
-  private feedback = inject(FeedbackService);
-
-  constructor(
-    private itemService: ItemService,
-    private categoryService: CategoryService,
-    private unitService: UnitService,
-    private fb: FormBuilder,
-  ) {
+  private readonly confirmDialog = inject(ConfirmDialogService);
+  private readonly feedback = inject(FeedbackService);
+  private readonly itemService = inject(ItemService);
+  private readonly categoryService = inject(CategoryService);
+  private readonly unitService = inject(UnitService);
+  private readonly fb = inject(FormBuilder);
+
+  constructor() {
     this.itemForm = this.fb.group({
       name: ['', [Validators.required, Validators.minLength(2)]],
       idCategory: ['', Validators.required],
       idUnit: ['', Validators.required],
     });
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/item/item.component.ts` around lines 61 -
75, The component currently mixes inject() for confirmDialog/feedback with
constructor injection for ItemService, CategoryService, UnitService and
FormBuilder; make the injection style consistent by replacing the constructor
parameters with inject() calls: add private itemService = inject(ItemService),
private categoryService = inject(CategoryService), private unitService =
inject(UnitService), and private fb = inject(FormBuilder), remove those
parameters from the constructor, and keep/remove the empty constructor body;
then ensure itemForm (this.itemForm) is initialized using the injected fb
(either inline or in the constructor body) so references to itemService,
categoryService, unitService, fb, confirmDialog and feedback all use the same
inject() pattern.
frontend/src/app/auth/login/login.component.ts (1)

73-80: Use the shared error helper instead of re-specifying snackbar config here.

This still hard-codes panelClass and duration in the component, so any future change to error feedback has to be updated in multiple places again. Prefer routing this through FeedbackService.error(...) so the auth screens stay aligned with the centralized feedback API.

Possible direction
this.feedback.error(
  error.message || 'Falha ao fazer login. Verifique suas credenciais.',
);

If you need the 5s duration specifically, consider extending FeedbackService.error() to accept optional overrides and keep that policy centralized.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/auth/login/login.component.ts` around lines 73 - 80, Replace
the direct call to this.feedback.notify(...) in LoginComponent with the shared
error helper to centralize snackbar styling and duration; specifically, swap the
notify invocation in login.component.ts to this.feedback.error(error.message ||
'Falha ao fazer login. Verifique suas credenciais.'); if you must preserve a 5s
override, update FeedbackService.error to accept an optional options parameter
(e.g., duration/panelClass) and call it from LoginComponent with that override
instead of hard-coding panelClass/duration locally.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/src/app/list/components/items-management/items-management.component.ts`:
- Line 147: In ItemsManagementComponent locate the this.feedback.success call
that currently logs "Item excluido com sucesso" and fix the typo by updating the
message to include the accent (use "Item excluído com sucesso"); ensure you
update the single string passed to this.feedback.success so the success
notification displays the correct Portuguese spelling.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`:
- Line 72: Remove the unused class field declaration "snackBar: any;" from the
ListShareDialogComponent (the leftover field in list-share-dialog.component.ts)
to satisfy `@typescript-eslint/no-explicit-any` and cleanup after the
FeedbackService migration; locate the declaration inside the component class and
delete that single line so no other references are affected.

In `@frontend/src/app/list/components/shopping-list/shopping-list.component.ts`:
- Around line 101-104: The success message is shown before the UI state is
updated, so remove the deleted item from the component's local state first
(e.g., update the shopping lists array maintained by ShoppingListComponent),
then call feedback.success('Lista excluida com sucesso') and finally invoke
loadLists() for a full refresh; locate the HTTP call in
shoppingListService.deleteShoppingList and the subscriber in
ShoppingListComponent (the delete handler that currently calls loadLists()),
update the local collection (e.g., this.shoppingLists =
this.shoppingLists.filter(...) or splice by id) on next, and handle errors in
error: to restore state or show a failure message if needed.

In `@frontend/src/app/shared/components/item/item.component.ts`:
- Line 151: The success message string passed to this.feedback.success contains
a typo: "Item excluido com sucesso" should use the accented "í". Update the
literal in the call to this.feedback.success (in ItemComponent /
item.component.ts) to "Item excluído com sucesso" so the Portuguese message is
correct.

---

Outside diff comments:
In `@frontend/src/app/auth/signup/signup.component.ts`:
- Around line 78-82: The signup failure path is calling
this.feedback.notify(...) which bypasses the standardized error styling; replace
that call with the FeedbackService error method (e.g., this.feedback.error(...))
used elsewhere so the error-snackbar styling and consistent presentation are
preserved. Update the call in signup.component.ts (the block handling signup
failure) to invoke the same signature/parameters as FeedbackService.error and
remove the direct notify usage so styling/behavior matches other error flows.

In
`@frontend/src/app/list/components/categories-management/categories-management.component.ts`:
- Around line 48-59: loadCategories() currently always surfaces an error via
feedback.error when the refetch fails, which causes conflicting UI messages
after a delete that calls loadCategories(); modify the refresh path so delete
success does not trigger user-facing error feedback: either (a) update the local
signal this.categories (or remove the deleted item from this.categories)
immediately in the delete success handler and then call a silent refresh that
suppresses feedback.error from categoryService.getAllCategories() (e.g., add a
boolean silent flag to loadCategories() that skips feedback on error), or (b)
have loadCategories() detect a silent refresh parameter and only set
this.isLoading/feedback on non-silent calls; reference loadCategories(),
categoryService.getAllCategories(), and feedback.error to implement the
silent-refresh or immediate local update approach.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`:
- Around line 118-129: The code uses a non-null assertion on user.id when
building the request in the ListShareDialog component; instead, guard that id is
present before calling addListPermission: after finding user via users(), check
if user.id is defined, show the existing feedback.error (or a new message) and
return if missing, then build the request using user.id (no !) and call
addListPermission; update any references in the submit/share handler (e.g., the
method that constructs request and calls addListPermission) to perform this
guard so an undefined id is never sent to the API.

In `@frontend/src/app/shared/components/category/category.component.ts`:
- Around line 82-100: The success message re-evaluates editingCategoryId()
inside the async subscribe next handler which can be different if the form
changed before the response returns; capture the edit state once before making
the request (e.g. const isEditing = this.editingCategoryId() !== null), use that
to set categoryData.id if needed and to decide which service method to call
(operation) and then use isEditing inside the subscribe next callback to pick
the correct success text; update references to editingCategoryId(),
categoryData, operation, and the next handler accordingly.
- Around line 65-76: loadCategories() currently always shows feedback.error on
any fetch failure which causes confusing UX when it’s used as a follow-up
refresh after a successful create/update/delete; change loadCategories signature
to accept an optional flag (e.g., suppressError?: boolean or silent?: boolean)
and use that flag to avoid showing the global error message on silent refreshes,
only log or show a refresh-specific message when not silent; update all callers
(including the create/update/delete follow-ups referenced at the other
occurrences) to call loadCategories(true) for background refreshes and leave
default behavior for direct user-initiated loads, and ensure
isLoading.set(false) is still executed in both success and error paths.

---

Nitpick comments:
In `@frontend/src/app/auth/login/login.component.ts`:
- Around line 73-80: Replace the direct call to this.feedback.notify(...) in
LoginComponent with the shared error helper to centralize snackbar styling and
duration; specifically, swap the notify invocation in login.component.ts to
this.feedback.error(error.message || 'Falha ao fazer login. Verifique suas
credenciais.'); if you must preserve a 5s override, update FeedbackService.error
to accept an optional options parameter (e.g., duration/panelClass) and call it
from LoginComponent with that override instead of hard-coding
panelClass/duration locally.

In
`@frontend/src/app/list/components/items-management/items-management.component.ts`:
- Around line 135-153: The nested subscription should be flattened: instead of
subscribing inside confirmDialog.open(...).subscribe(...), pipe the
confirmDialog.open(...) observable through operators (e.g., filter to keep only
confirmed results and switchMap to call itemService.deleteItem(item.id)), then
subscribe once to handle next (call loadData and feedback.success) and error
(feedback.error); reference confirmDialog.open, itemService.deleteItem,
loadData, and feedback.success/error when making the change.

In `@frontend/src/app/shared/components/item/item.component.ts`:
- Around line 139-159: The deleteItem method currently nests a subscription
inside the confirmDialog.open callback; refactor to flatten the stream by
returning confirmDialog.open(...) and piping it through RxJS operators (e.g.,
filter to pass only confirmed values and switchMap/concatMap to call
itemService.deleteItem(id)), then subscribe once to handle next/error and call
feedback.success/feedback.error and loadInitialData from that single
subscription; update references: deleteItem, confirmDialog.open,
itemService.deleteItem, loadInitialData, feedback.success, feedback.error.
- Around line 61-75: The component currently mixes inject() for
confirmDialog/feedback with constructor injection for ItemService,
CategoryService, UnitService and FormBuilder; make the injection style
consistent by replacing the constructor parameters with inject() calls: add
private itemService = inject(ItemService), private categoryService =
inject(CategoryService), private unitService = inject(UnitService), and private
fb = inject(FormBuilder), remove those parameters from the constructor, and
keep/remove the empty constructor body; then ensure itemForm (this.itemForm) is
initialized using the injected fb (either inline or in the constructor body) so
references to itemService, categoryService, unitService, fb, confirmDialog and
feedback all use the same inject() pattern.

In `@frontend/src/app/shared/components/unit/unit.component.ts`:
- Around line 49-55: The component mixes inject() calls for confirmDialog and
feedback with constructor-based injection for UnitService and FormBuilder; pick
one style and apply it consistently (either move confirmDialog and feedback into
the constructor or convert unitService and fb to use inject()). Locate the class
where confirmDialog and feedback are declared and the constructor that accepts
UnitService and FormBuilder (e.g., the UnitComponent class) and refactor so all
dependencies use the same approach, updating property declarations accordingly
and removing any now-unused constructor parameters or inject() calls.
- Around line 121-141: Refactor the nested subscribes in deleteUnit to use RxJS
operators: have confirmDialog.open(...) return an observable piped through
filter(Boolean) to only continue when confirmed, then switchMap to
unitService.deleteUnit(id) and subscribe to handle next/error (calling
feedback.success, loadUnits, feedback.error). Import filter and switchMap from
'rxjs' and remove the inner subscribe; keep function name deleteUnit and calls
to confirmDialog.open, unitService.deleteUnit, loadUnits, feedback.success, and
feedback.error unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b6043d3b-8c33-4c52-bc1a-2fe5a2c1d1d0

📥 Commits

Reviewing files that changed from the base of the PR and between 88ac529 and f4e963e.

📒 Files selected for processing (15)
  • frontend/src/app/auth/login/login.component.ts
  • frontend/src/app/auth/signup/signup.component.ts
  • frontend/src/app/list/components/categories-management/categories-management.component.ts
  • frontend/src/app/list/components/category-dialog/category-dialog.component.ts
  • frontend/src/app/list/components/items-management/items-management.component.ts
  • frontend/src/app/list/components/list-details/list-details.component.ts
  • frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts
  • frontend/src/app/list/components/shopping-list-dialog/shopping-list-dialog.component.ts
  • frontend/src/app/list/components/shopping-list/shopping-list.component.ts
  • frontend/src/app/list/components/units-management/units-management.component.ts
  • frontend/src/app/shared/components/category/category.component.ts
  • frontend/src/app/shared/components/item/item.component.ts
  • frontend/src/app/shared/components/list-item/list-item.component.ts
  • frontend/src/app/shared/components/unit/unit.component.ts
  • frontend/src/app/shared/services/feedback.service.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • frontend/src/app/list/components/list-details/list-details.component.ts
  • frontend/src/app/list/components/category-dialog/category-dialog.component.ts
  • frontend/src/app/shared/components/list-item/list-item.component.ts
  • frontend/src/app/list/components/units-management/units-management.component.ts
  • frontend/src/app/shared/services/feedback.service.ts
  • frontend/src/app/list/components/shopping-list-dialog/shopping-list-dialog.component.ts

Comment thread frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts Outdated
Comment thread frontend/src/app/shared/components/item/item.component.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @matheusandre1, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @coderabbitai[bot], I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot]: Thanks for the update! I'll keep an eye on the workflow progress. Once the run completes, the review results will be posted on this PR. 🚀

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @coderabbitai[bot], but I was unable to process your request. Please see the logs for more details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

@omatheusmesmo — Thanks for the notification. The workflow failure is expected at this stage. The review cannot be completed because the PR is still in draft status and has unresolved merge conflicts on the issue37 branch.

Here's the recommended path forward:

  1. @matheusandre1: Please rebase or merge the develop branch into issue37 and resolve all conflicts.
  2. Once the conflicts are resolved, mark the PR as ready for review (or ping me again if you'd like to keep it as a draft).
  3. I'll then trigger a fresh, full review automatically.

No further action is needed on my end until the conflicts are cleared. 🙌

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts (1)

104-121: ⚠️ Potential issue | 🟠 Major

Don't treat an empty user cache as "user not found".

If getAllUsers() is still loading, or failed earlier, this.users() is empty and every valid email falls into the "Usuario nao encontrado" branch. Gate onShare() on a loaded user list, or show a distinct "users unavailable" message instead of a false negative.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`
around lines 104 - 121, The current onShare() treats an empty this.users() as
"user not found" which produces false negatives when loadUsers() is still
loading or previously failed; modify loadUsers() to maintain a usersLoaded flag
(or similar) and set it true in the next callback and false in error, and update
onShare() to first check usersLoaded (or this.users().length) and show a
distinct "users unavailable" feedback (or disable the share action) when the
list isn't loaded instead of treating it as not found; ensure references to
loadUsers(), userService.getAllUsers(), this.users, onShare(), shareForm are
updated accordingly.
🧹 Nitpick comments (1)
frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts (1)

145-165: Flatten the confirm/delete flow instead of nesting subscribes.

This works, but the nested subscription makes the async path harder to follow and extend. Composing the confirmation result into the delete request keeps the method linear and easier to maintain.

♻️ Suggested refactor
+import { EMPTY, switchMap } from 'rxjs';
+
  removePermission(permissionId: number): void {
    this.confirmDialog
      .open({
        title: 'Remover permissao',
        message: 'Tem certeza que deseja remover esta permissao?',
        confirmText: 'Remover',
      })
-      .subscribe((confirmed) => {
-        if (!confirmed) return;
-
-        this.listPermissionService
-          .deleteListPermission(this.data.listId, permissionId)
-          .subscribe({
-            next: () => {
-              this.feedback.success('Permissao removida com sucesso');
-              this.loadPermissions();
-            },
-            error: () => {
-              this.feedback.error('Erro ao remover permissao');
-            },
-          });
-      });
+      .pipe(
+        switchMap((confirmed) =>
+          confirmed
+            ? this.listPermissionService.deleteListPermission(
+                this.data.listId,
+                permissionId,
+              )
+            : EMPTY,
+        ),
+      )
+      .subscribe({
+        next: () => {
+          this.feedback.success('Permissao removida com sucesso');
+          this.loadPermissions();
+        },
+        error: () => {
+          this.feedback.error('Erro ao remover permissao');
+        },
+      });
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`
around lines 145 - 165, The confirm/delete flow nests subscriptions; refactor
confirmDialog.open(...) and the deleteListPermission(...) call into a single
observable chain: call this.confirmDialog.open({...}).pipe(filter(confirmed =>
!!confirmed), switchMap(() =>
this.listPermissionService.deleteListPermission(this.data.listId,
permissionId))).subscribe({ next: () => { this.feedback.success('Permissao
removida com sucesso'); this.loadPermissions(); }, error: () => {
this.feedback.error('Erro ao remover permissao'); } }); this keeps the logic
linear while still using confirmDialog.open,
listPermissionService.deleteListPermission, loadPermissions, and
feedback.success/error.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`:
- Around line 104-121: The current onShare() treats an empty this.users() as
"user not found" which produces false negatives when loadUsers() is still
loading or previously failed; modify loadUsers() to maintain a usersLoaded flag
(or similar) and set it true in the next callback and false in error, and update
onShare() to first check usersLoaded (or this.users().length) and show a
distinct "users unavailable" feedback (or disable the share action) when the
list isn't loaded instead of treating it as not found; ensure references to
loadUsers(), userService.getAllUsers(), this.users, onShare(), shareForm are
updated accordingly.

---

Nitpick comments:
In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`:
- Around line 145-165: The confirm/delete flow nests subscriptions; refactor
confirmDialog.open(...) and the deleteListPermission(...) call into a single
observable chain: call this.confirmDialog.open({...}).pipe(filter(confirmed =>
!!confirmed), switchMap(() =>
this.listPermissionService.deleteListPermission(this.data.listId,
permissionId))).subscribe({ next: () => { this.feedback.success('Permissao
removida com sucesso'); this.loadPermissions(); }, error: () => {
this.feedback.error('Erro ao remover permissao'); } }); this keeps the logic
linear while still using confirmDialog.open,
listPermissionService.deleteListPermission, loadPermissions, and
feedback.success/error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 881d3bcd-642d-416a-b991-029591eb99a5

📥 Commits

Reviewing files that changed from the base of the PR and between f4e963e and 713d4da.

📒 Files selected for processing (1)
  • frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @matheusandre1, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @matheusandre1, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @coderabbitai[bot], I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot]: Thanks for the update! I'll keep an eye on the workflow progress. Once the run completes, the review results will be posted on this PR. 🚀

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @coderabbitai[bot], but I was unable to process your request. Please see the logs for more details.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
frontend/src/app/shared/components/item/item.component.ts (2)

61-68: Minor: Inconsistent dependency injection style.

The component mixes inject() function (lines 61-62) with constructor-based DI (lines 65-68). Both work correctly, but consider using one style consistently for better maintainability.

♻️ Option: Use inject() for all services
-  private confirmDialog = inject(ConfirmDialogService);
-  private feedback = inject(FeedbackService);
-
-  constructor(
-    private itemService: ItemService,
-    private categoryService: CategoryService,
-    private unitService: UnitService,
-    private fb: FormBuilder,
-  ) {
+  private confirmDialog = inject(ConfirmDialogService);
+  private feedback = inject(FeedbackService);
+  private itemService = inject(ItemService);
+  private categoryService = inject(CategoryService);
+  private unitService = inject(UnitService);
+  private fb = inject(FormBuilder);
+
+  constructor() {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/item/item.component.ts` around lines 61 -
68, The component mixes inject() calls for ConfirmDialogService and
FeedbackService with constructor-based DI for ItemService, CategoryService,
UnitService and FormBuilder; make the injection style consistent by converting
the constructor-injected services to use inject() as well (replace usages of the
constructor and its parameters ItemService, CategoryService, UnitService,
FormBuilder with private fields assigned via inject(ItemService),
inject(CategoryService), inject(UnitService), inject(FormBuilder)), or
alternatively convert the two inject() calls into constructor parameters—ensure
all references to ConfirmDialogService, FeedbackService, ItemService,
CategoryService, UnitService, and FormBuilder are updated accordingly and remove
the now-unused constructor or inject variables.

139-159: Delete confirmation flow meets PR objectives.

The replacement of native confirm() with ConfirmDialogService satisfies the acceptance criteria. The typo fix from the previous review ("excluído") is correctly applied.

Consider flattening the nested subscriptions using switchMap for a more idiomatic RxJS approach:

♻️ Optional: Flatten nested subscriptions with switchMap
+import { filter, switchMap } from 'rxjs';
   deleteItem(id: number): void {
     this.confirmDialog
       .open({
         title: 'Excluir item',
         message: 'Tem certeza que deseja excluir este item?',
         confirmText: 'Excluir',
       })
-      .subscribe((confirmed) => {
-        if (!confirmed) return;
-
-        this.itemService.deleteItem(id).subscribe({
-          next: () => {
-            this.feedback.success('Item excluído com sucesso');
-            this.loadInitialData();
-          },
-          error: () => {
-            this.feedback.error('Erro ao excluir item');
-          },
-        });
+      .pipe(
+        filter((confirmed) => confirmed),
+        switchMap(() => this.itemService.deleteItem(id))
+      )
+      .subscribe({
+        next: () => {
+          this.feedback.success('Item excluído com sucesso');
+          this.loadInitialData();
+        },
+        error: () => {
+          this.feedback.error('Erro ao excluir item');
+        },
       });
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/item/item.component.ts` around lines 139 -
159, The nested subscription in deleteItem should be flattened: replace the
inner subscribe pattern by piping the confirmDialog.open() Observable into
switchMap and then into itemService.deleteItem(id), handling success and error
in the final subscription (or in tap/catchError) so you avoid subscribing inside
a subscribe; update the deleteItem method (referencing deleteItem,
confirmDialog.open, itemService.deleteItem, loadInitialData, feedback.success
and feedback.error) to use switchMap (and optionally catchError) to call
loadInitialData on success and show feedback messages on success/error.
frontend/src/app/list/components/items-management/items-management.component.ts (1)

92-102: Extract the repeated post-mutation feedback path.

These three handlers now duplicate the same loadData() + feedback pattern. A small helper would keep CRUD feedback behavior consistent and reduce drift as more actions are added.

♻️ Suggested refactor
+  private handleMutationSuccess(message: string): void {
+    this.loadData();
+    this.feedback.success(message);
+  }
+
+  private handleMutationError(message: string): void {
+    this.feedback.error(message);
+  }
+
   openAddItemDialog(): void {
     const dialogRef = this.dialog.open(ItemDialogComponent, {
       width: '400px',
       data: { item: null },
     });

     dialogRef.afterClosed().subscribe((result) => {
       if (result) {
         this.itemService.addItem(result).subscribe({
           next: () => {
-            this.loadData();
-            this.feedback.success('Item adicionado com sucesso');
+            this.handleMutationSuccess('Item adicionado com sucesso');
           },
           error: () => {
-            this.feedback.error('Erro ao adicionar item');
+            this.handleMutationError('Erro ao adicionar item');
           },
         });
       }
     });
   }
         this.itemService.updateItem(item.id, result).subscribe({
           next: () => {
-            this.loadData();
-            this.feedback.success('Item atualizado com sucesso');
+            this.handleMutationSuccess('Item atualizado com sucesso');
           },
           error: () => {
-            this.feedback.error('Erro ao atualizar item');
+            this.handleMutationError('Erro ao atualizar item');
           },
         });
         this.itemService.deleteItem(item.id).subscribe({
           next: () => {
-            this.loadData();
-            this.feedback.success('Item excluído com sucesso');
+            this.handleMutationSuccess('Item excluído com sucesso');
           },
           error: () => {
-            this.feedback.error('Erro ao excluir item');
+            this.handleMutationError('Erro ao excluir item');
           },
         });

Also applies to: 119-129, 144-152

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/items-management/items-management.component.ts`
around lines 92 - 102, The code repeats the same post-mutation sequence (calling
this.loadData() and showing success/error via this.feedback) in multiple places
(e.g., the dialogRef.afterClosed() callback that calls
this.itemService.addItem). Introduce a small helper on the component (e.g.,
applyMutation(observable, successMsg, errorMsg) or handleMutationResult) that
subscribes to the passed Observable, calls this.loadData() on next and invokes
this.feedback.success(successMsg) or this.feedback.error(errorMsg) on error;
then replace the inline subscribe blocks in addItem, editItem, deleteItem flows
(references: itemService.addItem, itemService.updateItem, itemService.deleteItem
and dialogRef.afterClosed callbacks) with calls to that helper to centralize the
pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@frontend/src/app/list/components/items-management/items-management.component.ts`:
- Around line 92-102: The code repeats the same post-mutation sequence (calling
this.loadData() and showing success/error via this.feedback) in multiple places
(e.g., the dialogRef.afterClosed() callback that calls
this.itemService.addItem). Introduce a small helper on the component (e.g.,
applyMutation(observable, successMsg, errorMsg) or handleMutationResult) that
subscribes to the passed Observable, calls this.loadData() on next and invokes
this.feedback.success(successMsg) or this.feedback.error(errorMsg) on error;
then replace the inline subscribe blocks in addItem, editItem, deleteItem flows
(references: itemService.addItem, itemService.updateItem, itemService.deleteItem
and dialogRef.afterClosed callbacks) with calls to that helper to centralize the
pattern.

In `@frontend/src/app/shared/components/item/item.component.ts`:
- Around line 61-68: The component mixes inject() calls for ConfirmDialogService
and FeedbackService with constructor-based DI for ItemService, CategoryService,
UnitService and FormBuilder; make the injection style consistent by converting
the constructor-injected services to use inject() as well (replace usages of the
constructor and its parameters ItemService, CategoryService, UnitService,
FormBuilder with private fields assigned via inject(ItemService),
inject(CategoryService), inject(UnitService), inject(FormBuilder)), or
alternatively convert the two inject() calls into constructor parameters—ensure
all references to ConfirmDialogService, FeedbackService, ItemService,
CategoryService, UnitService, and FormBuilder are updated accordingly and remove
the now-unused constructor or inject variables.
- Around line 139-159: The nested subscription in deleteItem should be
flattened: replace the inner subscribe pattern by piping the
confirmDialog.open() Observable into switchMap and then into
itemService.deleteItem(id), handling success and error in the final subscription
(or in tap/catchError) so you avoid subscribing inside a subscribe; update the
deleteItem method (referencing deleteItem, confirmDialog.open,
itemService.deleteItem, loadInitialData, feedback.success and feedback.error) to
use switchMap (and optionally catchError) to call loadInitialData on success and
show feedback messages on success/error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dd63de5b-3c79-4614-81d2-7618f30f0864

📥 Commits

Reviewing files that changed from the base of the PR and between 713d4da and 5cd3937.

📒 Files selected for processing (3)
  • frontend/src/app/list/components/items-management/items-management.component.ts
  • frontend/src/app/list/components/shopping-list/shopping-list.component.ts
  • frontend/src/app/shared/components/item/item.component.ts

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot] — Thanks for the notification. This workflow failure is expected given the current state of the PR.

Root cause: The PR is still in draft status with unresolved merge conflicts on the issue37 branch, which prevents the review workflow from completing successfully.

To unblock the review, @matheusandre1 needs to:

  1. Rebase or merge the develop branch into issue37.
  2. Resolve all merge conflicts.
  3. Push the resolved changes.

Once the conflicts are cleared, a fresh review can be triggered. No further action is needed on my end until then. 🙌

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/app/list/components/list-details/list-details.component.ts (1)

95-102: ⚠️ Potential issue | 🟠 Major

Add success feedback for item status updates.

This update path only reports errors; successful status toggles are silent, while other CRUD actions now show success messages. That breaks the PR goal of consistent operation feedback.

💡 Suggested patch
     this.listItemService
       .updateListItem(this.listId, item.idListItem, updatedItem)
       .subscribe({
-        next: () => this.loadData(),
+        next: () => {
+          this.loadData();
+          this.feedback.success('Status do item atualizado com sucesso');
+        },
         error: () => {
           this.feedback.error('Erro ao atualizar status do item');
         },
       });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/list/components/list-details/list-details.component.ts`
around lines 95 - 102, The updateListItem call in list-details.component.ts
currently only shows an error on failure; add a success feedback call in the
success branch so users get confirmation when a status toggle succeeds. Modify
the subscribe handlers on listItemService.updateListItem(this.listId,
item.idListItem, updatedItem) to call this.feedback.success('Item atualizado com
sucesso') (or the appropriate success message) inside the next handler before or
after invoking this.loadData(), and keep the existing error handler
this.feedback.error('Erro ao atualizar status do item').
♻️ Duplicate comments (4)
frontend/src/app/list/components/shopping-list/shopping-list.component.ts (1)

101-105: ⚠️ Potential issue | 🟠 Major

Update local state before showing delete success feedback.

Success is shown immediately after triggering reload; users can momentarily see stale UI with a success toast.

🐛 Suggested fix
         this.shoppingListService.deleteShoppingList(id).subscribe({
           next: () => {
-            this.loadLists();
-            this.feedback.success('Lista excluida com sucesso');
+            this.shoppingLists.update((lists) =>
+              lists.filter((list) => list.idList !== id),
+            );
+            this.feedback.success('Lista excluída com sucesso');
+            this.loadLists();
           },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/list/components/shopping-list/shopping-list.component.ts`
around lines 101 - 105, When handling deleteShoppingList(id) in the subscribe
next handler, remove the deleted item from the local collection
(this.shoppingLists) before calling feedback.success so the UI reflects the
deletion immediately; then call loadLists() or refresh if needed after updating
local state. Update the code around shoppingListService.deleteShoppingList,
next: (), feedback.success and loadLists to perform the optimistic local removal
(filter out the id) first, then show feedback.success('Lista excluida com
sucesso') and finally trigger loadLists() only if a full refresh is required.
frontend/src/app/shared/components/unit/unit.component.ts (1)

133-133: ⚠️ Potential issue | 🟡 Minor

Correct Portuguese spelling in success toast.

Use the accented form “excluída”.

✏️ Suggested fix
-            this.feedback.success('Unidade excluida com sucesso');
+            this.feedback.success('Unidade excluída com sucesso');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/unit/unit.component.ts` at line 133,
Update the success toast message in the UnitComponent where
this.feedback.success(...) is called to use the correct Portuguese accent:
replace the string "Unidade excluida com sucesso" with "Unidade excluída com
sucesso" (locate the call to this.feedback.success in unit.component.ts).
frontend/src/app/shared/components/category/category.component.ts (1)

130-130: ⚠️ Potential issue | 🟡 Minor

Fix accent in delete success message.

Use “excluída” instead of “excluida”.

✏️ Suggested fix
-            this.feedback.success('Categoria excluida com sucesso');
+            this.feedback.success('Categoria excluída com sucesso');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/shared/components/category/category.component.ts` at line
130, The success message string in CategoryComponent (where
this.feedback.success('Categoria excluida com sucesso') is called) has a missing
accent; update the literal to use the correct Portuguese spelling "Categoria
excluída com sucesso" so the UI shows the accented 'í' in the delete
confirmation message.
frontend/src/app/list/components/category-dialog/category-dialog.component.ts (1)

93-93: ⚠️ Potential issue | 🟡 Minor

Correct Portuguese orthography in error message.

This still shows “validacao” instead of “validação”.

✏️ Suggested fix
-        this.feedback.error('Erro ao carregar categorias para validacao');
+        this.feedback.error('Erro ao carregar categorias para validação');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/category-dialog/category-dialog.component.ts`
at line 93, Fix the Portuguese spelling in the error message inside
CategoryDialogComponent (the line calling this.feedback.error). Replace "Erro ao
carregar categorias para validacao" with the correctly accented "Erro ao
carregar categorias para validação" so the user-facing message uses proper
orthography.
🧹 Nitpick comments (1)
frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.html (1)

4-5: Add initial focus to the cancel button for safer UX.

For destructive confirmation dialogs, best practice is to focus the cancel button initially to prevent accidental confirmations via keyboard (e.g., pressing Enter). Use cdkFocusInitial on the cancel button.

♻️ Proposed fix
-  <button mat-button (click)="onCancel()">
+  <button mat-button cdkFocusInitial (click)="onCancel()">
     {{ data.cancelText ?? "Cancelar" }}
   </button>

Ensure A11yModule (from @angular/cdk/a11y) is imported in the component.

As per coding guidelines: "Accessibility Requirements - It MUST pass all AXE checks. It MUST follow all WCAG AA minimums, including focus management."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.html`
around lines 4 - 5, Add initial focus to the cancel button by adding the
cdkFocusInitial directive on the cancel button element in the
ConfirmDialogComponent template (the button that calls onCancel() and displays
data.cancelText ?? "Cancelar"); also ensure A11yModule from `@angular/cdk/a11y` is
imported into the NgModule that declares ConfirmDialogComponent so
cdkFocusInitial is available at runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/src/app/list/components/categories-management/categories-management.component.ts`:
- Around line 37-42: The component currently mixes constructor injection and the
project's inject() pattern—refactor CategoryService and MatDialog to use
Angular's inject() like the other two services: add import { inject } from
'@angular/core' and replace the constructor-based params with class properties
such as private categoryService = inject(CategoryService), private dialog =
inject(MatDialog), private confirmDialog = inject(ConfirmDialogService), and
private feedback = inject(FeedbackService); then remove the constructor entirely
so all four dependencies consistently use inject().

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`:
- Around line 98-99: Replace the unaccented Portuguese feedback strings passed
to this.feedback.error and this.feedback.success in list-share-dialog.component
(e.g., the messages used in the methods where this.feedback.error('Erro ao
carregar permissoes'), this.feedback.success('Permissoes atualizadas'), etc.)
with correctly accented versions (e.g., "Erro ao carregar permissões",
"Permissões atualizadas", "Permissão removida", "Não foi possível ...", etc.),
keeping the same message intent and interpolation; update all occurrences
referenced in the review (the calls around the this.feedback.* usages and
related success/error branches at the locations noted) so copy is consistent
across the component while leaving the surrounding logic (e.g.,
this.isLoading.set(false), error handling) unchanged.

In
`@frontend/src/app/list/components/shopping-list-dialog/shopping-list-dialog.component.ts`:
- Around line 76-77: Update the Portuguese error message string passed to
this.feedback.error in ShoppingListDialogComponent to include proper accents:
change "Usuario nao identificado. Por favor, faca login novamente." to "Usuário
não identificado. Por favor, faça login novamente." so the UX text is correctly
localized; locate the call to this.feedback.error in
shopping-list-dialog.component (the authentication error branch) and replace the
literal string accordingly.

In `@frontend/src/app/list/components/shopping-list/shopping-list.component.ts`:
- Around line 40-45: The constructor currently injects dependencies via
constructor parameters (ShoppingListService, MatDialog, ConfirmDialogService,
FeedbackService) which must be migrated to Angular's inject() pattern for
consistency; replace the constructor DI by removing those parameters and instead
create private readonly fields initialized with inject() (e.g., private readonly
shoppingListService = inject(ShoppingListService), private readonly dialog =
inject(MatDialog), private readonly confirmDialog =
inject(ConfirmDialogService), private readonly feedback =
inject(FeedbackService)) and ensure any usages of these fields in
ShoppingListComponent methods remain unchanged.

In
`@frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts`:
- Line 88: Replace the misspelled localized message in the unit dialog error
call: update the string passed to this.feedback.error in unit-dialog.component
(the call currently using 'Erro ao carregar unidades para validacao') to the
correct Portuguese form 'Erro ao carregar unidades para validação' so the
accented characters are used properly.

---

Outside diff comments:
In `@frontend/src/app/list/components/list-details/list-details.component.ts`:
- Around line 95-102: The updateListItem call in list-details.component.ts
currently only shows an error on failure; add a success feedback call in the
success branch so users get confirmation when a status toggle succeeds. Modify
the subscribe handlers on listItemService.updateListItem(this.listId,
item.idListItem, updatedItem) to call this.feedback.success('Item atualizado com
sucesso') (or the appropriate success message) inside the next handler before or
after invoking this.loadData(), and keep the existing error handler
this.feedback.error('Erro ao atualizar status do item').

---

Duplicate comments:
In
`@frontend/src/app/list/components/category-dialog/category-dialog.component.ts`:
- Line 93: Fix the Portuguese spelling in the error message inside
CategoryDialogComponent (the line calling this.feedback.error). Replace "Erro ao
carregar categorias para validacao" with the correctly accented "Erro ao
carregar categorias para validação" so the user-facing message uses proper
orthography.

In `@frontend/src/app/list/components/shopping-list/shopping-list.component.ts`:
- Around line 101-105: When handling deleteShoppingList(id) in the subscribe
next handler, remove the deleted item from the local collection
(this.shoppingLists) before calling feedback.success so the UI reflects the
deletion immediately; then call loadLists() or refresh if needed after updating
local state. Update the code around shoppingListService.deleteShoppingList,
next: (), feedback.success and loadLists to perform the optimistic local removal
(filter out the id) first, then show feedback.success('Lista excluida com
sucesso') and finally trigger loadLists() only if a full refresh is required.

In `@frontend/src/app/shared/components/category/category.component.ts`:
- Line 130: The success message string in CategoryComponent (where
this.feedback.success('Categoria excluida com sucesso') is called) has a missing
accent; update the literal to use the correct Portuguese spelling "Categoria
excluída com sucesso" so the UI shows the accented 'í' in the delete
confirmation message.

In `@frontend/src/app/shared/components/unit/unit.component.ts`:
- Line 133: Update the success toast message in the UnitComponent where
this.feedback.success(...) is called to use the correct Portuguese accent:
replace the string "Unidade excluida com sucesso" with "Unidade excluída com
sucesso" (locate the call to this.feedback.success in unit.component.ts).

---

Nitpick comments:
In
`@frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.html`:
- Around line 4-5: Add initial focus to the cancel button by adding the
cdkFocusInitial directive on the cancel button element in the
ConfirmDialogComponent template (the button that calls onCancel() and displays
data.cancelText ?? "Cancelar"); also ensure A11yModule from `@angular/cdk/a11y` is
imported into the NgModule that declares ConfirmDialogComponent so
cdkFocusInitial is available at runtime.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: af3dbda4-19c9-4984-ba83-4e4539c83b62

📥 Commits

Reviewing files that changed from the base of the PR and between 5cd3937 and 59d2927.

📒 Files selected for processing (20)
  • frontend/src/app/list/components/categories-management/categories-management.component.ts
  • frontend/src/app/list/components/category-dialog/category-dialog.component.ts
  • frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts
  • frontend/src/app/list/components/items-management/items-management.component.ts
  • frontend/src/app/list/components/list-details/list-details.component.ts
  • frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts
  • frontend/src/app/list/components/shopping-list-dialog/shopping-list-dialog.component.ts
  • frontend/src/app/list/components/shopping-list/shopping-list.component.ts
  • frontend/src/app/list/components/units-management/unit-dialog/unit-dialog.component.ts
  • frontend/src/app/list/components/units-management/units-management.component.ts
  • frontend/src/app/shared/components/category/category.component.ts
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.html
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.scss
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts
  • frontend/src/app/shared/components/item/item.component.ts
  • frontend/src/app/shared/components/list-item/list-item.component.ts
  • frontend/src/app/shared/components/unit/unit.component.ts
  • frontend/src/app/shared/services/confirm-dialog.service.ts
  • frontend/src/app/shared/services/feedback.service.ts
  • frontend/src/styles.scss
🚧 Files skipped from review as they are similar to previous changes (6)
  • frontend/src/app/list/components/units-management/units-management.component.ts
  • frontend/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts
  • frontend/src/app/shared/services/confirm-dialog.service.ts
  • frontend/src/app/list/components/items-management/items-management.component.ts
  • frontend/src/app/shared/components/list-item/list-item.component.ts
  • frontend/src/app/list/components/items-management/item-dialog/item-dialog.component.ts

Comment on lines +98 to 99
this.feedback.error('Erro ao carregar permissoes');
this.isLoading.set(false);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Polish Portuguese strings (accentuation) in user-facing feedback.

There are regressions in localized copy quality (missing accents), which reduces UX polish and consistency.

✏️ Suggested patch
-          this.feedback.error('Erro ao carregar permissoes');
+          this.feedback.error('Erro ao carregar permissões');
@@
-        this.feedback.error('Erro ao carregar usuarios');
+        this.feedback.error('Erro ao carregar usuários');
@@
-        this.feedback.error('Usuario nao encontrado com este e-mail');
+        this.feedback.error('Usuário não encontrado com este e-mail');
@@
-        title: 'Remover permissao',
-        message: 'Tem certeza que deseja remover esta permissao?',
+        title: 'Remover permissão',
+        message: 'Tem certeza que deseja remover esta permissão?',
@@
-              this.feedback.success('Permissao removida com sucesso');
+              this.feedback.success('Permissão removida com sucesso');
@@
-              this.feedback.error('Erro ao remover permissao');
+              this.feedback.error('Erro ao remover permissão');

Also applies to: 110-110, 121-121, 147-149, 158-163

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/list/components/list-share-dialog/list-share-dialog.component.ts`
around lines 98 - 99, Replace the unaccented Portuguese feedback strings passed
to this.feedback.error and this.feedback.success in list-share-dialog.component
(e.g., the messages used in the methods where this.feedback.error('Erro ao
carregar permissoes'), this.feedback.success('Permissoes atualizadas'), etc.)
with correctly accented versions (e.g., "Erro ao carregar permissões",
"Permissões atualizadas", "Permissão removida", "Não foi possível ...", etc.),
keeping the same message intent and interpolation; update all occurrences
referenced in the review (the calls around the this.feedback.* usages and
related success/error branches at the locations noted) so copy is consistent
across the component while leaving the surrounding logic (e.g.,
this.isLoading.set(false), error handling) unchanged.

Copy link
Copy Markdown
Owner

@omatheusmesmo omatheusmesmo left a comment

Choose a reason for hiding this comment

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

LGTM, @matheusandre1 ! Thanks.

@omatheusmesmo omatheusmesmo merged commit 60dfbc3 into omatheusmesmo:develop Mar 13, 2026
4 checks passed
@matheusandre1 matheusandre1 deleted the issue37 branch March 13, 2026 04:38
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.

UX: Improve operation feedback using SnackBars

2 participants