mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 1954: feat: Enhance product info components and add redemption points feature...
Related work items: #5346
This commit is contained in:
committed by
Nino Righi
parent
6c86dfbbad
commit
6ab839a529
456
CLAUDE.md
456
CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 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.
|
||||
This is a sophisticated Angular 20.1.2 monorepo managed by Nx 21.3.2. The main application is `isa-app`, a comprehensive inventory and returns management system for retail/e-commerce operations. The system handles complex workflows including order management (OMS), returns processing (remission), customer relationship management (CRM), product cataloging, and checkout/reward systems.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -23,34 +23,43 @@ This is an Angular monorepo managed by Nx. The main application is `isa-app`, wh
|
||||
- **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/`
|
||||
- **Domain-Driven Design**: Clear domain boundaries with dedicated modules (OMS, remission, CRM, catalogue, checkout)
|
||||
- **Layered Architecture**: Strict dependency hierarchy (Feature → Shared/UI → Data Access → Infrastructure)
|
||||
- **Standalone Components**: All new components use Angular standalone architecture with explicit imports
|
||||
- **Feature Libraries**: Domain features organized as separate libraries (e.g., `oms-feature-return-search`, `remission-feature-remission-list`)
|
||||
- **Data Access Layer**: Separate data-access libraries for each domain with NgRx Signals stores
|
||||
- **Shared UI Components**: 15 dedicated UI component libraries with design system integration
|
||||
- **Generated API Clients**: 10 auto-generated Swagger/OpenAPI clients with post-processing pipeline
|
||||
- **Path Aliases**: Comprehensive TypeScript path mapping (`@isa/domain/layer/feature`)
|
||||
- **Component Prefixes**: Domain-specific prefixes (OMS: `oms-feature-*`, Remission: `remi-*`, UI: `ui-*`)
|
||||
- **Modern State Management**: NgRx Signals with entities, session persistence, and reactive patterns
|
||||
|
||||
## Common Development Commands
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
# Build the main application (development)
|
||||
npx nx build isa-app --configuration=development
|
||||
# Build the main application (development) - default configuration
|
||||
npm run build
|
||||
# Or: npx nx build isa-app --configuration=development
|
||||
|
||||
# Build for production
|
||||
npx nx build isa-app --configuration=production
|
||||
npm run build-prod
|
||||
# Or: npx nx build isa-app --configuration=production
|
||||
|
||||
# Serve the application with SSL
|
||||
npx nx serve isa-app --ssl
|
||||
# Serve the application with SSL (development server)
|
||||
npm start
|
||||
# Or: npx nx serve isa-app --ssl
|
||||
```
|
||||
|
||||
### Testing Commands
|
||||
```bash
|
||||
# Run tests for a specific library (always use --skip-cache)
|
||||
npx nx run <project-name>:test --skip-cache
|
||||
# Example: npx nx run remission-data-access:test --skip-cache
|
||||
# Run tests for all libraries except the main app (default command)
|
||||
npm test
|
||||
# Or: npx nx run-many -t test --exclude isa-app --skip-cache
|
||||
|
||||
# Run tests for all libraries except the main app
|
||||
npx nx run-many -t test --exclude isa-app --skip-cache
|
||||
# Run tests for a specific library (always use --skip-cache for fresh results)
|
||||
npx nx run <project-name>:test --skip-cache
|
||||
# Example: npx nx run oms-data-access:test --skip-cache
|
||||
|
||||
# Run a single test file
|
||||
npx nx run <project-name>:test --testFile=<path-to-test-file> --skip-cache
|
||||
@@ -60,6 +69,10 @@ npx nx run <project-name>:test --code-coverage --skip-cache
|
||||
|
||||
# Run tests in watch mode
|
||||
npx nx run <project-name>:test --watch
|
||||
|
||||
# Run CI tests with coverage (for CI/CD)
|
||||
npm run ci
|
||||
# Or: npx nx run-many -t test --exclude isa-app -c ci
|
||||
```
|
||||
|
||||
### Linting Commands
|
||||
@@ -74,19 +87,24 @@ npx nx run-many -t lint
|
||||
|
||||
### Other Useful Commands
|
||||
```bash
|
||||
# Generate Swagger API clients
|
||||
# Generate Swagger API clients (regenerates all API clients)
|
||||
npm run generate:swagger
|
||||
# Or: npx nx run-many -t generate -p tag:generated,swagger
|
||||
|
||||
# Start Storybook
|
||||
npx nx run isa-app:storybook
|
||||
# Start Storybook for UI component development
|
||||
npm run storybook
|
||||
# Or: npx nx run isa-app:storybook
|
||||
|
||||
# Format code with Prettier
|
||||
npm run prettier
|
||||
|
||||
# Format staged files only (used in pre-commit hooks)
|
||||
npm run pretty-quick
|
||||
|
||||
# List all projects in the workspace
|
||||
npx nx list
|
||||
|
||||
# Show project dependencies graph
|
||||
# Show project dependencies graph (visual)
|
||||
npx nx graph
|
||||
|
||||
# Run affected tests (based on git changes)
|
||||
@@ -95,54 +113,380 @@ 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
|
||||
### Current Setup (Migration in Progress)
|
||||
- **Jest**: Used by 40 libraries (76% of codebase) - existing/legacy libraries
|
||||
- **Vitest**: Used by 13 libraries (24% of codebase) - newer libraries and migrations
|
||||
- **Testing Utilities Migration**:
|
||||
- **Angular Testing Utilities** (TestBed, ComponentFixture): Preferred for new tests (25 test files)
|
||||
- **Spectator**: Legacy testing utility for existing tests (56 test files)
|
||||
- **ng-mocks**: For advanced mocking scenarios and child component mocking
|
||||
|
||||
### Migration Status by Domain
|
||||
- **Migrated to Vitest**: `crm-data-access`, `checkout-*`, several `ui/*` components, `remission/*` libraries
|
||||
- **Still on Jest**: Core `oms/*` libraries, main application, most legacy libraries
|
||||
- **New Libraries**: Should use Vitest + Angular Testing Utilities from the start
|
||||
|
||||
### 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
|
||||
- Use AAA pattern (Arrange-Act-Assert) consistently across both frameworks
|
||||
- Include E2E testing attributes (`data-what`, `data-which`, dynamic `data-*` attributes) in HTML templates
|
||||
- Mock external dependencies and child components using appropriate framework tools
|
||||
- Verify E2E attributes are correctly applied in component unit tests
|
||||
|
||||
## State Management
|
||||
- **NgRx**: Store, Effects, Entity, Component Store, Signals
|
||||
- **RxJS**: For reactive programming patterns
|
||||
- **NgRx Signals**: Primary state management with modern functional approach using `signalStore()`
|
||||
- **Entity Management**: Uses `withEntities()` for normalized data storage
|
||||
- **Session Persistence**: State persistence with `withStorage()` using SessionStorageProvider
|
||||
- **Reactive Methods**: `rxMethod()` with `takeUntilKeydownEscape()` for user-cancellable operations
|
||||
- **Custom RxJS Operators**: Specialized operators like `takeUntilAborted()`, `takeUntilKeydown()`
|
||||
- **Error Handling**: `tapResponse()` for handling success/error states in stores
|
||||
- **Lifecycle Hooks**: `withHooks()` for cleanup and initialization (e.g., orphaned entity cleanup)
|
||||
|
||||
## Styling
|
||||
- **Tailwind CSS**: Primary styling framework with custom configuration
|
||||
- **SCSS**: For component-specific styles
|
||||
- **Custom Tailwind plugins**: For buttons, inputs, menus, typography
|
||||
## Styling and Design System
|
||||
- **Tailwind CSS**: Primary styling framework with extensive ISA-specific customization
|
||||
- **Custom Breakpoints**: `isa-desktop` (1024px), `isa-desktop-l` (1440px), `isa-desktop-xl` (1920px)
|
||||
- **Brand Color System**: Comprehensive `isa-*` color palette with semantic naming
|
||||
- **Design Tokens**: Consistent spacing, typography, shadows, and border-radius values
|
||||
- **Custom Tailwind Plugins** (7 plugins): `button`, `typography`, `menu`, `label`, `input`, `section`, `select-bullet`
|
||||
- **SCSS Integration**: Component-scoped SCSS with BEM-like naming conventions
|
||||
- **CSS Custom Properties**: Extensive use of CSS variables for theming and component variants
|
||||
- **Typography System**: 14 custom text utilities (`.isa-text-heading-1-bold`, `.isa-text-body-2-regular`)
|
||||
- **UI Component Libraries**: 15 specialized UI libraries with consistent API patterns
|
||||
- **Storybook Integration**: Component documentation and development environment
|
||||
|
||||
## 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
|
||||
## API Integration and Data Access
|
||||
- **Generated Swagger Clients**: 10 auto-generated TypeScript clients from OpenAPI specs in `generated/swagger/`
|
||||
- **Available APIs**: availability-api, cat-search-api, checkout-api, crm-api, eis-api, inventory-api, isa-api, oms-api, print-api, wws-api
|
||||
- **Generation Tool**: `ng-swagger-gen` with custom configurations per API
|
||||
- **Post-processing**: Automatic Unicode character cleanup via `tools/fix-files.js`
|
||||
- **Data Access Architecture**:
|
||||
- **Business Logic Services**: Domain-specific services that wrap generated API clients
|
||||
- **Type Safety**: Full TypeScript integration with Zod schema validation
|
||||
- **Error Handling**: Global HTTP interceptor with custom error classes and automatic re-authentication
|
||||
- **Configuration Management**: Dynamic API endpoint configuration through dependency injection
|
||||
- **Request Cancellation**: Built-in support via AbortSignal and custom operators
|
||||
- **Service Patterns**:
|
||||
- **Modern Injection**: Uses `inject()` function with private field pattern
|
||||
- **Logging Integration**: Comprehensive logging throughout data access layer
|
||||
- **Consistent API**: Standardized service interfaces across all domains
|
||||
|
||||
## 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
|
||||
- **Node.js >= 22.0.0**: Required Node version (specified in package.json engines)
|
||||
- **npm >= 10.0.0**: Required npm version (specified in package.json engines)
|
||||
- **Nx 21.3.2**: Monorepo build system and development tools
|
||||
- **Vite 6.3.5**: Build tool for faster development and testing (used with Vitest)
|
||||
|
||||
## 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
|
||||
## Important Conventions and Patterns
|
||||
|
||||
## Development Workflow Tips
|
||||
- Always use `npx nx run` pattern for executing tasks
|
||||
### Library Organization
|
||||
- **Naming Pattern**: `[domain]-[layer]-[feature]` (e.g., `oms-feature-return-search`, `ui-buttons`)
|
||||
- **Path Aliases**: `@isa/[domain]/[layer]/[feature]` (e.g., `@isa/oms/data-access`, `@isa/ui/buttons`)
|
||||
- **Project Names**: Found in each library's `project.json` file, following consistent naming
|
||||
|
||||
### Component Architecture
|
||||
- **Standalone Components**: All new components must be standalone with explicit imports
|
||||
- **Component Prefixes**: Domain-specific prefixes for clear identification
|
||||
- OMS features: `oms-feature-*` (e.g., `oms-feature-return-search-main`)
|
||||
- Remission features: `remi-*`
|
||||
- UI components: `ui-*`
|
||||
- Core utilities: `core-*`
|
||||
- **Signal-based Inputs**: Use Angular signals (`input()`, `computed()`) for reactive properties
|
||||
- **Host Binding**: Dynamic CSS classes via Angular host properties
|
||||
|
||||
### Dependency Rules
|
||||
- **Unidirectional Dependencies**: Feature → Shared/UI → Data Access → Infrastructure
|
||||
- **Import Boundaries**: Use path aliases, avoid relative imports across domain boundaries
|
||||
- **Generated API Imports**: Import from `@generated/swagger/[api-name]` for API clients
|
||||
|
||||
### Code Quality
|
||||
- **Modern Angular Patterns**: Prefer `inject()` over constructor injection
|
||||
- **Type Safety**: Use Zod schemas for runtime validation alongside TypeScript
|
||||
- **Error Handling**: Custom error classes with specific error codes
|
||||
- **E2E Testing**: Always include `data-what` and `data-which` attributes in templates
|
||||
|
||||
## Development Workflow and Best Practices
|
||||
|
||||
### Essential Commands
|
||||
- **Development**: `npm start` (serves with SSL enabled by default)
|
||||
- **Testing**: `npm test` (runs all library tests, skips main app)
|
||||
- **Building**: `npm run build` (development), `npm run build-prod` (production)
|
||||
- **Code Generation**: `npm run generate:swagger` (regenerates all API clients)
|
||||
- **Code Quality**: `npm run prettier` (formats all files), `npm run pretty-quick` (staged files only)
|
||||
|
||||
### Nx Workflow Optimization
|
||||
- Always use `npx nx run` pattern for executing specific 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`
|
||||
- Use affected commands for CI/CD optimization: `npx nx affected:test`
|
||||
- Visualize project dependencies: `npx nx graph`
|
||||
- The default git branch is `develop` (not `main`)
|
||||
|
||||
## 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
|
||||
### Testing Best Practices
|
||||
- **New Libraries**: Use Vitest + Angular Testing Utilities
|
||||
- **Legacy Libraries**: Continue using Jest + Spectator until migrated
|
||||
- **Migration Priority**: UI components and new domains migrate first
|
||||
- **E2E Attributes**: Verify `data-what`, `data-which`, and dynamic `data-*` attributes in tests
|
||||
- **Mock Strategy**: Use appropriate framework tools (Spectator's `mocks` array vs TestBed providers)
|
||||
|
||||
### Code Quality Guidelines
|
||||
- **Linting**: ESLint flat config with Nx dependency checks
|
||||
- **Formatting**: Prettier with pre-commit hooks via Husky and lint-staged
|
||||
- **Type Safety**: Zod validation for API boundaries, TypeScript strict mode
|
||||
- **Bundle Optimization**: Monitor bundle sizes (2MB warning, 5MB error for main bundle)
|
||||
- **Performance**: Use NgRx Signals for reactive state management with session persistence
|
||||
|
||||
## Development Notes and Guidelines
|
||||
|
||||
### Getting Started
|
||||
- **Application Startup**: Only `isa-app` can be started - it's the main application entry point
|
||||
- **SSL Development**: The development server runs with SSL by default (`npm start`), which is crucial for production-like authentication flows
|
||||
- **Node Requirements**: Ensure Node.js ≥22.0.0 and npm ≥10.0.0 before starting development
|
||||
- **First-Time Setup**: After cloning, run `npm install` then `npm start` to verify everything works
|
||||
|
||||
### Essential Documentation References
|
||||
- **Testing Guidelines**: Review `docs/guidelines/testing.md` before writing any tests - it covers the Jest→Vitest migration, Spectator→Angular Testing Utilities transition, and E2E attribute requirements
|
||||
- **Code Review Standards**: Follow the structured review process in `.github/review-instructions.md` with categorized feedback (🚨 Critical, ❗ Minor, ⚠️ Warnings, ✅ Good Practices)
|
||||
- **E2E Testing Requirements**: Always include `data-what`, `data-which`, and dynamic `data-*` attributes in HTML templates - these are essential for automated testing by QA colleagues
|
||||
|
||||
### Library Development Patterns
|
||||
- **New Library Creation**: Use Nx generators with domain-specific naming (`[domain]-[layer]-[feature]`)
|
||||
- **Standalone Components**: All new components must be standalone with explicit imports - no more NgModules
|
||||
- **Testing Framework Selection**:
|
||||
- **New libraries**: Use Vitest + Angular Testing Utilities
|
||||
- **Existing libraries**: Continue with Jest + Spectator until migrated
|
||||
- **Path Aliases**: Always use `@isa/[domain]/[layer]/[feature]` - avoid relative imports across domain boundaries
|
||||
|
||||
### API Integration Workflow
|
||||
- **Swagger Generation**: Run `npm run generate:swagger` to regenerate all 10 API clients when backend changes
|
||||
- **Data Services**: Wrap generated API clients in domain-specific data-access services with proper error handling and Zod validation
|
||||
- **State Management**: Use NgRx Signals with `signalStore()`, entity management, and session persistence for complex state
|
||||
|
||||
### Performance and Quality Considerations
|
||||
- **Bundle Monitoring**: Watch bundle sizes (2MB warning, 5MB error for main bundle)
|
||||
- **Testing Cache**: Always use `--skip-cache` flag when running tests to ensure reliable results
|
||||
- **Code Quality**: Pre-commit hooks enforce Prettier formatting and ESLint rules automatically
|
||||
- **Memory Management**: Clean up subscriptions and use OnPush change detection for optimal performance
|
||||
|
||||
### Common Troubleshooting
|
||||
- **Build Issues**: Check Node version and run `npm install` if encountering module resolution errors
|
||||
- **Test Failures**: Use `--skip-cache` flag and ensure test isolation (no shared state between tests)
|
||||
- **SSL Certificates**: Development server uses SSL - accept certificate warnings in browser for localhost
|
||||
- **Import Errors**: Verify path aliases in `tsconfig.base.json` and use absolute imports for cross-library dependencies
|
||||
|
||||
### Domain-Specific Conventions
|
||||
- **Component Prefixes**: Use `oms-feature-*` for OMS, `remi-*` for remission, `ui-*` for shared components
|
||||
- **Git Workflow**: Default branch is `develop` (not main), use conventional commits without co-author tags
|
||||
- **Design System**: Use ISA-specific Tailwind utilities (`isa-accent-*`, `isa-text-*`) and custom breakpoints (`isa-desktop-*`)
|
||||
- **Logging**: Use centralized logging service (`@isa/core/logging`) with contextual information for debugging
|
||||
|
||||
## Claude Code Workflow Definition
|
||||
|
||||
Based on comprehensive analysis of development patterns and available tools/MCP servers, here's the formal workflow for handling requests using the Task tool with specialized subagents:
|
||||
|
||||
### Phase 1: Request Analysis and Routing
|
||||
|
||||
#### 1.1 Initial Analysis (Always Use Subagents)
|
||||
**Trigger**: Any user request
|
||||
**Subagents**: `general-purpose` (for research) + domain specialists as needed
|
||||
|
||||
```
|
||||
1. Parse request intent and complexity level
|
||||
2. Classify request type:
|
||||
- Feature Development (new functionality)
|
||||
- Bug Fix/Maintenance (corrections)
|
||||
- Code Quality/Refactoring (improvements)
|
||||
- Testing/QA (validation)
|
||||
- Architecture/Design (structure)
|
||||
- Research/Investigation (exploration)
|
||||
3. Assess information completeness and ambiguity
|
||||
4. Determine required domains and expertise
|
||||
```
|
||||
|
||||
#### 1.2 Clarification Decision Matrix
|
||||
```
|
||||
IF (high ambiguity + high impact) → REQUEST clarification
|
||||
IF (medium ambiguity + architectural changes) → REQUEST optional clarification
|
||||
IF (low ambiguity OR simple changes) → PROCEED with documented assumptions
|
||||
```
|
||||
|
||||
### Phase 2: Task Decomposition and Agent Assignment
|
||||
|
||||
#### 2.1 Complexity-Based Routing
|
||||
|
||||
**Simple Tasks (Single file, isolated change)**:
|
||||
- Route directly to specialist (`frontend-developer`, `typescript-pro`, etc.)
|
||||
- Single quality gate at completion
|
||||
|
||||
**Moderate Tasks (Multiple related files, limited scope)**:
|
||||
- Decompose into 2-4 parallel subagent tasks
|
||||
- Example: `angular-mcp` + `test-automator` + `docs-architect`
|
||||
|
||||
**Complex Tasks (Multiple domains, significant scope)**:
|
||||
- Hierarchical task tree with dependencies
|
||||
- Example: `general-purpose` (analysis) → `nx-mcp` (structure) → `frontend-developer` + `test-automator` (parallel) → `code-reviewer` (validation)
|
||||
|
||||
**Architectural Tasks (System-wide changes)**:
|
||||
- Multi-phase with user approval gates
|
||||
- Example: `architect-review` → user approval → `frontend-developer` + `backend-architect` + `database-optimizer` → `performance-engineer` (validation)
|
||||
|
||||
#### 2.2 Optimal Agent Combinations
|
||||
|
||||
**Feature Development Pattern**:
|
||||
```
|
||||
context7 (fetch latest APIs)
|
||||
→ frontend-developer + test-automator (parallel TDD)
|
||||
→ ui-ux-designer (if UI changes)
|
||||
→ code-reviewer (quality validation)
|
||||
```
|
||||
|
||||
**Bug Fix Pattern**:
|
||||
```
|
||||
error-detective (analyze issue)
|
||||
→ debugger (reproduce and fix)
|
||||
→ test-automator (regression tests)
|
||||
→ performance-engineer (if performance-related)
|
||||
```
|
||||
|
||||
**Refactoring Pattern**:
|
||||
```
|
||||
general-purpose (understand current state)
|
||||
→ legacy-modernizer (plan modernization)
|
||||
→ test-automator (safety tests)
|
||||
→ frontend-developer (implement changes)
|
||||
→ architect-review (validate architecture)
|
||||
```
|
||||
|
||||
### Phase 3: Execution with Progressive Quality Gates
|
||||
|
||||
#### 3.1 Standard Execution Flow
|
||||
```
|
||||
1. Each subagent receives atomic task with clear requirements
|
||||
2. Subagent performs implementation with embedded quality checks
|
||||
3. Results validated against project standards (E2E attributes, naming conventions)
|
||||
4. Integration compatibility verified
|
||||
5. Progress reported to user with next steps
|
||||
```
|
||||
|
||||
#### 3.2 Quality Gates by Task Type
|
||||
- **Code Changes**: `test-automator` → `code-reviewer` → `performance-engineer`
|
||||
- **UI Changes**: `ui-visual-validator` → `frontend-security-coder` → `code-reviewer`
|
||||
- **Architecture Changes**: `architect-review` → user approval → implementation → `performance-engineer`
|
||||
- **API Changes**: `api-documenter` → `backend-security-coder` → integration tests
|
||||
|
||||
### Phase 4: Integration and Validation
|
||||
|
||||
#### 4.1 Continuous Validation
|
||||
```
|
||||
- Every file change triggers appropriate quality subagent
|
||||
- Integration points validated by architect-review
|
||||
- Performance impacts assessed by performance-engineer
|
||||
- Security changes reviewed by security-auditor
|
||||
```
|
||||
|
||||
#### 4.2 User Communication Strategy
|
||||
```
|
||||
- Real-time: Critical decisions and blockers
|
||||
- Milestone-based: Major phase completions
|
||||
- Exception-driven: Alternative approaches or issues
|
||||
- Summary-based: Long-running workflow progress
|
||||
```
|
||||
|
||||
### Specialized Subagent Usage Patterns
|
||||
|
||||
#### **Always Use These Subagents Proactively**:
|
||||
- `general-purpose`: For codebase analysis, research, and complex multi-step tasks
|
||||
- Available specialist agents based on task requirements (see full list below)
|
||||
|
||||
#### **Available MCP Server Integration**:
|
||||
- **nx-mcp**: `nx_workspace`, `nx_project_details`, `nx_run_generator`, `nx_visualize_graph`, etc.
|
||||
- **angular-mcp**: `list_projects`, `search_documentation`
|
||||
- **context7**: `resolve-library-id`, `get-library-docs` for latest package documentation
|
||||
|
||||
#### **Project-Relevant Subagent Types**:
|
||||
|
||||
**Tier 1 - Essential (Most Frequently Needed)**:
|
||||
- `frontend-developer`: Angular 20.1.2 feature development, standalone components, domain library implementation
|
||||
- `typescript-pro`: Advanced TypeScript 5.8.3 patterns, type system optimization, interface design
|
||||
- `test-automator`: Jest→Vitest migration, Spectator→Angular Testing Utilities, unit testing, E2E attributes
|
||||
- `ui-ux-designer`: Tailwind CSS design system, UI component libraries, responsive design
|
||||
|
||||
**Tier 2 - Important (Regularly Needed)**:
|
||||
- `code-reviewer`: ESLint compliance, Angular best practices, code quality validation
|
||||
- `performance-engineer`: Angular optimization, bundle analysis, NgRx performance patterns
|
||||
- `api-documenter`: Swagger/OpenAPI integration, API client documentation
|
||||
- `docs-architect`: Technical documentation, architecture guides, CLAUDE.md maintenance
|
||||
|
||||
**Tier 3 - Specialized (Domain-Specific)**:
|
||||
- `architect-review`: Nx monorepo architecture, domain-driven design validation
|
||||
- `frontend-security-coder`: Angular security patterns, XSS prevention, authentication flows
|
||||
- `deployment-engineer`: Angular build pipelines, Nx CI/CD, npm script automation
|
||||
- `debugger`: Error analysis, RxJS debugging, state management troubleshooting
|
||||
|
||||
**Cross-Cutting Support**:
|
||||
- `general-purpose`: Complex analysis, codebase research, multi-domain investigations
|
||||
- `error-detective`: Production issue investigation, log analysis, performance bottlenecks
|
||||
|
||||
### Escalation and Error Handling
|
||||
|
||||
#### Immediate Escalation Triggers:
|
||||
- Subagent cannot access required files or resources
|
||||
- Conflicting requirements between parallel tasks
|
||||
- Security vulnerabilities discovered
|
||||
- Breaking changes with no compatibility path
|
||||
|
||||
#### Recovery Hierarchy:
|
||||
1. Subagent self-resolution (retry with different approach)
|
||||
2. Alternative subagent assignment (different specialist)
|
||||
3. Task redecomposition (break down further)
|
||||
4. User consultation (clarification or decision needed)
|
||||
|
||||
### Example Workflow: "Add Dark Mode Feature"
|
||||
|
||||
```
|
||||
1. ANALYSIS PHASE:
|
||||
Task(general-purpose, "Research Angular/Tailwind dark mode patterns and analyze ISA theme system")
|
||||
|
||||
2. PLANNING PHASE:
|
||||
Task(ui-ux-designer, "Design dark mode integration with ISA color system and Tailwind classes")
|
||||
Task(frontend-developer, "Plan component modifications and theme service architecture")
|
||||
|
||||
3. IMPLEMENTATION PHASE (can run in parallel):
|
||||
Task(frontend-developer, "Implement Angular theme service and component modifications")
|
||||
Task(typescript-pro, "Create TypeScript interfaces and type-safe theme system")
|
||||
Task(test-automator, "Create Jest/Vitest tests with E2E attributes for theme functionality")
|
||||
|
||||
4. VALIDATION PHASE:
|
||||
Task(code-reviewer, "Review Angular patterns, NgRx integration, and code quality")
|
||||
Task(performance-engineer, "Assess bundle size impact and runtime performance")
|
||||
|
||||
5. INTEGRATION PHASE:
|
||||
Task(test-automator, "Run full Nx test suite and validate E2E attributes")
|
||||
Task(docs-architect, "Update Storybook documentation and component usage guides")
|
||||
```
|
||||
|
||||
### MCP Server Integration Workflow: "Integrate New Angular Library"
|
||||
|
||||
```
|
||||
1. RESEARCH PHASE:
|
||||
- Use mcp__context7__resolve-library-id to find the library
|
||||
- Use mcp__context7__get-library-docs to understand APIs
|
||||
- Use mcp__angular-mcp__search_documentation for Angular integration patterns
|
||||
|
||||
2. PROJECT SETUP:
|
||||
- Use mcp__nx-mcp__nx_generators to find appropriate generators
|
||||
- Use mcp__nx-mcp__nx_run_generator to scaffold integration components
|
||||
- Use mcp__nx-mcp__nx_project_details to understand impact scope
|
||||
|
||||
3. IMPLEMENTATION WITH SUBAGENTS:
|
||||
Task(typescript-pro, "Create TypeScript interfaces for library integration")
|
||||
Task(frontend-developer, "Implement Angular service wrapping the library")
|
||||
Task(test-automator, "Create unit and integration tests")
|
||||
|
||||
4. VALIDATION:
|
||||
- Use mcp__nx-mcp__nx_visualize_graph to verify dependency relationships
|
||||
- Use mcp__nx-mcp__nx_current_running_tasks_details to monitor builds
|
||||
Task(code-reviewer, "Review integration patterns and code quality")
|
||||
```
|
||||
|
||||
This comprehensive workflow leverages ALL available MCP servers and specialized subagents for maximum efficiency, with each agent handling both analysis AND implementation tasks according to their expertise.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
type Meta,
|
||||
type StoryObj,
|
||||
applicationConfig,
|
||||
argsToTemplate,
|
||||
moduleMetadata,
|
||||
} from '@storybook/angular';
|
||||
import { ProductInfoRedemptionComponent } from '@isa/checkout/shared/product-info';
|
||||
import { provideProductImageUrl } from '@isa/shared/product-image';
|
||||
import { provideProductRouterLinkBuilder } from '@isa/shared/product-router-link';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
const meta: Meta<ProductInfoRedemptionComponent> = {
|
||||
title: 'checkout/shared/product-info/ProductInfoRedemption',
|
||||
component: ProductInfoRedemptionComponent,
|
||||
decorators: [
|
||||
applicationConfig({
|
||||
providers: [
|
||||
provideRouter([
|
||||
{ path: ':ean', component: ProductInfoRedemptionComponent },
|
||||
]),
|
||||
],
|
||||
}),
|
||||
moduleMetadata({
|
||||
providers: [
|
||||
provideProductImageUrl('https://produktbilder-test.paragon-data.net'),
|
||||
provideProductRouterLinkBuilder((ean: string) => ean),
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<ProductInfoRedemptionComponent>;
|
||||
|
||||
export const Primary: Story = {
|
||||
args: {
|
||||
item: {
|
||||
product: {
|
||||
ean: '9783498007706',
|
||||
name: 'Die Assistentin',
|
||||
contributors: 'Wahl, Caroline',
|
||||
format: 'TB',
|
||||
formatDetail: 'Taschenbuch (Kartoniert)',
|
||||
manufacturer: 'Test Manufacturer',
|
||||
publicationDate: '2023-01-01',
|
||||
},
|
||||
redemptionPoints: 100,
|
||||
},
|
||||
orientation: 'vertical',
|
||||
},
|
||||
argTypes: {
|
||||
item: { control: 'object' },
|
||||
orientation: {
|
||||
control: { type: 'radio' },
|
||||
options: ['horizontal', 'vertical'],
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
type Meta,
|
||||
type StoryObj,
|
||||
applicationConfig,
|
||||
argsToTemplate,
|
||||
moduleMetadata,
|
||||
} from '@storybook/angular';
|
||||
|
||||
import { StockInfoComponent } from '@isa/checkout/shared/product-info';
|
||||
import { RemissionStockService } from '@isa/remission/data-access';
|
||||
import { StockInfoDTO } from '@generated/swagger/inventory-api';
|
||||
|
||||
const meta: Meta<StockInfoComponent> = {
|
||||
title: 'checkout/shared/product-info/StockInfoComponent',
|
||||
component: StockInfoComponent,
|
||||
decorators: [
|
||||
applicationConfig({
|
||||
providers: [],
|
||||
}),
|
||||
moduleMetadata({
|
||||
imports: [],
|
||||
providers: [
|
||||
{
|
||||
provide: RemissionStockService,
|
||||
useValue: {
|
||||
fetchStock: async (
|
||||
params: { itemIds: number[]; assignedStockId?: number },
|
||||
abortSignal?: AbortSignal,
|
||||
) => {
|
||||
const result: StockInfoDTO = {
|
||||
itemId: params.itemIds[0],
|
||||
stockId: params.assignedStockId,
|
||||
inStock: 14,
|
||||
};
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
return [result];
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<StockInfoComponent>;
|
||||
|
||||
export const Primary: Story = {
|
||||
args: {
|
||||
item: {
|
||||
id: 123456,
|
||||
catalogAvailability: {
|
||||
ssc: '999',
|
||||
sscText: 'Lieferbar in 1-3 Werktagen',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,48 +1,57 @@
|
||||
import { argsToTemplate, Meta } from '@storybook/angular';
|
||||
import { ProductFormatIconGroup } from '@isa/icons';
|
||||
import { ProductFormatComponent } from '@isa/shared/product-foramt';
|
||||
|
||||
type ProductFormatInputs = {
|
||||
format: string;
|
||||
formatDetail: string;
|
||||
};
|
||||
|
||||
const options = Object.keys(ProductFormatIconGroup).map((key) =>
|
||||
key.toUpperCase(),
|
||||
);
|
||||
|
||||
const meta: Meta<ProductFormatInputs> = {
|
||||
title: 'shared/product-format/ProductFormat',
|
||||
component: ProductFormatComponent,
|
||||
argTypes: {
|
||||
format: {
|
||||
control: {
|
||||
type: 'select',
|
||||
},
|
||||
options,
|
||||
description: 'The product format to display the icon for.',
|
||||
defaultValue: options[0],
|
||||
},
|
||||
formatDetail: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
description: 'The detail text for the product format.',
|
||||
defaultValue: 'Default Format Detail',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
format: options[0], // Default value for the product format
|
||||
formatDetail: 'Default Format Detail', // Default value for the format detail
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<shared-product-format ${argsToTemplate(args)}></shared-product-format>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = typeof meta;
|
||||
|
||||
export const Default: Story = {};
|
||||
import { argsToTemplate, Meta } from '@storybook/angular';
|
||||
import { ProductFormatIconGroup } from '@isa/icons';
|
||||
import { ProductFormatComponent } from '@isa/shared/product-foramt';
|
||||
|
||||
type ProductFormatInputs = {
|
||||
format: string;
|
||||
formatDetail: string;
|
||||
formatDetailsBold: boolean;
|
||||
};
|
||||
|
||||
const options = Object.keys(ProductFormatIconGroup).map((key) =>
|
||||
key.toUpperCase(),
|
||||
);
|
||||
|
||||
const meta: Meta<ProductFormatInputs> = {
|
||||
title: 'shared/product-format/ProductFormat',
|
||||
component: ProductFormatComponent,
|
||||
argTypes: {
|
||||
format: {
|
||||
control: {
|
||||
type: 'select',
|
||||
},
|
||||
options,
|
||||
description: 'The product format to display the icon for.',
|
||||
defaultValue: options[0],
|
||||
},
|
||||
formatDetail: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
description: 'The detail text for the product format.',
|
||||
defaultValue: 'Default Format Detail',
|
||||
},
|
||||
formatDetailsBold: {
|
||||
control: {
|
||||
type: 'boolean',
|
||||
},
|
||||
description: 'Whether the format detail text should be bold.',
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
args: {
|
||||
format: options[0], // Default value for the product format
|
||||
formatDetail: 'Default Format Detail', // Default value for the format detail
|
||||
formatDetailsBold: false, // Default value for the format details bold
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<shared-product-format ${argsToTemplate(args)}></shared-product-format>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = typeof meta;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { ItemDTO } from '@generated/swagger/cat-search-api';
|
||||
import { Product } from './product';
|
||||
import { Availability } from './availability';
|
||||
|
||||
export interface Item extends ItemDTO {
|
||||
id: number;
|
||||
product: Product;
|
||||
catalogAvailability: Availability;
|
||||
}
|
||||
import { ItemDTO } from '@generated/swagger/cat-search-api';
|
||||
import { Product } from './product';
|
||||
import { Availability } from './availability';
|
||||
|
||||
export interface Item extends ItemDTO {
|
||||
id: number;
|
||||
product: Product;
|
||||
catalogAvailability: Availability;
|
||||
redemptionPoints?: number;
|
||||
}
|
||||
|
||||
7
libs/checkout/shared/product-info/README.md
Normal file
7
libs/checkout/shared/product-info/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# checkout-shared-product-info
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test checkout-shared-product-info` to execute the unit tests.
|
||||
34
libs/checkout/shared/product-info/eslint.config.cjs
Normal file
34
libs/checkout/shared/product-info/eslint.config.cjs
Normal file
@@ -0,0 +1,34 @@
|
||||
const nx = require('@nx/eslint-plugin');
|
||||
const baseConfig = require('../../../../eslint.config.js');
|
||||
|
||||
module.exports = [
|
||||
...baseConfig,
|
||||
...nx.configs['flat/angular'],
|
||||
...nx.configs['flat/angular-template'],
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
rules: {
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: 'checkout',
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'element',
|
||||
prefix: 'checkout',
|
||||
style: 'kebab-case',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.html'],
|
||||
// Override or add rules here
|
||||
rules: {},
|
||||
},
|
||||
];
|
||||
20
libs/checkout/shared/product-info/project.json
Normal file
20
libs/checkout/shared/product-info/project.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "checkout-shared-product-info",
|
||||
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "libs/checkout/shared/product-info/src",
|
||||
"prefix": "checkout",
|
||||
"projectType": "library",
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {
|
||||
"executor": "@nx/vite:test",
|
||||
"outputs": ["{options.reportsDirectory}"],
|
||||
"options": {
|
||||
"reportsDirectory": "../../../../coverage/libs/checkout/shared/product-info"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint"
|
||||
}
|
||||
}
|
||||
}
|
||||
2
libs/checkout/shared/product-info/src/index.ts
Normal file
2
libs/checkout/shared/product-info/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './lib/product-info/product-info-redemption.component';
|
||||
export * from './lib/stock-info/stock-info.component';
|
||||
@@ -0,0 +1,15 @@
|
||||
:host {
|
||||
@apply grid grid-flow-col gap-6 text-neutral-900;
|
||||
}
|
||||
|
||||
:host.vertical {
|
||||
@apply grid-flow-row;
|
||||
}
|
||||
|
||||
shared-product-format span {
|
||||
@apply isa-text-body-2-bold text-isa-secondary-900;
|
||||
}
|
||||
|
||||
.lh-1 {
|
||||
line-height: 1;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
@let prd = item().product;
|
||||
@let rPoints = item().redemptionPoints;
|
||||
<div class="grid grid-cols-[auto,1fr] gap-6">
|
||||
<div>
|
||||
<img
|
||||
sharedProductRouterLink
|
||||
sharedProductImage
|
||||
[ean]="prd.ean"
|
||||
[alt]="prd.name"
|
||||
class="checkout-product-info-redemption__image w-14"
|
||||
data-what="product-image"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-1 flex-col justify-between gap-1">
|
||||
<div class="isa-text-body-2-bold">{{ prd.contributors }}</div>
|
||||
<div
|
||||
[class.isa-text-body-2-regular]="orientation() === 'horizontal'"
|
||||
[class.isa-text-subtitle-1-regular]="orientation() === 'vertical'"
|
||||
>
|
||||
{{ prd.name }}
|
||||
</div>
|
||||
<div class="isa-text-body-2-regular">
|
||||
<span class="isa-text-body-2-bold">{{ rPoints }}</span>
|
||||
Lesepunkte
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-1 flex-col justify-between gap-1"
|
||||
[class.ml-20]="orientation() === 'vertical'"
|
||||
>
|
||||
<shared-product-format
|
||||
[format]="prd.format"
|
||||
[formatDetail]="prd.formatDetail"
|
||||
[formatDetailsBold]="true"
|
||||
></shared-product-format>
|
||||
<div class="isa-text-body-2-regular text-neutral-600">
|
||||
{{ prd.manufacturer }} | {{ prd.ean }}
|
||||
</div>
|
||||
<div class="isa-text-body-2-regular text-neutral-600">
|
||||
{{ prd.publicationDate | date: 'dd. MMMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||
import { Product } from '@isa/catalogue/data-access';
|
||||
import { ProductImageDirective } from '@isa/shared/product-image';
|
||||
import { ProductRouterLinkDirective } from '@isa/shared/product-router-link';
|
||||
import { ProductFormatComponent } from '@isa/shared/product-foramt';
|
||||
import { DatePipe } from '@angular/common';
|
||||
|
||||
export type ProductInfoItem = {
|
||||
product: Pick<
|
||||
Product,
|
||||
| 'ean'
|
||||
| 'name'
|
||||
| 'contributors'
|
||||
| 'format'
|
||||
| 'formatDetail'
|
||||
| 'manufacturer'
|
||||
| 'publicationDate'
|
||||
>;
|
||||
redemptionPoints: number;
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'checkout-product-info-redemption',
|
||||
templateUrl: './product-info-redemption.component.html',
|
||||
styleUrls: ['./product-info-redemption.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [
|
||||
ProductImageDirective,
|
||||
ProductRouterLinkDirective,
|
||||
ProductFormatComponent,
|
||||
DatePipe,
|
||||
],
|
||||
host: {
|
||||
'[class]': '[orientation()]',
|
||||
},
|
||||
})
|
||||
export class ProductInfoRedemptionComponent {
|
||||
item = input.required<ProductInfoItem>();
|
||||
|
||||
orientation = input<'horizontal' | 'vertical'>('vertical');
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply grid grid-flow-row gap-2;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
@let itm = item();
|
||||
<div
|
||||
class="grid grid-cols-[auto,1fr] gap-2 items-center text-isa-secondary-900"
|
||||
>
|
||||
<ng-icon size="1.5rem" name="isaFiliale"></ng-icon>
|
||||
<div class="isa-text-body-2-bold">
|
||||
@if (loading()) {
|
||||
<ui-skeleton-loader class="w-8 h-5 inline-block"></ui-skeleton-loader>
|
||||
} @else {
|
||||
{{ inStock() }}x
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-isa-neutral-600 isa-text-body-2-regular">
|
||||
{{ itm.catalogAvailability.ssc }} - {{ itm.catalogAvailability.sscText }}
|
||||
</div>
|
||||
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
inject,
|
||||
input,
|
||||
resource,
|
||||
} from '@angular/core';
|
||||
import { RemissionStockService } from '@isa/remission/data-access';
|
||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||
import { isaFiliale } from '@isa/icons';
|
||||
import { Item } from '@isa/catalogue/data-access';
|
||||
import { SkeletonLoaderComponent } from '@isa/ui/skeleton-loader';
|
||||
|
||||
export type StockInfoItem = {
|
||||
id: Item['id'];
|
||||
catalogAvailability: Required<
|
||||
Pick<Item['catalogAvailability'], 'ssc' | 'sscText'>
|
||||
>;
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'checkout-stock-info',
|
||||
templateUrl: './stock-info.component.html',
|
||||
styleUrls: ['./stock-info.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [NgIconComponent, SkeletonLoaderComponent],
|
||||
providers: [provideIcons({ isaFiliale })],
|
||||
})
|
||||
export class StockInfoComponent {
|
||||
#stockService = inject(RemissionStockService);
|
||||
|
||||
item = input.required<StockInfoItem>();
|
||||
|
||||
stockResource = resource({
|
||||
params: () => this.item().id,
|
||||
loader: ({ params, abortSignal }) =>
|
||||
this.#stockService.fetchStock(
|
||||
{
|
||||
itemIds: [params],
|
||||
},
|
||||
abortSignal,
|
||||
),
|
||||
});
|
||||
|
||||
inStock = computed(() => {
|
||||
if (this.stockResource.hasValue()) {
|
||||
const stock = this.stockResource.value();
|
||||
return stock[0]?.inStock ?? 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
loading = computed(() => this.stockResource.isLoading() && !this.inStock());
|
||||
}
|
||||
13
libs/checkout/shared/product-info/src/test-setup.ts
Normal file
13
libs/checkout/shared/product-info/src/test-setup.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import '@angular/compiler';
|
||||
import '@analogjs/vitest-angular/setup-zone';
|
||||
|
||||
import {
|
||||
BrowserTestingModule,
|
||||
platformBrowserTesting,
|
||||
} from '@angular/platform-browser/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserTestingModule,
|
||||
platformBrowserTesting(),
|
||||
);
|
||||
30
libs/checkout/shared/product-info/tsconfig.json
Normal file
30
libs/checkout/shared/product-info/tsconfig.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "preserve"
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"typeCheckHostBindings": true,
|
||||
"strictTemplates": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
27
libs/checkout/shared/product-info/tsconfig.lib.json
Normal file
27
libs/checkout/shared/product-info/tsconfig.lib.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": []
|
||||
},
|
||||
"exclude": [
|
||||
"src/**/*.spec.ts",
|
||||
"src/test-setup.ts",
|
||||
"jest.config.ts",
|
||||
"src/**/*.test.ts",
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx"
|
||||
],
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
29
libs/checkout/shared/product-info/tsconfig.spec.json
Normal file
29
libs/checkout/shared/product-info/tsconfig.spec.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../../dist/out-tsc",
|
||||
"types": [
|
||||
"vitest/globals",
|
||||
"vitest/importMeta",
|
||||
"vite/client",
|
||||
"node",
|
||||
"vitest"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
"files": ["src/test-setup.ts"]
|
||||
}
|
||||
28
libs/checkout/shared/product-info/vite.config.mts
Normal file
28
libs/checkout/shared/product-info/vite.config.mts
Normal file
@@ -0,0 +1,28 @@
|
||||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import angular from '@analogjs/vite-plugin-angular';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../../../node_modules/.vite/libs/checkout/shared/product-info',
|
||||
plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
setupFiles: ['src/test-setup.ts'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory:
|
||||
'../../../../coverage/libs/checkout/shared/product-info',
|
||||
provider: 'v8' as const,
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -1,8 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const FetchStockInStockSchema = z.object({
|
||||
assignedStockId: z.number(),
|
||||
itemIds: z.array(z.number()),
|
||||
});
|
||||
|
||||
export type FetchStockInStock = z.infer<typeof FetchStockInStockSchema>;
|
||||
import { z } from 'zod';
|
||||
|
||||
export const FetchStockInStockSchema = z.object({
|
||||
assignedStockId: z.number().optional(),
|
||||
itemIds: z.array(z.number()),
|
||||
});
|
||||
|
||||
export type FetchStockInStock = z.infer<typeof FetchStockInStockSchema>;
|
||||
|
||||
@@ -110,13 +110,23 @@ export class RemissionStockService {
|
||||
this.#logger.debug('Fetching stock info', () => ({ params }));
|
||||
const parsed = FetchStockInStockSchema.parse(params);
|
||||
|
||||
let assignedStockId: number;
|
||||
|
||||
if (parsed.assignedStockId) {
|
||||
assignedStockId = parsed.assignedStockId;
|
||||
} else {
|
||||
assignedStockId = await this.fetchAssignedStock(abortSignal).then(
|
||||
(s) => s.id,
|
||||
);
|
||||
}
|
||||
|
||||
this.#logger.info('Fetching stock info from API', () => ({
|
||||
stockId: parsed.assignedStockId,
|
||||
itemCount: parsed.itemIds.length,
|
||||
}));
|
||||
|
||||
let req$ = this.#stockService.StockInStock({
|
||||
stockId: parsed.assignedStockId,
|
||||
stockId: assignedStockId,
|
||||
articleIds: parsed.itemIds,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||
import { ProductFormatIconComponent } from './product-format-icon.component';
|
||||
|
||||
@Component({
|
||||
selector: 'shared-product-format',
|
||||
template: `<shared-product-format-icon
|
||||
[format]="format()"
|
||||
></shared-product-format-icon>
|
||||
<span class="isa-text-body-2-regular text-isa-secondary-900">
|
||||
{{ formatDetail() }}
|
||||
</span>`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [ProductFormatIconComponent],
|
||||
host: {
|
||||
'[class]': '["flex", "items-center", "gap-2"]',
|
||||
'data-what': 'product-format',
|
||||
'data-which': 'shared-product-format',
|
||||
},
|
||||
})
|
||||
export class ProductFormatComponent {
|
||||
format = input.required<string>();
|
||||
|
||||
formatDetail = input.required<string>();
|
||||
}
|
||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||
import { ProductFormatIconComponent } from './product-format-icon.component';
|
||||
|
||||
@Component({
|
||||
selector: 'shared-product-format',
|
||||
template: `<shared-product-format-icon
|
||||
[format]="format()"
|
||||
></shared-product-format-icon>
|
||||
<span
|
||||
[class.isa-text-body-2-regular]="!formatDetailsBold()"
|
||||
[class.isa-text-body-2-bold]="formatDetailsBold()"
|
||||
class="text-isa-secondary-900"
|
||||
>
|
||||
{{ formatDetail() }}
|
||||
</span>`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [ProductFormatIconComponent],
|
||||
host: {
|
||||
'[class]': '["flex", "items-center", "gap-2"]',
|
||||
'data-what': 'product-format',
|
||||
'data-which': 'shared-product-format',
|
||||
},
|
||||
})
|
||||
export class ProductFormatComponent {
|
||||
format = input.required<string>();
|
||||
|
||||
formatDetail = input.required<string>();
|
||||
|
||||
formatDetailsBold = input<boolean>(false);
|
||||
}
|
||||
|
||||
63533
package-lock.json
generated
63533
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
276
package.json
276
package.json
@@ -1,138 +1,138 @@
|
||||
{
|
||||
"name": "hima",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "nx serve isa-app --ssl",
|
||||
"pretest": "npx trash-cli testresults",
|
||||
"test": "npx nx run-many --tuiAutoExit true -t test --exclude isa-app",
|
||||
"ci": "npx nx run-many -t test --exclude isa-app -c ci --tuiAutoExit true",
|
||||
"build": "nx build isa-app --configuration=development",
|
||||
"build-prod": "nx build isa-app --configuration=production",
|
||||
"lint": "nx lint",
|
||||
"e2e": "nx e2e",
|
||||
"generate:swagger": "nx run-many -t generate -p tag:generated,swagger",
|
||||
"fix:files:swagger": "node ./tools/fix-files.js generated/swagger",
|
||||
"prettier": "prettier --write .",
|
||||
"pretty-quick": "pretty-quick --staged",
|
||||
"prepare": "husky",
|
||||
"storybook": "npx nx run isa-app:storybook"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular-architects/ngrx-toolkit": "^20.4.0",
|
||||
"@angular/animations": "20.1.2",
|
||||
"@angular/cdk": "20.1.2",
|
||||
"@angular/common": "20.1.2",
|
||||
"@angular/compiler": "20.1.2",
|
||||
"@angular/core": "20.1.2",
|
||||
"@angular/forms": "20.1.2",
|
||||
"@angular/localize": "20.1.2",
|
||||
"@angular/platform-browser": "20.1.2",
|
||||
"@angular/platform-browser-dynamic": "20.1.2",
|
||||
"@angular/router": "20.1.2",
|
||||
"@angular/service-worker": "20.1.2",
|
||||
"@microsoft/signalr": "^8.0.7",
|
||||
"@ng-icons/core": "32.0.0",
|
||||
"@ng-icons/material-icons": "32.0.0",
|
||||
"@ngrx/component-store": "^20.0.0",
|
||||
"@ngrx/effects": "^20.0.0",
|
||||
"@ngrx/entity": "^20.0.0",
|
||||
"@ngrx/operators": "^20.0.0",
|
||||
"@ngrx/signals": "^20.0.0",
|
||||
"@ngrx/store": "^20.0.0",
|
||||
"@ngrx/store-devtools": "^20.0.0",
|
||||
"angular-oauth2-oidc": "20.0.0",
|
||||
"angular-oauth2-oidc-jwks": "20.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"ng2-pdf-viewer": "^10.4.0",
|
||||
"ngx-matomo-client": "^8.0.0",
|
||||
"parse-duration": "^2.1.3",
|
||||
"rxjs": "~7.8.2",
|
||||
"scandit-web-datacapture-barcode": "^6.28.1",
|
||||
"scandit-web-datacapture-core": "^6.28.1",
|
||||
"tslib": "^2.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
"zod": "^3.24.2",
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@analogjs/vite-plugin-angular": "1.19.1",
|
||||
"@analogjs/vitest-angular": "1.19.1",
|
||||
"@angular-devkit/build-angular": "20.1.1",
|
||||
"@angular-devkit/core": "20.1.1",
|
||||
"@angular-devkit/schematics": "20.1.1",
|
||||
"@angular/build": "20.1.1",
|
||||
"@angular/cli": "~20.1.0",
|
||||
"@angular/compiler-cli": "20.1.2",
|
||||
"@angular/language-service": "20.1.2",
|
||||
"@angular/pwa": "20.1.1",
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@ngneat/spectator": "19.6.2",
|
||||
"@nx/angular": "21.3.2",
|
||||
"@nx/eslint": "21.3.2",
|
||||
"@nx/eslint-plugin": "21.3.2",
|
||||
"@nx/jest": "21.3.2",
|
||||
"@nx/js": "21.3.2",
|
||||
"@nx/storybook": "21.3.2",
|
||||
"@nx/vite": "21.3.2",
|
||||
"@nx/web": "21.3.2",
|
||||
"@nx/workspace": "21.3.2",
|
||||
"@schematics/angular": "20.1.1",
|
||||
"@storybook/addon-docs": "^9.0.11",
|
||||
"@storybook/angular": "^9.0.5",
|
||||
"@swc-node/register": "1.10.10",
|
||||
"@swc/core": "1.12.1",
|
||||
"@swc/helpers": "0.5.17",
|
||||
"@types/jest": "30.0.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/node": "18.16.9",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/utils": "^8.33.1",
|
||||
"@vitest/coverage-v8": "^3.1.1",
|
||||
"@vitest/ui": "^3.1.1",
|
||||
"angular-eslint": "20.1.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.28.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-environment-node": "^29.7.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-preset-angular": "14.6.0",
|
||||
"jiti": "2.4.2",
|
||||
"jsdom": "~22.1.0",
|
||||
"jsonc-eslint-parser": "^2.1.0",
|
||||
"ng-mocks": "14.13.5",
|
||||
"ng-packagr": "20.1.0",
|
||||
"ng-swagger-gen": "^2.3.1",
|
||||
"nx": "21.3.2",
|
||||
"postcss": "^8.5.3",
|
||||
"postcss-url": "~10.1.3",
|
||||
"prettier": "^3.5.2",
|
||||
"pretty-quick": "~4.0.0",
|
||||
"storybook": "^9.0.5",
|
||||
"tailwindcss": "^3.4.14",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "^8.33.1",
|
||||
"vite": "6.3.5",
|
||||
"vitest": "^3.1.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/linux-x64": "^0.25.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.00.0",
|
||||
"npm": ">=10.0.0"
|
||||
},
|
||||
"overrides": {
|
||||
"jest-environment-jsdom": {
|
||||
"jsdom": "26.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "hima",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "nx serve isa-app --ssl",
|
||||
"pretest": "npx trash-cli testresults",
|
||||
"test": "npx nx run-many --tuiAutoExit true -t test --exclude isa-app",
|
||||
"ci": "npx nx run-many -t test --exclude isa-app -c ci --tuiAutoExit true",
|
||||
"build": "nx build isa-app --configuration=development",
|
||||
"build-prod": "nx build isa-app --configuration=production",
|
||||
"lint": "nx lint",
|
||||
"e2e": "nx e2e",
|
||||
"generate:swagger": "nx run-many -t generate -p tag:generated,swagger",
|
||||
"fix:files:swagger": "node ./tools/fix-files.js generated/swagger",
|
||||
"prettier": "prettier --write .",
|
||||
"pretty-quick": "pretty-quick --staged",
|
||||
"prepare": "husky",
|
||||
"storybook": "npx nx run isa-app:storybook"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular-architects/ngrx-toolkit": "^20.4.0",
|
||||
"@angular/animations": "20.1.2",
|
||||
"@angular/cdk": "20.1.2",
|
||||
"@angular/common": "20.1.2",
|
||||
"@angular/compiler": "20.1.2",
|
||||
"@angular/core": "20.1.2",
|
||||
"@angular/forms": "20.1.2",
|
||||
"@angular/localize": "20.1.2",
|
||||
"@angular/platform-browser": "20.1.2",
|
||||
"@angular/platform-browser-dynamic": "20.1.2",
|
||||
"@angular/router": "20.1.2",
|
||||
"@angular/service-worker": "20.1.2",
|
||||
"@microsoft/signalr": "^8.0.7",
|
||||
"@ng-icons/core": "32.0.0",
|
||||
"@ng-icons/material-icons": "32.0.0",
|
||||
"@ngrx/component-store": "^20.0.0",
|
||||
"@ngrx/effects": "^20.0.0",
|
||||
"@ngrx/entity": "^20.0.0",
|
||||
"@ngrx/operators": "^20.0.0",
|
||||
"@ngrx/signals": "^20.0.0",
|
||||
"@ngrx/store": "^20.0.0",
|
||||
"@ngrx/store-devtools": "^20.0.0",
|
||||
"angular-oauth2-oidc": "20.0.0",
|
||||
"angular-oauth2-oidc-jwks": "20.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"ng2-pdf-viewer": "^10.4.0",
|
||||
"ngx-matomo-client": "^8.0.0",
|
||||
"parse-duration": "^2.1.3",
|
||||
"rxjs": "~7.8.2",
|
||||
"scandit-web-datacapture-barcode": "^6.28.1",
|
||||
"scandit-web-datacapture-core": "^6.28.1",
|
||||
"tslib": "^2.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
"zod": "^3.24.2",
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@analogjs/vite-plugin-angular": "1.19.1",
|
||||
"@analogjs/vitest-angular": "1.19.1",
|
||||
"@angular-devkit/build-angular": "20.1.1",
|
||||
"@angular-devkit/core": "20.1.1",
|
||||
"@angular-devkit/schematics": "20.1.1",
|
||||
"@angular/build": "20.1.1",
|
||||
"@angular/cli": "~20.1.0",
|
||||
"@angular/compiler-cli": "20.1.2",
|
||||
"@angular/language-service": "20.1.2",
|
||||
"@angular/pwa": "20.1.1",
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@ngneat/spectator": "19.6.2",
|
||||
"@nx/angular": "21.3.2",
|
||||
"@nx/eslint": "21.3.2",
|
||||
"@nx/eslint-plugin": "21.3.2",
|
||||
"@nx/jest": "21.3.2",
|
||||
"@nx/js": "21.3.2",
|
||||
"@nx/storybook": "21.3.2",
|
||||
"@nx/vite": "21.3.2",
|
||||
"@nx/web": "21.3.2",
|
||||
"@nx/workspace": "21.3.2",
|
||||
"@schematics/angular": "20.1.1",
|
||||
"@storybook/addon-docs": "^9.0.11",
|
||||
"@storybook/angular": "^9.0.5",
|
||||
"@swc-node/register": "1.10.10",
|
||||
"@swc/core": "1.12.1",
|
||||
"@swc/helpers": "0.5.17",
|
||||
"@types/jest": "30.0.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/node": "18.16.9",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/utils": "^8.33.1",
|
||||
"@vitest/coverage-v8": "^3.1.1",
|
||||
"@vitest/ui": "^3.1.1",
|
||||
"angular-eslint": "20.1.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.28.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-environment-node": "^29.7.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-preset-angular": "14.6.0",
|
||||
"jiti": "2.4.2",
|
||||
"jsdom": "~22.1.0",
|
||||
"jsonc-eslint-parser": "^2.1.0",
|
||||
"ng-mocks": "14.13.5",
|
||||
"ng-packagr": "20.1.0",
|
||||
"ng-swagger-gen": "^2.3.1",
|
||||
"nx": "21.3.2",
|
||||
"postcss": "^8.5.3",
|
||||
"postcss-url": "~10.1.3",
|
||||
"prettier": "^3.5.2",
|
||||
"pretty-quick": "~4.0.0",
|
||||
"storybook": "^9.0.5",
|
||||
"tailwindcss": "^3.4.14",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "^8.33.1",
|
||||
"vite": "6.3.5",
|
||||
"vitest": "^3.1.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/linux-x64": "^0.25.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.00.0",
|
||||
"npm": ">=10.0.0"
|
||||
},
|
||||
"overrides": {
|
||||
"jest-environment-jsdom": {
|
||||
"jsdom": "26.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +1,143 @@
|
||||
{
|
||||
"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/checkout/shared/product-info": [
|
||||
"libs/checkout/shared/product-info/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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user