mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 1913: feat(remission): refactor return receipt details and extract shared actions
feat(remission): refactor return receipt details and extract shared actions Refactor remission return receipt details to use return-based data flow instead of individual receipt fetching. Extract reusable action components for better code organization and consistency. - Remove deprecated fetchRemissionReturnReceipt method and schema - Add helper functions for extracting data from return objects - Replace receipt-specific components with return-based equivalents - Create shared return-receipt-actions library with reusable components - Update components to use modern Angular patterns (signals, computed) - Improve data flow consistency across remission features - Add comprehensive test coverage for new components - Update eager loading support in fetch return functionality The new architecture provides better data consistency and reduces code duplication by centralizing receipt actions and data extraction logic into reusable components. Refs: #5242, #5138, #5232, #5241
This commit is contained in:
committed by
Andreas Schickinger
parent
2e012a124a
commit
99e8e7cfe0
@@ -1,17 +1,24 @@
|
||||
<div class="w-full flex flex-row justify-between items-start">
|
||||
<filter-search-bar-input
|
||||
class="flex flex-row gap-4 h-12"
|
||||
[appearance]="'results'"
|
||||
inputKey="qs"
|
||||
(triggerSearch)="triggerSearch.emit($event)"
|
||||
data-what="search-input"
|
||||
></filter-search-bar-input>
|
||||
<div
|
||||
class="w-full flex flex-row justify-between items-start"
|
||||
[class.empty-filter-input]="!hasFilter() && !hasInput()"
|
||||
>
|
||||
@if (hasInput()) {
|
||||
<filter-search-bar-input
|
||||
class="flex flex-row gap-4 h-12"
|
||||
[appearance]="'results'"
|
||||
[inputKey]="inputKey()"
|
||||
(triggerSearch)="triggerSearch.emit($event)"
|
||||
data-what="search-input"
|
||||
></filter-search-bar-input>
|
||||
}
|
||||
|
||||
<div class="flex flex-row gap-4 items-center">
|
||||
<filter-filter-menu-button
|
||||
(applied)="triggerSearch.emit('filter')"
|
||||
[rollbackOnClose]="true"
|
||||
></filter-filter-menu-button>
|
||||
@if (hasFilter()) {
|
||||
<filter-filter-menu-button
|
||||
(applied)="triggerSearch.emit('filter')"
|
||||
[rollbackOnClose]="true"
|
||||
></filter-filter-menu-button>
|
||||
}
|
||||
|
||||
@if (mobileBreakpoint()) {
|
||||
<ui-icon-button
|
||||
@@ -23,7 +30,9 @@
|
||||
></ui-icon-button>
|
||||
} @else {
|
||||
<filter-order-by-toolbar
|
||||
[class.empty-filter-input-width]="!hasFilter() && !hasInput()"
|
||||
(toggled)="triggerSearch.emit('order-by')"
|
||||
data-what="sort-toolbar"
|
||||
></filter-order-by-toolbar>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
.filter-controls-panel {
|
||||
@apply flex flex-col gap-4;
|
||||
@apply w-full flex flex-col gap-4;
|
||||
}
|
||||
|
||||
.empty-filter-input {
|
||||
@apply justify-end;
|
||||
}
|
||||
|
||||
.empty-filter-input-width {
|
||||
@apply w-[44.375rem];
|
||||
}
|
||||
|
||||
@@ -1,32 +1,36 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
inject,
|
||||
linkedSignal,
|
||||
output,
|
||||
signal,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { SearchBarInputComponent } from '../inputs';
|
||||
import { FilterMenuButtonComponent } from '../menus/filter-menu';
|
||||
import { provideIcons } from '@ng-icons/core';
|
||||
import { isaActionFilter, isaActionSort } from '@isa/icons';
|
||||
import { IconButtonComponent } from '@isa/ui/buttons';
|
||||
import { OrderByToolbarComponent } from '../order-by';
|
||||
import { Breakpoint, breakpoint } from '@isa/ui/layout';
|
||||
import { SearchTrigger } from '../types';
|
||||
import { InputType, SearchTrigger } from '../types';
|
||||
import { FilterService, TextFilterInput } from '../core';
|
||||
import { SearchBarInputComponent } from '../inputs';
|
||||
|
||||
/**
|
||||
* Filter controls panel component that provides a unified interface for search and filtering operations.
|
||||
*
|
||||
*
|
||||
* This component combines search input, filter menu, and sorting controls into a responsive panel.
|
||||
* It adapts its layout based on screen size, showing/hiding controls appropriately for mobile and desktop views.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```html
|
||||
* <filter-controls-panel
|
||||
* <filter-controls-panel
|
||||
* (triggerSearch)="handleSearch($event)">
|
||||
* </filter-controls-panel>
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Responsive design that adapts to mobile/desktop layouts
|
||||
* - Integrated search bar with scanner support
|
||||
@@ -53,11 +57,22 @@ import { SearchTrigger } from '../types';
|
||||
providers: [provideIcons({ isaActionSort, isaActionFilter })],
|
||||
})
|
||||
export class FilterControlsPanelComponent {
|
||||
/**
|
||||
* Service for managing filter state and operations.
|
||||
*/
|
||||
#filterService = inject(FilterService);
|
||||
|
||||
/**
|
||||
* The unique key identifier for this input in the filter system.
|
||||
* @default 'qs'
|
||||
*/
|
||||
inputKey = signal('qs');
|
||||
|
||||
/**
|
||||
* Output event that emits when any search action is triggered.
|
||||
* Provides the specific SearchTrigger type to indicate how the search was initiated:
|
||||
* - 'input': Text input or search button
|
||||
* - 'filter': Filter menu changes
|
||||
* - 'filter': Filter menu changes
|
||||
* - 'order-by': Sort order changes
|
||||
* - 'scan': Barcode scan
|
||||
*/
|
||||
@@ -75,4 +90,26 @@ export class FilterControlsPanelComponent {
|
||||
* Linked to mobileBreakpoint to automatically adjust when screen size changes.
|
||||
*/
|
||||
showOrderByToolbarMobile = linkedSignal(() => !this.mobileBreakpoint());
|
||||
|
||||
/**
|
||||
* Computed signal that determines if the search input is present in the filter inputs.
|
||||
* This checks if there is a TextFilterInput with the specified inputKey.
|
||||
* Used to conditionally render the search input in the template.
|
||||
*/
|
||||
hasInput = computed(() => {
|
||||
const inputs = this.#filterService.inputs();
|
||||
const input = inputs.find(
|
||||
(input) => input.key === this.inputKey() && input.type === InputType.Text,
|
||||
) as TextFilterInput;
|
||||
return !!input;
|
||||
});
|
||||
|
||||
/**
|
||||
* Computed signal that checks if there are any active filters applied.
|
||||
* This is determined by checking if there are any inputs of types other than Text.
|
||||
*/
|
||||
hasFilter = computed(() => {
|
||||
const inputs = this.#filterService.inputs();
|
||||
return inputs.some((input) => input.type !== InputType.Text);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user