mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 1972: hotfix(remission-list-item, remission-list-empty-state): improve empty state...
hotfix(remission-list-item, remission-list-empty-state): improve empty state logic and cleanup selected items on destroy Refactor empty state display conditions in remission-list-empty-state component to correctly handle search term validation. Move hasValidSearchTerm check to parent condition to prevent displaying empty states during active searches. Add ngOnDestroy lifecycle hook to remission-list-item component to properly clean up selected quantities from the store when items are removed from the list. This prevents memory leaks and ensures the store state remains synchronized with the displayed items. Changes: - Move hasValidSearchTerm check in displayEmptyState computed signal to improve empty state display logic - Implement OnDestroy interface in RemissionListItemComponent - Add removeItem call in ngOnDestroy to clean up store state - Add corresponding unit tests for the cleanup behavior Ref: #5387
This commit is contained in:
committed by
Lorenz Hilpert
parent
a086111ab5
commit
4c56f394c5
@@ -49,7 +49,7 @@ export class RemissionListEmptyStateComponent {
|
||||
* @remarks This logic ensures that the most relevant empty state is shown to the user based on their current context.
|
||||
*/
|
||||
displayEmptyState = computed<EmptyState>(() => {
|
||||
if (!this.listFetching()) {
|
||||
if (!this.listFetching() && !this.hasValidSearchTerm()) {
|
||||
// Prio 1: Abteilungsremission - Es ist noch keine Abteilung ausgewählt
|
||||
if (
|
||||
this.isDepartment() &&
|
||||
@@ -65,7 +65,6 @@ export class RemissionListEmptyStateComponent {
|
||||
|
||||
// Prio 2: Liste abgearbeitet und keine Artikel mehr vorhanden
|
||||
if (
|
||||
!this.hasValidSearchTerm() &&
|
||||
this.hits() === 0 &&
|
||||
this.isReloadSearch()
|
||||
) {
|
||||
@@ -77,7 +76,7 @@ export class RemissionListEmptyStateComponent {
|
||||
}
|
||||
|
||||
// Prio 3: Keine Ergebnisse bei leerem Suchbegriff (nur Filter gesetzt)
|
||||
if (!this.hasValidSearchTerm() && this.hits() === 0) {
|
||||
if (this.hits() === 0) {
|
||||
return {
|
||||
title: 'Keine Suchergebnisse',
|
||||
description:
|
||||
|
||||
@@ -46,6 +46,7 @@ jest.mock('@isa/remission/data-access', () => ({
|
||||
// Mock the RemissionStore
|
||||
const mockRemissionStore = {
|
||||
selectedQuantity: signal({}),
|
||||
removeItem: jest.fn(),
|
||||
};
|
||||
|
||||
describe('RemissionListItemComponent', () => {
|
||||
@@ -112,6 +113,7 @@ describe('RemissionListItemComponent', () => {
|
||||
// Reset mocks before each test
|
||||
jest.clearAllMocks();
|
||||
mockRemissionStore.selectedQuantity.set({});
|
||||
mockRemissionStore.removeItem.mockClear();
|
||||
|
||||
// Reset the mocked functions to return default values
|
||||
const {
|
||||
@@ -712,4 +714,37 @@ describe('RemissionListItemComponent', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngOnDestroy', () => {
|
||||
it('should remove item from store when component is destroyed', () => {
|
||||
// Arrange
|
||||
const mockItem = createMockReturnItem({ id: 123 });
|
||||
|
||||
fixture.componentRef.setInput('item', mockItem);
|
||||
fixture.componentRef.setInput('stock', createMockStockInfo());
|
||||
fixture.detectChanges();
|
||||
|
||||
// Act
|
||||
component.ngOnDestroy();
|
||||
|
||||
// Assert
|
||||
expect(mockRemissionStore.removeItem).toHaveBeenCalledWith(123);
|
||||
expect(mockRemissionStore.removeItem).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not call removeItem when item has no id', () => {
|
||||
// Arrange
|
||||
const mockItem = createMockReturnItem({ id: undefined });
|
||||
|
||||
fixture.componentRef.setInput('item', mockItem);
|
||||
fixture.componentRef.setInput('stock', createMockStockInfo());
|
||||
fixture.detectChanges();
|
||||
|
||||
// Act
|
||||
component.ngOnDestroy();
|
||||
|
||||
// Assert
|
||||
expect(mockRemissionStore.removeItem).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
computed,
|
||||
inject,
|
||||
input,
|
||||
OnDestroy,
|
||||
output,
|
||||
} from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -60,7 +61,7 @@ import { LabelComponent, Labeltype } from '@isa/ui/label';
|
||||
LabelComponent,
|
||||
],
|
||||
})
|
||||
export class RemissionListItemComponent {
|
||||
export class RemissionListItemComponent implements OnDestroy {
|
||||
/**
|
||||
* Type of label to display for the item.
|
||||
* Defaults to 'tag', can be changed to 'notice' or other types as needed.
|
||||
@@ -219,4 +220,16 @@ export class RemissionListItemComponent {
|
||||
const attempts = this.item()?.impediment?.attempts;
|
||||
return `${comment}${attempts ? ` (${attempts})` : ''}`;
|
||||
});
|
||||
|
||||
/**
|
||||
* Cleans up the selected item from the store when the component is destroyed.
|
||||
* Removes the item using its ID.
|
||||
* @returns void
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
const itemId = this.item()?.id;
|
||||
if (itemId) {
|
||||
this.#store.removeItem(itemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user