From c5d057e3a723b5911041e79aa62c3b5a6eb02238 Mon Sep 17 00:00:00 2001 From: Lorenz Hilpert Date: Tue, 16 Sep 2025 09:54:29 +0000 Subject: [PATCH] Merged PR 1950: 5343-Filter-NumberRange Related work items: #5343 --- .github/prompts/plan.prompt.md | 185 ++++++++++++ CLAUDE.md | 148 +++++++++ .../ui/input-controls/inline-input.stories.ts | 59 ++++ libs/checkout/data-access/project.json | 2 +- .../src/lib/reward-catalog.component.html | 140 ++++----- .../filter/src/lib/core/filter.service.ts | 79 ++++- .../filter-input-to-record.mapping.ts | 9 + .../mappings/filter-input.mapping.spec.ts | 18 -- .../lib/core/mappings/filter-input.mapping.ts | 61 ++-- .../src/lib/core/mappings/filter.mapping.ts | 10 +- .../number-range-filter-input.mapping.ts | 32 ++ .../lib/core/schemas/filter-input.schema.ts | 44 +-- .../filter/src/lib/core/schemas/index.ts | 25 +- .../number-range-filter-input.schema.ts | 31 ++ .../input-renderer.component.html | 34 ++- .../input-renderer.component.ts | 59 ++-- .../lib/inputs/number-range-input/index.ts | 1 + .../number-range-input.component.html | 43 +++ .../number-range-input.component.scss | 7 + .../number-range-input.component.ts | 87 ++++++ libs/shared/filter/src/lib/types.ts | 3 +- libs/ui/input-controls/src/index.ts | 33 ++- .../ui/input-controls/src/input-controls.scss | 1 + .../src/lib/inline-input/_inline-input.scss | 47 +++ .../inline-input/inline-input.component.html | 1 + .../inline-input/inline-input.component.ts | 39 +++ tsconfig.base.json | 280 +++++++++--------- 27 files changed, 1117 insertions(+), 361 deletions(-) create mode 100644 .github/prompts/plan.prompt.md create mode 100644 CLAUDE.md create mode 100644 apps/isa-app/stories/ui/input-controls/inline-input.stories.ts create mode 100644 libs/shared/filter/src/lib/core/mappings/number-range-filter-input.mapping.ts create mode 100644 libs/shared/filter/src/lib/core/schemas/number-range-filter-input.schema.ts create mode 100644 libs/shared/filter/src/lib/inputs/number-range-input/index.ts create mode 100644 libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.html create mode 100644 libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.scss create mode 100644 libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.ts create mode 100644 libs/ui/input-controls/src/lib/inline-input/_inline-input.scss create mode 100644 libs/ui/input-controls/src/lib/inline-input/inline-input.component.html create mode 100644 libs/ui/input-controls/src/lib/inline-input/inline-input.component.ts diff --git a/.github/prompts/plan.prompt.md b/.github/prompts/plan.prompt.md new file mode 100644 index 000000000..df21a039c --- /dev/null +++ b/.github/prompts/plan.prompt.md @@ -0,0 +1,185 @@ +--- +mode: agent +tools: [ 'edit', 'search', 'usages', 'vscodeAPI', 'problems', 'changes', 'fetch', 'githubRepo', 'Nx Mcp Server', 'context7' ] +description: Plan Mode - Research and create a detailed implementation plan before making any changes. +--- + +# Plan Mode + +You are now operating in **Plan Mode** - a research and planning phase that ensures thorough analysis before implementation. Plan mode is **ALWAYS ACTIVE** when using this prompt. You must follow these strict guidelines for every request: + +## Phase 1: Research & Analysis (MANDATORY) + +### ALLOWED Operations: + +- ✅ Read files using Read, Glob, Grep tools +- ✅ Search documentation and codebases +- ✅ Analyze existing patterns and structures +- ✅ Use WebFetch for documentation research +- ✅ List and explore project structure +- ✅ Use Nx/Angular/Context7 MCP tools for workspace analysis +- ✅ Review dependencies and configurations + +### FORBIDDEN Operations: + +- ❌ **NEVER** create, edit, or modify any files +- ❌ **NEVER** run commands that change system state +- ❌ **NEVER** make commits or push changes +- ❌ **NEVER** install packages or modify configurations +- ❌ **NEVER** run build/test commands during planning + +## Phase 2: Plan Presentation (REQUIRED FORMAT) + +After thorough research, present your plan using this exact structure: + +```markdown +## 📋 Implementation Plan + +### 🎯 Objective + +[Clear statement of what will be accomplished] + +### 🔍 Research Summary + +- **Current State**: [What exists now] +- **Requirements**: [What needs to be built/changed] +- **Constraints**: [Limitations and considerations] + +### 📁 Files to be Modified/Created + +1. **File**: `path/to/file.ts` + + - **Action**: Create/Modify/Delete + - **Purpose**: [Why this file needs changes] + - **Key Changes**: [Specific modifications planned] + +2. **File**: `path/to/another-file.ts` + - **Action**: Create/Modify/Delete + - **Purpose**: [Why this file needs changes] + - **Key Changes**: [Specific modifications planned] + +### 🏗️ Implementation Steps + +1. **Step 1**: [Detailed description] + + - Files affected: `file1.ts`, `file2.ts` + - Rationale: [Why this step is necessary] + +2. **Step 2**: [Detailed description] + + - Files affected: `file3.ts` + - Rationale: [Why this step is necessary] + +3. **Step N**: [Continue numbering...] + +### ⚠️ Risks & Considerations + +- **Risk 1**: [Potential issue and mitigation] +- **Risk 2**: [Potential issue and mitigation] + +### 🧪 Testing Strategy + +- [How the changes will be tested] +- [Specific test files or approaches] + +### 📚 Architecture Decisions + +- **Pattern Used**: [Which architectural pattern will be followed] +- **Libraries/Dependencies**: [What will be used and why] +- **Integration Points**: [How this fits with existing code] + +### ✅ Success Criteria + +- [ ] Criterion 1 +- [ ] Criterion 2 +- [ ] All tests pass +- [ ] No lint errors +``` + +## Phase 3: Await Approval + +After presenting the plan: + +1. **STOP** all implementation activities +2. **WAIT** for explicit user approval +3. **DO NOT** proceed with any file changes +4. **RESPOND** to questions or plan modifications +5. **EXIT PLAN MODE** only when user explicitly says "execute", "implement", "go ahead", "approved", or similar approval language + +## Phase 4: Implementation (After Exiting Plan Mode) + +Once the user explicitly approves and you exit plan mode: + +1. **PLAN MODE IS NOW DISABLED** - you can proceed with normal implementation +2. Use TodoWrite to create implementation todos +3. Follow the plan step-by-step +4. Update todos as you progress +5. Run tests and lint checks as specified +6. Provide progress updates + +## Key Behavioral Rules + +### Research Thoroughly + +- Spend significant time understanding the codebase +- Look for existing patterns to follow +- Identify all dependencies and integration points +- Consider edge cases and error scenarios + +### Be Comprehensive + +- Plans should be detailed enough for another developer to implement +- Include all necessary file changes +- Consider testing, documentation, and deployment +- Address potential conflicts or breaking changes + +### Show Your Work + +- Explain reasoning behind architectural decisions +- Reference existing code patterns when applicable +- Cite documentation or best practices +- Provide alternatives when multiple approaches exist + +### Safety First + +- Never make changes during planning phase +- Always wait for explicit approval +- Flag potentially risky changes +- Suggest incremental implementation when complex + +## Example Interactions + +### Good Plan Mode Behavior: + +``` +User: "Add a dark mode toggle to the settings page" +Assistant: I'll research the current theming system and create a comprehensive plan for implementing dark mode. + +[Extensive research using Read, Grep, Glob tools] + +## 📋 Implementation Plan +[Follows complete format above] + +Ready to proceed? Please approve this plan before I begin implementation. +``` + +### What NOT to do: + +``` +User: "Add a dark mode toggle" +Assistant: I'll add that right away! +[Immediately starts editing files - WRONG!] +``` + +## Integration with Existing Copilot Instructions + +This plan mode respects all existing project patterns: + +- Follows Angular + Nx workspace conventions +- Uses existing import path aliases +- Respects testing strategy (Jest/Vitest) +- Follows NgRx Signals patterns +- Adheres to logging and configuration patterns +- Maintains library conventions and file naming + +Remember: **RESEARCH FIRST, PLAN THOROUGHLY, WAIT FOR APPROVAL, THEN IMPLEMENT** diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..b8fa2c95d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,148 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is an Angular monorepo managed by Nx. The main application is `isa-app`, which appears to be an inventory and returns management system for retail/e-commerce. + +## Architecture + +### Monorepo Structure +- **apps/isa-app**: Main Angular application +- **libs/**: Reusable libraries organized by domain and type + - **core/**: Core utilities (config, logging, storage, tabs) + - **common/**: Shared utilities (data-access, decorators, print) + - **ui/**: UI component libraries (buttons, dialogs, inputs, etc.) + - **shared/**: Shared domain components (filter, scanner, product components) + - **oms/**: Order Management System features and utilities + - **remission/**: Remission/returns management features + - **catalogue/**: Product catalogue functionality + - **utils/**: General utilities (validation, scroll position, parsing) + - **icons/**: Icon library +- **generated/swagger/**: Auto-generated API client code from OpenAPI specs + +### Key Architectural Patterns +- **Standalone Components**: Project uses Angular standalone components +- **Feature Libraries**: Domain features organized as separate libraries (e.g., `oms-feature-return-search`) +- **Data Access Layer**: Separate data-access libraries for each domain (e.g., `oms-data-access`, `remission-data-access`) +- **Shared UI Components**: Reusable UI components in `libs/ui/` +- **Generated API Clients**: Swagger/OpenAPI clients auto-generated in `generated/swagger/` + +## Common Development Commands + +### Build Commands +```bash +# Build the main application (development) +npx nx build isa-app --configuration=development + +# Build for production +npx nx build isa-app --configuration=production + +# Serve the application with SSL +npx nx serve isa-app --ssl +``` + +### Testing Commands +```bash +# Run tests for a specific library (always use --skip-cache) +npx nx run :test --skip-cache +# Example: npx nx run remission-data-access:test --skip-cache + +# Run tests for all libraries except the main app +npx nx run-many -t test --exclude isa-app --skip-cache + +# Run a single test file +npx nx run :test --testFile= --skip-cache + +# Run tests with coverage +npx nx run :test --code-coverage --skip-cache + +# Run tests in watch mode +npx nx run :test --watch +``` + +### Linting Commands +```bash +# Lint a specific project +npx nx lint +# Example: npx nx lint remission-data-access + +# Run linting for all projects +npx nx run-many -t lint +``` + +### Other Useful Commands +```bash +# Generate Swagger API clients +npm run generate:swagger + +# Start Storybook +npx nx run isa-app:storybook + +# Format code with Prettier +npm run prettier + +# List all projects in the workspace +npx nx list + +# Show project dependencies graph +npx nx graph + +# Run affected tests (based on git changes) +npx nx affected:test +``` + +## Testing Framework + +### Current Setup +- **Jest**: Primary test runner for existing libraries +- **Vitest**: Being adopted for new libraries (migration in progress) +- **Testing Utilities**: + - **Angular Testing Utilities** (TestBed, ComponentFixture): Use for new tests + - **Spectator**: Legacy testing utility for existing tests + - **ng-mocks**: For advanced mocking scenarios + +### Test File Requirements +- Test files must end with `.spec.ts` +- Use AAA pattern (Arrange-Act-Assert) +- Include E2E testing attributes (`data-what`, `data-which`) in HTML templates +- Mock external dependencies and child components + +## State Management +- **NgRx**: Store, Effects, Entity, Component Store, Signals +- **RxJS**: For reactive programming patterns + +## Styling +- **Tailwind CSS**: Primary styling framework with custom configuration +- **SCSS**: For component-specific styles +- **Custom Tailwind plugins**: For buttons, inputs, menus, typography + +## API Integration +- **Generated Swagger Clients**: Auto-generated TypeScript clients from OpenAPI specs +- **Available APIs**: availability, cat-search, checkout, crm, eis, inventory, isa, oms, print, wws + +## Build Configuration +- **Angular 20.1.2**: Latest Angular version +- **TypeScript 5.8.3**: For type safety +- **Node.js >= 22.0.0**: Required Node version +- **npm >= 10.0.0**: Required npm version + +## Important Conventions +- **Component Prefix**: Each library has its own prefix (e.g., `remi` for remission, `oms` for OMS) +- **Standalone Components**: All new components should be standalone +- **Path Aliases**: Use TypeScript path aliases defined in `tsconfig.base.json` (e.g., `@isa/core/config`) +- **Project Names**: Can be found in each library's `project.json` file + +## Development Workflow Tips +- Always use `npx nx run` pattern for executing tasks +- Include `--skip-cache` flag when running tests to ensure fresh results +- Use Nx's affected commands to optimize CI/CD pipelines +- Project graph visualization helps understand dependencies: `npx nx graph` + +## Development Notes +- Use start target to start the application. Only one project can be started: isa-app +- Make sure to have a look at @docs/guidelines/testing.md before writing tests +- Make sure to add e2e attributes to the html. Those are important for my colleagues writen e2e tests +- Guide for the e2e testing attributes can be found in the testing.md +- When reviewing code follow the instructions @.github/review-instructions.md diff --git a/apps/isa-app/stories/ui/input-controls/inline-input.stories.ts b/apps/isa-app/stories/ui/input-controls/inline-input.stories.ts new file mode 100644 index 000000000..76a269eb4 --- /dev/null +++ b/apps/isa-app/stories/ui/input-controls/inline-input.stories.ts @@ -0,0 +1,59 @@ +import { + argsToTemplate, + moduleMetadata, + type Meta, + type StoryObj, +} from '@storybook/angular'; +import { + InlineInputComponent, + InputControlDirective, +} from '@isa/ui/input-controls'; + +const meta: Meta = { + component: InlineInputComponent, + title: 'ui/input-controls/InlineInput', + argTypes: { + size: { control: 'select', options: ['small', 'medium'] }, + }, + args: { + size: 'medium', + }, + decorators: [ + moduleMetadata({ + imports: [InputControlDirective], + }), + ], + render: (args) => ({ + props: args, + template: ` + + + + `, + }), +}; + +export default meta; + +type Story = StoryObj; + +export const Primary: Story = { + args: { + size: 'medium', + }, +}; + +export const WithLabel: Story = { + args: { + size: 'medium', + }, + render: (args) => ({ + props: args, + template: ` + + + + + `, + }), +}; diff --git a/libs/checkout/data-access/project.json b/libs/checkout/data-access/project.json index 13db5959a..8457d80a8 100644 --- a/libs/checkout/data-access/project.json +++ b/libs/checkout/data-access/project.json @@ -1,5 +1,5 @@ { - "name": "data-access", + "name": "checkout-data-access", "$schema": "../../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/checkout/data-access/src", "prefix": "lib", diff --git a/libs/checkout/feature/reward-catalog/src/lib/reward-catalog.component.html b/libs/checkout/feature/reward-catalog/src/lib/reward-catalog.component.html index 58ee16915..84bb1618f 100644 --- a/libs/checkout/feature/reward-catalog/src/lib/reward-catalog.component.html +++ b/libs/checkout/feature/reward-catalog/src/lib/reward-catalog.component.html @@ -1,70 +1,70 @@ - - - - - - - XXX Einträge - - -
- - - -
- - + + + + + + + XXX Einträge + + +
+ + + +
+ + diff --git a/libs/shared/filter/src/lib/core/filter.service.ts b/libs/shared/filter/src/lib/core/filter.service.ts index c41156552..b8e0cd49f 100644 --- a/libs/shared/filter/src/lib/core/filter.service.ts +++ b/libs/shared/filter/src/lib/core/filter.service.ts @@ -193,19 +193,18 @@ export class FilterService { return input; } - const isParent = + const hasChildren = Array.isArray(checkboxOption.values) && checkboxOption.values.length > 0; - let keys: string[] = []; - - if (isParent) { - // If the option has children, we need to include all child keys - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - keys = checkboxOption.values!.map((v) => - checkboxOptionKeysHelper(v).join('.'), + // Collect the keys we want to add/remove. When the option has children we only include the + // children's keys; otherwise we include the option's own key. Avoids non-null assertion. + let keys: string[]; + if (hasChildren) { + const children = checkboxOption.values as CheckboxFilterInputOption[]; // safe due to hasChildren + keys = children.map((child) => + checkboxOptionKeysHelper(child).join('.'), ); } else { - // If no children, just use the current option key keys = [optionKeys.join('.')]; } @@ -361,6 +360,45 @@ export class FilterService { } } + /** + * Sets the number range values for an input with the specified key. + * + * This updates the current minimum (min) and maximum (max) values for a + * NumberRange filter input. Passing `undefined` for either side will clear that + * boundary while leaving the other intact. + * + * @param key - The key of the number range input to update + * @param min - The minimum numeric value (inclusive) or undefined to clear + * @param max - The maximum numeric value (inclusive) or undefined to clear + * @param options - Optional parameters + * @param options.commit - If true, commits the changes immediately + */ + setInputNumberRangeValue( + key: string, + min?: number, + max?: number, + options?: { commit: boolean }, + ): void { + const inputs = this.#state.inputs().map((input) => { + if (input.key !== key) { + return input; + } + + if (input.type === InputType.NumberRange) { + return { ...input, min, max }; + } + + this.logUnsupportedInputType(input, 'setInputNumberRangeValue'); + return input; + }); + + patchState(this.#state, { inputs }); + + if (options?.commit) { + this.commit(); + } + } + /** * Helper method to consistently log unsupported input type warnings * @private @@ -809,6 +847,17 @@ export class FilterService { result[input.key] = ''; } break; + case InputType.NumberRange: { + const { min: minVal, max: maxVal } = input; + if (minVal != null && maxVal != null) { + result[input.key] = `"${minVal}-${maxVal}"`; + } else if (minVal != null) { + result[input.key] = `"${minVal}-"`; + } else if (maxVal != null) { + result[input.key] = `"-${maxVal}"`; + } + break; + } } } @@ -927,6 +976,18 @@ export class FilterService { this.setInputDateRangeValue(key, start, stop); break; } + case InputType.NumberRange: { + const decoded = decodeURIComponent(params[key]); + const [minRaw, maxRaw] = decoded.split('-"'); + const min = minRaw + ? Number(minRaw.replace(/"-/g, '').replace(/"/g, '')) + : undefined; + const max = maxRaw + ? Number(maxRaw.replace(/"-/g, '').replace(/"/g, '')) + : undefined; + this.setInputNumberRangeValue(key, min, max); + break; + } default: this.logUnsupportedInputType(input, 'parseQueryParams'); break; diff --git a/libs/shared/filter/src/lib/core/mappings/filter-input-to-record.mapping.ts b/libs/shared/filter/src/lib/core/mappings/filter-input-to-record.mapping.ts index b2586c1a9..8b4dea528 100644 --- a/libs/shared/filter/src/lib/core/mappings/filter-input-to-record.mapping.ts +++ b/libs/shared/filter/src/lib/core/mappings/filter-input-to-record.mapping.ts @@ -50,6 +50,15 @@ export function mapFilterInputToRecord( if (start || stop) { acc[input.key] = `${start}-${stop}`; } + } else if (input.type === InputType.NumberRange) { + const { min, max } = input; + if (min && max) { + acc[input.key] = `"${min}-${max}"`; + } else if (min) { + acc[input.key] = `"${min}-"`; + } else if (max) { + acc[input.key] = `"-${max}"`; + } } return acc; }, {}); diff --git a/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.spec.ts b/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.spec.ts index 819880a4e..ca00c2d03 100644 --- a/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.spec.ts +++ b/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.spec.ts @@ -119,22 +119,4 @@ describe('filterInputMapping', () => { mapped: 'dateRange', }); }); - - it('should throw error for unknown input type', () => { - // Arrange - const group = 'testGroup'; - const input: Input = { - key: 'unknownInput', - label: 'Unknown Input', - type: 999 as unknown as InputType, // Invalid input type - }; - - // Act & Assert - expect(() => filterInputMapping(group, input)).toThrow( - 'Unknown input type: 999', - ); - expect(mockTextFilterInputMapping).not.toHaveBeenCalled(); - expect(mockCheckboxFilterInputMapping).not.toHaveBeenCalled(); - expect(mockDateRangeFilterInputMapping).not.toHaveBeenCalled(); - }); }); diff --git a/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.ts b/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.ts index 1889f56d3..8d85c15dc 100644 --- a/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.ts +++ b/libs/shared/filter/src/lib/core/mappings/filter-input.mapping.ts @@ -1,29 +1,32 @@ -import { Input, InputType } from '../../types'; -import { FilterInput } from '../schemas'; -import { checkboxFilterInputMapping } from './checkbox-filter-input.mapping'; -import { dateRangeFilterInputMapping } from './date-range-filter-input.mapping'; -import { textFilterInputMapping } from './text-filter-input.mapping'; - -/** - * Maps an Input object to the appropriate FilterInput type based on its input type - * - * This function serves as a router that delegates to the specific mapping function - * based on the input type (Text, Checkbox, DateRange). It ensures that each input - * is converted to its corresponding strongly-typed filter input object. - * - * @param group - The group identifier that this input belongs to - * @param input - The source input object to map - * @returns A validated FilterInput object of the appropriate subtype - * @throws Error if the input type is not supported - */ -export function filterInputMapping(group: string, input: Input): FilterInput { - switch (input.type) { - case InputType.Text: - return textFilterInputMapping(group, input); - case InputType.Checkbox: - return checkboxFilterInputMapping(group, input); - case InputType.DateRange: - return dateRangeFilterInputMapping(group, input); - } - throw new Error(`Unknown input type: ${input.type}`); -} +import { Input, InputType } from '../../types'; +import { FilterInput } from '../schemas'; +import { checkboxFilterInputMapping } from './checkbox-filter-input.mapping'; +import { dateRangeFilterInputMapping } from './date-range-filter-input.mapping'; +import { numberRangeFilterInputMapping } from './number-range-filter-input.mapping'; +import { textFilterInputMapping } from './text-filter-input.mapping'; + +/** + * Maps an Input object to the appropriate FilterInput type based on its input type + * + * This function serves as a router that delegates to the specific mapping function + * based on the input type (Text, Checkbox, DateRange). It ensures that each input + * is converted to its corresponding strongly-typed filter input object. + * + * @param group - The group identifier that this input belongs to + * @param input - The source input object to map + * @returns A validated FilterInput object of the appropriate subtype + * @throws Error if the input type is not supported + */ +export function filterInputMapping(group: string, input: Input): FilterInput { + switch (input.type) { + case InputType.Text: + return textFilterInputMapping(group, input); + case InputType.Checkbox: + return checkboxFilterInputMapping(group, input); + case InputType.DateRange: + return dateRangeFilterInputMapping(group, input); + case InputType.NumberRange: + return numberRangeFilterInputMapping(group, input); + } + console.warn('filterInputMapping: Unknown input type', input); +} diff --git a/libs/shared/filter/src/lib/core/mappings/filter.mapping.ts b/libs/shared/filter/src/lib/core/mappings/filter.mapping.ts index 2513c3632..ffca0c3a3 100644 --- a/libs/shared/filter/src/lib/core/mappings/filter.mapping.ts +++ b/libs/shared/filter/src/lib/core/mappings/filter.mapping.ts @@ -31,8 +31,14 @@ export function filterMapping(settings: QuerySettings): Filter { for (const group of groups) { filter.groups.push(filterGroupMapping(group)); - for (const input of group.input) { - filter.inputs.push(filterInputMapping(group.group, input)); + if (Array.isArray(group.input)) { + for (const input of group.input) { + const inputs = filterInputMapping(group.group, input); + if (inputs === undefined) { + continue; + } + filter.inputs.push(inputs); + } } } diff --git a/libs/shared/filter/src/lib/core/mappings/number-range-filter-input.mapping.ts b/libs/shared/filter/src/lib/core/mappings/number-range-filter-input.mapping.ts new file mode 100644 index 000000000..896254acd --- /dev/null +++ b/libs/shared/filter/src/lib/core/mappings/number-range-filter-input.mapping.ts @@ -0,0 +1,32 @@ +import { Input, InputType } from '../../types'; +import { + NumberRangeFilterInput, + NumberRangeFilterInputSchema, +} from '../schemas'; + +export function numberRangeFilterInputMapping( + group: string, + input: Input, +): NumberRangeFilterInput { + return NumberRangeFilterInputSchema.parse({ + group, + key: input.key, + label: input.label, + description: input.description, + type: InputType.NumberRange, + min: input.options?.values?.[0]?.value + ? Number(input.options?.values?.[0]?.value) + : undefined, + max: input.options?.values?.[1]?.value + ? Number(input.options?.values?.[1]?.value) + : undefined, + minValue: input.options?.values?.[0]?.minValue + ? Number(input.options?.values?.[0]?.minValue.replace('-', '')) + : undefined, + maxValue: input.options?.values?.[0]?.maxValue + ? Number(input.options?.values?.[0]?.maxValue.replace('-', '')) + : undefined, + minLabel: input.options?.values?.[0]?.label || 'Min', + maxLabel: input.options?.values?.[1]?.label || 'Max', + }); +} diff --git a/libs/shared/filter/src/lib/core/schemas/filter-input.schema.ts b/libs/shared/filter/src/lib/core/schemas/filter-input.schema.ts index acb9be8ad..17b402ec1 100644 --- a/libs/shared/filter/src/lib/core/schemas/filter-input.schema.ts +++ b/libs/shared/filter/src/lib/core/schemas/filter-input.schema.ts @@ -1,21 +1,23 @@ -import { z } from 'zod'; -import { CheckboxFilterInputSchema } from './checkbox-filter-input.schema'; -import { DateRangeFilterInputSchema } from './date-range-filter-input.schema'; -import { TextFilterInputSchema } from './text-filter-input.schema'; - -/** - * A union schema representing all possible filter input types in the system. - * This schema allows for type discrimination based on the `type` property. - * - * Supported filter input types: - * - TextFilterInput: Simple text input fields - * - CheckboxFilterInput: Multiple-choice checkbox selections - * - DateRangeFilterInput: Date range selectors for time-based filtering - */ -export const FilterInputSchema = z.union([ - TextFilterInputSchema, - CheckboxFilterInputSchema, - DateRangeFilterInputSchema, -]); - -export type FilterInput = z.infer; +import { z } from 'zod'; +import { CheckboxFilterInputSchema } from './checkbox-filter-input.schema'; +import { DateRangeFilterInputSchema } from './date-range-filter-input.schema'; +import { TextFilterInputSchema } from './text-filter-input.schema'; +import { NumberRangeFilterInputSchema } from './number-range-filter-input.schema'; + +/** + * A union schema representing all possible filter input types in the system. + * This schema allows for type discrimination based on the `type` property. + * + * Supported filter input types: + * - TextFilterInput: Simple text input fields + * - CheckboxFilterInput: Multiple-choice checkbox selections + * - DateRangeFilterInput: Date range selectors for time-based filtering + */ +export const FilterInputSchema = z.union([ + TextFilterInputSchema, + CheckboxFilterInputSchema, + DateRangeFilterInputSchema, + NumberRangeFilterInputSchema, +]); + +export type FilterInput = z.infer; diff --git a/libs/shared/filter/src/lib/core/schemas/index.ts b/libs/shared/filter/src/lib/core/schemas/index.ts index e3af7688b..db1877cea 100644 --- a/libs/shared/filter/src/lib/core/schemas/index.ts +++ b/libs/shared/filter/src/lib/core/schemas/index.ts @@ -1,12 +1,13 @@ -export * from './base-filter-input.schema'; -export * from './checkbox-filter-input-option.schema'; -export * from './checkbox-filter-input.schema'; -export * from './date-range-filter-input.schema'; -export * from './filter-group.schema'; -export * from './filter-input.schema'; -export * from './filter.schema'; -export * from './order-by-direction.schema'; -export * from './order-by-option.schema'; -export * from './query-order.schema'; -export * from './query.schema'; -export * from './text-filter-input.schema'; +export * from './base-filter-input.schema'; +export * from './checkbox-filter-input-option.schema'; +export * from './checkbox-filter-input.schema'; +export * from './date-range-filter-input.schema'; +export * from './filter-group.schema'; +export * from './filter-input.schema'; +export * from './filter.schema'; +export * from './number-range-filter-input.schema'; +export * from './order-by-direction.schema'; +export * from './order-by-option.schema'; +export * from './query-order.schema'; +export * from './query.schema'; +export * from './text-filter-input.schema'; diff --git a/libs/shared/filter/src/lib/core/schemas/number-range-filter-input.schema.ts b/libs/shared/filter/src/lib/core/schemas/number-range-filter-input.schema.ts new file mode 100644 index 000000000..eb4e967ae --- /dev/null +++ b/libs/shared/filter/src/lib/core/schemas/number-range-filter-input.schema.ts @@ -0,0 +1,31 @@ +import { z } from 'zod'; +import { BaseFilterInputSchema } from './base-filter-input.schema'; +import { InputType } from '../../types'; + +export const NumberRangeFilterInputSchema = BaseFilterInputSchema.extend({ + type: z + .literal(InputType.NumberRange) + .describe( + 'Specifies this as a number range input type. Must be InputType.NumberRange.', + ), + min: z.number().optional().describe('Current minimum value of the range.'), + max: z.number().optional().describe('Current maximum value of the range.'), + minValue: z + .number() + .optional() + .describe( + 'Minimum value of the number range. Optional if only a maximum is needed.', + ), + maxValue: z + .number() + .optional() + .describe( + 'Maximum value of the number range. Optional if only a minimum is needed.', + ), + minLabel: z.string().describe('Label for the minimum input field.'), + maxLabel: z.string().describe('Label for the maximum input field.'), +}).describe('NumberRangeFilterInput'); + +export type NumberRangeFilterInput = z.infer< + typeof NumberRangeFilterInputSchema +>; diff --git a/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.html b/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.html index f592087ee..4a1fcd999 100644 --- a/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.html +++ b/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.html @@ -1,15 +1,19 @@ -@switch (filterInput().type) { - @case (InputType.Checkbox) { - - - } - @case (InputType.DateRange) { - - - } - @default { -
- Fehler: Kein Template für diesen Typ gefunden! {{ filterInput().type }} -
- } -} +@switch (filterInput().type) { + @case (InputType.Checkbox) { + + + } + @case (InputType.DateRange) { + + + } + @case (InputType.NumberRange) { + + + } + @default { +
+ Fehler: Kein Template für diesen Typ gefunden! {{ filterInput().type }} +
+ } +} diff --git a/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.ts b/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.ts index 60735c241..e8e634161 100644 --- a/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.ts +++ b/libs/shared/filter/src/lib/inputs/input-renderer/input-renderer.component.ts @@ -1,27 +1,32 @@ -import { - ChangeDetectionStrategy, - Component, - input, - ViewEncapsulation, -} from '@angular/core'; -import { CheckboxInputComponent } from '../checkbox-input'; -import { DatepickerRangeInputComponent } from '../datepicker-range-input'; -import { FilterInput } from '../../core'; -import { InputType } from '../../types'; - -@Component({ - selector: 'filter-input-renderer', - templateUrl: 'input-renderer.component.html', - styleUrls: ['./input-renderer.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - standalone: true, - imports: [CheckboxInputComponent, DatepickerRangeInputComponent], - host: { - '[class]': "['filter-input-renderer']", - }, -}) -export class InputRendererComponent { - filterInput = input.required(); - InputType = InputType; -} +import { + ChangeDetectionStrategy, + Component, + input, + ViewEncapsulation, +} from '@angular/core'; +import { CheckboxInputComponent } from '../checkbox-input'; +import { DatepickerRangeInputComponent } from '../datepicker-range-input'; +import { NumberRangeInputComponent } from '../number-range-input'; +import { FilterInput } from '../../core'; +import { InputType } from '../../types'; + +@Component({ + selector: 'filter-input-renderer', + templateUrl: 'input-renderer.component.html', + styleUrls: ['./input-renderer.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + standalone: true, + imports: [ + CheckboxInputComponent, + DatepickerRangeInputComponent, + NumberRangeInputComponent, + ], + host: { + '[class]': "['filter-input-renderer']", + }, +}) +export class InputRendererComponent { + filterInput = input.required(); + InputType = InputType; +} diff --git a/libs/shared/filter/src/lib/inputs/number-range-input/index.ts b/libs/shared/filter/src/lib/inputs/number-range-input/index.ts new file mode 100644 index 000000000..ad86df583 --- /dev/null +++ b/libs/shared/filter/src/lib/inputs/number-range-input/index.ts @@ -0,0 +1 @@ +export * from './number-range-input.component'; diff --git a/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.html b/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.html new file mode 100644 index 000000000..2babb06bd --- /dev/null +++ b/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.html @@ -0,0 +1,43 @@ +@let inp = input(); + + + + @if (minModel.invalid && minModel.touched) { +
+ @if (minModel.errors?.['min']) { + Mindestens {{ minInputLowerLimit() }}. + } + @if (minModel.errors?.['max']) { + Maximal {{ minInputUpperLimit() }}. + } +
+ } +
+ + + + @if (minModel.invalid && minModel.touched) { +
+ @if (minModel.errors?.['min']) { + Mindestens {{ minInputLowerLimit() }}. + } + @if (minModel.errors?.['max']) { + Maximal {{ minInputUpperLimit() }}. + } +
+ } +
diff --git a/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.scss b/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.scss new file mode 100644 index 000000000..2013d47e0 --- /dev/null +++ b/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.scss @@ -0,0 +1,7 @@ +:host { + @apply grid grid-cols-2 gap-2 p-5; +} + +.ui-input-control { + @apply w-full; +} diff --git a/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.ts b/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.ts new file mode 100644 index 000000000..06f3c4645 --- /dev/null +++ b/libs/shared/filter/src/lib/inputs/number-range-input/number-range-input.component.ts @@ -0,0 +1,87 @@ +import { + ChangeDetectionStrategy, + Component, + computed, + effect, + inject, + input, + linkedSignal, +} from '@angular/core'; +import { FilterService, NumberRangeFilterInput } from '../../core'; +import { InputType } from '../../types'; +import { + InputControlDirective, + InlineInputComponent, +} from '@isa/ui/input-controls'; +import { logger } from '@isa/core/logging'; +import { FormsModule } from '@angular/forms'; + +@Component({ + selector: 'filter-number-range-input', + templateUrl: './number-range-input.component.html', + styleUrls: ['./number-range-input.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [InlineInputComponent, InputControlDirective, FormsModule], + host: { '[class]': "['filter-number-range-input']" }, +}) +export class NumberRangeInputComponent { + #logger = logger(() => ({ component: 'NumberRangeInputComponent' })); + + #filterService = inject(FilterService); + inputKey = input.required(); + + input = computed(() => { + const inputs = this.#filterService.inputs(); + const input = inputs.find( + (input) => + input.key === this.inputKey() && input.type === InputType.NumberRange, + ) as NumberRangeFilterInput; + + if (!input) { + const err = new Error(`Input not found for key: ${this.inputKey()}`); + this.#logger.error('Input not found', { error: err }); + } + + return input; + }); + + minValue = linkedSignal(() => this.input().min); + + // Overall domain bounds coming from the filter input definition + overallMinLimit = computed(() => this.input().minValue ?? 0); + overallMaxLimit = computed(() => this.input().maxValue ?? Infinity); + + // Allowed bounds for the minimum value input + minInputLowerLimit = computed(() => this.overallMinLimit()); + minInputUpperLimit = computed(() => + Math.min(this.maxValue() ?? Infinity, this.overallMaxLimit()), + ); + + maxValue = linkedSignal(() => this.input().max); + + // Allowed bounds for the maximum value input + maxInputLowerLimit = computed(() => + Math.max(this.minValue() ?? 0, this.overallMinLimit()), + ); + maxInputUpperLimit = computed(() => this.overallMaxLimit()); + + constructor() { + effect(() => { + const minValue = this.minValue(); + const maxValue = this.maxValue(); + + const currentMin = this.input().min; + const currentMax = this.input().max; + + if (minValue === currentMin && maxValue === currentMax) { + return; + } + + this.#filterService.setInputNumberRangeValue( + this.inputKey(), + minValue, + maxValue, + ); + }); + } +} diff --git a/libs/shared/filter/src/lib/types.ts b/libs/shared/filter/src/lib/types.ts index 93c017c8d..04b854a8f 100644 --- a/libs/shared/filter/src/lib/types.ts +++ b/libs/shared/filter/src/lib/types.ts @@ -2,13 +2,14 @@ export enum InputType { Text = 1, Checkbox = 2, DateRange = 128, + NumberRange = 4096, } /** * Enumeration of search trigger types that indicate how a search was initiated. * Used throughout the filter system to track user interaction patterns and * optimize search behavior based on the trigger source. - * + * * @example * ```typescript * // Handle different search triggers diff --git a/libs/ui/input-controls/src/index.ts b/libs/ui/input-controls/src/index.ts index 7131dd0f4..dd3a2d53a 100644 --- a/libs/ui/input-controls/src/index.ts +++ b/libs/ui/input-controls/src/index.ts @@ -1,16 +1,17 @@ -export * from './lib/checkbox/checkbox-label.directive'; -export * from './lib/checkbox/checkbox.component'; -export * from './lib/checkbox/checklist-value.directive'; -export * from './lib/checkbox/checklist.component'; -export * from './lib/core/input-control.directive'; -export * from './lib/dropdown/dropdown.component'; -export * from './lib/dropdown/dropdown.types'; -export * from './lib/listbox/listbox-item.directive'; -export * from './lib/listbox/listbox.directive'; -export * from './lib/text-field/textarea.component'; -export * from './lib/text-field/text-field.component'; -export * from './lib/text-field/text-field-clear.component'; -export * from './lib/text-field/text-field-container.component'; -export * from './lib/text-field/text-field-errors.component'; -export * from './lib/chips/chips.component'; -export * from './lib/chips/chip-option.component'; +export * from './lib/checkbox/checkbox-label.directive'; +export * from './lib/checkbox/checkbox.component'; +export * from './lib/checkbox/checklist-value.directive'; +export * from './lib/checkbox/checklist.component'; +export * from './lib/core/input-control.directive'; +export * from './lib/dropdown/dropdown.component'; +export * from './lib/dropdown/dropdown.types'; +export * from './lib/listbox/listbox-item.directive'; +export * from './lib/listbox/listbox.directive'; +export * from './lib/inline-input/inline-input.component'; +export * from './lib/text-field/textarea.component'; +export * from './lib/text-field/text-field.component'; +export * from './lib/text-field/text-field-clear.component'; +export * from './lib/text-field/text-field-container.component'; +export * from './lib/text-field/text-field-errors.component'; +export * from './lib/chips/chips.component'; +export * from './lib/chips/chip-option.component'; diff --git a/libs/ui/input-controls/src/input-controls.scss b/libs/ui/input-controls/src/input-controls.scss index 68df85788..4f92ebc28 100644 --- a/libs/ui/input-controls/src/input-controls.scss +++ b/libs/ui/input-controls/src/input-controls.scss @@ -2,6 +2,7 @@ @use "./lib/checkbox/checklist"; @use "./lib/chips/chips"; @use "./lib/dropdown/dropdown"; +@use "./lib/inline-input/inline-input"; @use "./lib/listbox/listbox"; @use "./lib/text-field/text-field"; @use "./lib/text-field/text-field-clear"; diff --git a/libs/ui/input-controls/src/lib/inline-input/_inline-input.scss b/libs/ui/input-controls/src/lib/inline-input/_inline-input.scss new file mode 100644 index 000000000..68f0f5951 --- /dev/null +++ b/libs/ui/input-controls/src/lib/inline-input/_inline-input.scss @@ -0,0 +1,47 @@ +.ui-inline-input { + display: inline-flex; + padding: 0.5rem 0; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: 0.25rem; + + label { + @apply text-isa-neutral-900; + + font-family: "Open Sans"; + font-size: 0.5rem; + font-style: normal; + font-weight: 700; + line-height: 0.75rem; /* 150% */ + text-transform: uppercase; + } + + &.ui-inline-input--small input { + @apply isa-text-body-2-bold; + } + + &.ui-inline-input--medium input { + @apply isa-text-body-1-bold; + } + + input { + @apply outline-none font-bold text-isa-neutral-900; + + &::placeholder { + @apply text-isa-neutral-500 font-normal; + + &:hover { + @apply font-normal; + } + + &:focus { + @apply text-isa-neutral-600 font-bold; + } + } + + &.ng-invalid { + @apply text-isa-accent-red; + } + } +} diff --git a/libs/ui/input-controls/src/lib/inline-input/inline-input.component.html b/libs/ui/input-controls/src/lib/inline-input/inline-input.component.html new file mode 100644 index 000000000..b391af18d --- /dev/null +++ b/libs/ui/input-controls/src/lib/inline-input/inline-input.component.html @@ -0,0 +1 @@ + diff --git a/libs/ui/input-controls/src/lib/inline-input/inline-input.component.ts b/libs/ui/input-controls/src/lib/inline-input/inline-input.component.ts new file mode 100644 index 000000000..4ef01e655 --- /dev/null +++ b/libs/ui/input-controls/src/lib/inline-input/inline-input.component.ts @@ -0,0 +1,39 @@ +import { + ChangeDetectionStrategy, + Component, + computed, + input, + contentChild, +} from '@angular/core'; + +import { InputControlDirective } from '../core/input-control.directive'; + +export const InlineInputSize = { + Small: 'small', + Medium: 'medium', +} as const; +export type InlineInputSize = + (typeof InlineInputSize)[keyof typeof InlineInputSize]; + +@Component({ + selector: 'ui-inline-input', + templateUrl: './inline-input.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + host: { '[class]': "['ui-inline-input', sizeClass()]" }, +}) +export class InlineInputComponent { + size = input(InlineInputSize.Medium); + + sizeClass = computed(() => { + const size = this.size(); + switch (size) { + case InlineInputSize.Small: + return 'ui-inline-input--small'; + case InlineInputSize.Medium: + default: + return 'ui-inline-input--medium'; + } + }); + + inputControl = contentChild.required(InputControlDirective); +} diff --git a/tsconfig.base.json b/tsconfig.base.json index f08f77cca..fe660eef0 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,140 +1,140 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "sourceMap": true, - "declaration": false, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "importHelpers": false, - "target": "ES2022", - "module": "es2020", - "lib": ["es2020", "dom"], - "baseUrl": "./", - "paths": { - "@adapter/*": ["apps/isa-app/src/adapter/*/index.ts"], - "@cdn/*": ["apps/isa-app/src/cdn/*/index.ts"], - "@core/*": ["apps/isa-app/src/core/*/index.ts"], - "@core/config": ["libs/core/config/src/index.ts"], - "@domain/*": ["apps/isa-app/src/domain/*/index.ts"], - "@external/*": ["apps/isa-app/src/external/*/index.ts"], - "@generated/swagger/availability-api": [ - "generated/swagger/availability-api/src/index.ts" - ], - "@generated/swagger/cat-search-api": [ - "generated/swagger/cat-search-api/src/index.ts" - ], - "@generated/swagger/checkout-api": [ - "generated/swagger/checkout-api/src/index.ts" - ], - "@generated/swagger/crm-api": ["generated/swagger/crm-api/src/index.ts"], - "@generated/swagger/eis-api": ["generated/swagger/eis-api/src/index.ts"], - "@generated/swagger/inventory-api": [ - "generated/swagger/inventory-api/src/index.ts" - ], - "@generated/swagger/isa-api": ["generated/swagger/isa-api/src/index.ts"], - "@generated/swagger/oms-api": ["generated/swagger/oms-api/src/index.ts"], - "@generated/swagger/print-api": [ - "generated/swagger/print-api/src/index.ts" - ], - "@generated/swagger/wws-api": ["generated/swagger/wws-api/src/index.ts"], - "@hub/*": ["apps/isa-app/src/hub/*/index.ts"], - "@isa/catalogue/data-access": ["libs/catalogue/data-access/src/index.ts"], - "@isa/checkout/data-access": ["libs/checkout/data-access/src/index.ts"], - "@isa/checkout/feature/reward-catalog": [ - "libs/checkout/feature/reward-catalog/src/index.ts" - ], - "@isa/common/data-access": ["libs/common/data-access/src/index.ts"], - "@isa/common/decorators": ["libs/common/decorators/src/index.ts"], - "@isa/common/print": ["libs/common/print/src/index.ts"], - "@isa/core/config": ["libs/core/config/src/index.ts"], - "@isa/core/logging": ["libs/core/logging/src/index.ts"], - "@isa/core/notifications": ["libs/core/notifications/src/index.ts"], - "@isa/core/storage": ["libs/core/storage/src/index.ts"], - "@isa/core/tabs": ["libs/core/tabs/src/index.ts"], - "@isa/crm/data-access": ["libs/crm/data-access/src/index.ts"], - "@isa/icons": ["libs/icons/src/index.ts"], - "@isa/oms/data-access": ["libs/oms/data-access/src/index.ts"], - "@isa/oms/feature/return-details": [ - "libs/oms/feature/return-details/src/index.ts" - ], - "@isa/oms/feature/return-process": [ - "libs/oms/feature/return-process/src/index.ts" - ], - "@isa/oms/feature/return-review": [ - "libs/oms/feature/return-review/src/index.ts" - ], - "@isa/oms/feature/return-search": [ - "libs/oms/feature/return-search/src/index.ts" - ], - "@isa/oms/feature/return-summary": [ - "libs/oms/feature/return-summary/src/index.ts" - ], - "@isa/oms/shared/product-info": [ - "libs/oms/shared/product-info/src/index.ts" - ], - "@isa/oms/shared/task-list": ["libs/oms/shared/task-list/src/index.ts"], - "@isa/oms/utils/translation": ["libs/oms/utils/translation/src/index.ts"], - "@isa/remission/data-access": ["libs/remission/data-access/src/index.ts"], - "@isa/remission/feature/remission-list": [ - "libs/remission/feature/remission-list/src/index.ts" - ], - "@isa/remission/feature/remission-return-receipt-details": [ - "libs/remission/feature/remission-return-receipt-details/src/index.ts" - ], - "@isa/remission/feature/remission-return-receipt-list": [ - "libs/remission/feature/remission-return-receipt-list/src/index.ts" - ], - "@isa/remission/shared/product": [ - "libs/remission/shared/product/src/index.ts" - ], - "@isa/remission/shared/remission-start-dialog": [ - "libs/remission/shared/remission-start-dialog/src/index.ts" - ], - "@isa/remission/shared/return-receipt-actions": [ - "libs/remission/shared/return-receipt-actions/src/index.ts" - ], - "@isa/remission/shared/search-item-to-remit-dialog": [ - "libs/remission/shared/search-item-to-remit-dialog/src/index.ts" - ], - "@isa/shared/filter": ["libs/shared/filter/src/index.ts"], - "@isa/shared/product-foramt": ["libs/shared/product-format/src/index.ts"], - "@isa/shared/product-image": ["libs/shared/product-image/src/index.ts"], - "@isa/shared/product-router-link": [ - "libs/shared/product-router-link/src/index.ts" - ], - "@isa/shared/scanner": ["libs/shared/scanner/src/index.ts"], - "@isa/ui/bullet-list": ["libs/ui/bullet-list/src/index.ts"], - "@isa/ui/buttons": ["libs/ui/buttons/src/index.ts"], - "@isa/ui/datepicker": ["libs/ui/datepicker/src/index.ts"], - "@isa/ui/dialog": ["libs/ui/dialog/src/index.ts"], - "@isa/ui/empty-state": ["libs/ui/empty-state/src/index.ts"], - "@isa/ui/expandable": ["libs/ui/expandable/src/index.ts"], - "@isa/ui/input-controls": ["libs/ui/input-controls/src/index.ts"], - "@isa/ui/item-rows": ["libs/ui/item-rows/src/index.ts"], - "@isa/ui/label": ["libs/ui/label/src/index.ts"], - "@isa/ui/layout": ["libs/ui/layout/src/index.ts"], - "@isa/ui/menu": ["libs/ui/menu/src/index.ts"], - "@isa/ui/progress-bar": ["libs/ui/progress-bar/src/index.ts"], - "@isa/ui/search-bar": ["libs/ui/search-bar/src/index.ts"], - "@isa/ui/skeleton-loader": ["libs/ui/skeleton-loader/src/index.ts"], - "@isa/ui/toolbar": ["libs/ui/toolbar/src/index.ts"], - "@isa/ui/tooltip": ["libs/ui/tooltip/src/index.ts"], - "@isa/utils/ean-validation": ["libs/utils/ean-validation/src/index.ts"], - "@isa/utils/scroll-position": ["libs/utils/scroll-position/src/index.ts"], - "@isa/utils/z-safe-parse": ["libs/utils/z-safe-parse/src/index.ts"], - "@modal/*": ["apps/isa-app/src/modal/*/index.ts"], - "@page/*": ["apps/isa-app/src/page/*/index.ts"], - "@shared/*": ["apps/isa-app/src/shared/*/index.ts"], - "@shared/components/*": ["apps/isa-app/src/shared/components/*/index.ts"], - "@shared/directives/*": ["apps/isa-app/src/shared/directives/*/index.ts"], - "@shared/pipes/*": ["apps/isa-app/src/shared/pipes/*/index.ts"], - "@shared/services/*": ["apps/isa-app/src/shared/services/*/index.ts"], - "@swagger/*": ["apps/isa-app/src/swagger/*/index.ts"], - "@ui/*": ["apps/isa-app/src/ui/*/index.ts"], - "@utils/*": ["apps/isa-app/src/utils/*/index.ts"], - "packageJson": ["package.json"] - }, - "skipLibCheck": true - } -} +{ + "compileOnSave": false, + "compilerOptions": { + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": false, + "target": "ES2022", + "module": "es2020", + "lib": ["es2020", "dom"], + "baseUrl": "./", + "paths": { + "@adapter/*": ["apps/isa-app/src/adapter/*/index.ts"], + "@cdn/*": ["apps/isa-app/src/cdn/*/index.ts"], + "@core/*": ["apps/isa-app/src/core/*/index.ts"], + "@core/config": ["libs/core/config/src/index.ts"], + "@domain/*": ["apps/isa-app/src/domain/*/index.ts"], + "@external/*": ["apps/isa-app/src/external/*/index.ts"], + "@generated/swagger/availability-api": [ + "generated/swagger/availability-api/src/index.ts" + ], + "@generated/swagger/cat-search-api": [ + "generated/swagger/cat-search-api/src/index.ts" + ], + "@generated/swagger/checkout-api": [ + "generated/swagger/checkout-api/src/index.ts" + ], + "@generated/swagger/crm-api": ["generated/swagger/crm-api/src/index.ts"], + "@generated/swagger/eis-api": ["generated/swagger/eis-api/src/index.ts"], + "@generated/swagger/inventory-api": [ + "generated/swagger/inventory-api/src/index.ts" + ], + "@generated/swagger/isa-api": ["generated/swagger/isa-api/src/index.ts"], + "@generated/swagger/oms-api": ["generated/swagger/oms-api/src/index.ts"], + "@generated/swagger/print-api": [ + "generated/swagger/print-api/src/index.ts" + ], + "@generated/swagger/wws-api": ["generated/swagger/wws-api/src/index.ts"], + "@hub/*": ["apps/isa-app/src/hub/*/index.ts"], + "@isa/catalogue/data-access": ["libs/catalogue/data-access/src/index.ts"], + "@isa/checkout/data-access": ["libs/checkout/data-access/src/index.ts"], + "@isa/checkout/feature/reward-catalog": [ + "libs/checkout/feature/reward-catalog/src/index.ts" + ], + "@isa/common/data-access": ["libs/common/data-access/src/index.ts"], + "@isa/common/decorators": ["libs/common/decorators/src/index.ts"], + "@isa/common/print": ["libs/common/print/src/index.ts"], + "@isa/core/config": ["libs/core/config/src/index.ts"], + "@isa/core/logging": ["libs/core/logging/src/index.ts"], + "@isa/core/notifications": ["libs/core/notifications/src/index.ts"], + "@isa/core/storage": ["libs/core/storage/src/index.ts"], + "@isa/core/tabs": ["libs/core/tabs/src/index.ts"], + "@isa/crm/data-access": ["libs/crm/data-access/src/index.ts"], + "@isa/icons": ["libs/icons/src/index.ts"], + "@isa/oms/data-access": ["libs/oms/data-access/src/index.ts"], + "@isa/oms/feature/return-details": [ + "libs/oms/feature/return-details/src/index.ts" + ], + "@isa/oms/feature/return-process": [ + "libs/oms/feature/return-process/src/index.ts" + ], + "@isa/oms/feature/return-review": [ + "libs/oms/feature/return-review/src/index.ts" + ], + "@isa/oms/feature/return-search": [ + "libs/oms/feature/return-search/src/index.ts" + ], + "@isa/oms/feature/return-summary": [ + "libs/oms/feature/return-summary/src/index.ts" + ], + "@isa/oms/shared/product-info": [ + "libs/oms/shared/product-info/src/index.ts" + ], + "@isa/oms/shared/task-list": ["libs/oms/shared/task-list/src/index.ts"], + "@isa/oms/utils/translation": ["libs/oms/utils/translation/src/index.ts"], + "@isa/remission/data-access": ["libs/remission/data-access/src/index.ts"], + "@isa/remission/feature/remission-list": [ + "libs/remission/feature/remission-list/src/index.ts" + ], + "@isa/remission/feature/remission-return-receipt-details": [ + "libs/remission/feature/remission-return-receipt-details/src/index.ts" + ], + "@isa/remission/feature/remission-return-receipt-list": [ + "libs/remission/feature/remission-return-receipt-list/src/index.ts" + ], + "@isa/remission/shared/product": [ + "libs/remission/shared/product/src/index.ts" + ], + "@isa/remission/shared/remission-start-dialog": [ + "libs/remission/shared/remission-start-dialog/src/index.ts" + ], + "@isa/remission/shared/return-receipt-actions": [ + "libs/remission/shared/return-receipt-actions/src/index.ts" + ], + "@isa/remission/shared/search-item-to-remit-dialog": [ + "libs/remission/shared/search-item-to-remit-dialog/src/index.ts" + ], + "@isa/shared/filter": ["libs/shared/filter/src/index.ts"], + "@isa/shared/product-foramt": ["libs/shared/product-format/src/index.ts"], + "@isa/shared/product-image": ["libs/shared/product-image/src/index.ts"], + "@isa/shared/product-router-link": [ + "libs/shared/product-router-link/src/index.ts" + ], + "@isa/shared/scanner": ["libs/shared/scanner/src/index.ts"], + "@isa/ui/bullet-list": ["libs/ui/bullet-list/src/index.ts"], + "@isa/ui/buttons": ["libs/ui/buttons/src/index.ts"], + "@isa/ui/datepicker": ["libs/ui/datepicker/src/index.ts"], + "@isa/ui/dialog": ["libs/ui/dialog/src/index.ts"], + "@isa/ui/empty-state": ["libs/ui/empty-state/src/index.ts"], + "@isa/ui/expandable": ["libs/ui/expandable/src/index.ts"], + "@isa/ui/input-controls": ["libs/ui/input-controls/src/index.ts"], + "@isa/ui/item-rows": ["libs/ui/item-rows/src/index.ts"], + "@isa/ui/label": ["libs/ui/label/src/index.ts"], + "@isa/ui/layout": ["libs/ui/layout/src/index.ts"], + "@isa/ui/menu": ["libs/ui/menu/src/index.ts"], + "@isa/ui/progress-bar": ["libs/ui/progress-bar/src/index.ts"], + "@isa/ui/search-bar": ["libs/ui/search-bar/src/index.ts"], + "@isa/ui/skeleton-loader": ["libs/ui/skeleton-loader/src/index.ts"], + "@isa/ui/toolbar": ["libs/ui/toolbar/src/index.ts"], + "@isa/ui/tooltip": ["libs/ui/tooltip/src/index.ts"], + "@isa/utils/ean-validation": ["libs/utils/ean-validation/src/index.ts"], + "@isa/utils/scroll-position": ["libs/utils/scroll-position/src/index.ts"], + "@isa/utils/z-safe-parse": ["libs/utils/z-safe-parse/src/index.ts"], + "@modal/*": ["apps/isa-app/src/modal/*/index.ts"], + "@page/*": ["apps/isa-app/src/page/*/index.ts"], + "@shared/*": ["apps/isa-app/src/shared/*/index.ts"], + "@shared/components/*": ["apps/isa-app/src/shared/components/*/index.ts"], + "@shared/directives/*": ["apps/isa-app/src/shared/directives/*/index.ts"], + "@shared/pipes/*": ["apps/isa-app/src/shared/pipes/*/index.ts"], + "@shared/services/*": ["apps/isa-app/src/shared/services/*/index.ts"], + "@swagger/*": ["apps/isa-app/src/swagger/*/index.ts"], + "@ui/*": ["apps/isa-app/src/ui/*/index.ts"], + "@utils/*": ["apps/isa-app/src/utils/*/index.ts"], + "packageJson": ["package.json"] + }, + "skipLibCheck": true + } +}