Files
ISA-Frontend/docs/architecture-quick-reference.md
Lorenz Hilpert fd8e0194ac 🚚 refactor(skills): reorganize skill structure
- Rename logging-helper to logging for consistency
- Remove git-commit-helper (superseded by /commit command)
- Add git-workflow skill for Git Flow operations

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 13:39:14 +01:00

15 KiB

ISA-Frontend Architecture: Quick Reference Guide

Project Overview at a Glance

Aspect Details
Project Type Angular 20.3.6 Monorepo (Domain-Driven Design)
Build Tool Nx 21.3.2
Total Libraries 63 (organized by domain + infrastructure)
Main Application isa-app (only runnable app)
Domains OMS, Remission, Checkout, Catalogue, Availability, CRM
UI Components 17 specialized design system libraries
Testing Jest (legacy) + Vitest (modern) - migration in progress
State Management NgRx Signals with entity normalization
API Clients 10 auto-generated from Swagger/OpenAPI specs
Styling Tailwind CSS + 7 custom plugins
Authentication OAuth2/OIDC via angular-oauth2-oidc
Barcode Support Scandit Web Datacapture
Analytics Matomo integration

Domain Summary

1. Order Management System (OMS) - 9 Libraries

Focus: Return workflows and receipt management

Library Purpose
oms-data-access State + API integration
oms-feature-return-search Receipt search interface
oms-feature-return-details Item selection & configuration
oms-feature-return-process Dynamic return questions
oms-feature-return-summary Confirmation & printing
oms-feature-return-review Completion review
oms-shared-product-info Product display
oms-shared-task-list Task management UI
oms-utils-translation Receipt type labels

Key APIs: oms-api, isa-api, print-api


2. Remission (Returns Management) - 8 Libraries

Focus: Warehouse return processing (mandatory + department)

Library Purpose
remission-data-access State + API integration
remission-feature-remission-list Main list view
remission-feature-remission-return-receipt-list Receipt list
remission-feature-remission-return-receipt-details Receipt details
remission-shared-product Product components
remission-shared-remission-start-dialog Start workflow
remission-shared-return-receipt-actions Action buttons
remission-shared-search-item-to-remit-dialog Item search

Key APIs: Remission-specific via ISA backend


3. Checkout & Rewards - 6 Libraries

Focus: Shopping cart, orders, loyalty rewards

Library Purpose
checkout-data-access Cart state + API
checkout-feature-reward-catalog Reward browsing
checkout-feature-reward-shopping-cart Cart with rewards
checkout-feature-reward-order-confirmation Order confirmation
checkout-shared-product-info Product display
checkout-shared-reward-selection-dialog Reward selection

Key APIs: checkout-api, crm-api (bonus cards)


4. Catalogue - 1 Library

Focus: Product search and discovery

Library Purpose
catalogue-data-access Search + filtering

Key APIs: cat-search-api, availability-api


5. Availability - 1 Library

Focus: Product stock checking

Library Purpose
availability-data-access Stock queries

Key APIs: availability-api


6. CRM - 1 Library

Focus: Customer data and bonus cards

Library Purpose
crm-data-access Customer + bonus card state

Key APIs: crm-api


Architecture Layers

┌─────────────────────────────────┐
│  FEATURE LAYER (User-Facing)    │
│  - Components with routes       │
│  - User interactions            │
│  - Navigation handlers          │
└──────────────┬──────────────────┘
               │ imports
┌──────────────▼──────────────────┐
│  SHARED LAYER (Reusable)        │
│  - UI components (17 libs)      │
│  - Shared components (7 libs)   │
│  - Domain shared                │
└──────────────┬──────────────────┘
               │ imports
┌──────────────▼──────────────────┐
│  DATA ACCESS LAYER (State)      │
│  - NgRx Signal Stores           │
│  - API Services                 │
│  - Entity management            │
└──────────────┬──────────────────┘
               │ imports
┌──────────────▼──────────────────┐
│  INFRASTRUCTURE (Foundation)    │
│  - Core libraries (5)           │
│  - Common utilities (3)         │
│  - Generated APIs (10)          │
│  - Utilities (3)                │
└─────────────────────────────────┘

State Management Pattern

NgRx Signals Store Structure

export const orderStore = signalStore(
  // 1. State definition
  withState({
    orders: [] as Order[],
    selected: null as Order | null,
    loading: false,
    error: null as Error | null,
  }),
  
  // 2. Entity management (auto-normalization)
  withEntities({ entity: type<Order>() }),
  
  // 3. Computed values
  withComputed((store) => ({
    orderCount: computed(() => store.orders().length),
    hasSelected: computed(() => store.selected() !== null),
  })),
  
  // 4. Methods for state mutations
  withMethods((store, api = inject(OmsApiService)) => ({
    load: rxMethod<void>(
      pipe(
        tapResponse(
          (orders) => patchState(store, setAllEntities(orders)),
          (error) => handleError(error)
        )
      )
    ),
    select: (order: Order) => {
      patchState(store, { selected: order });
    },
  })),
  
  // 5. Auto persistence
  withStorage({ key: 'orders' }),
  
  // 6. Cleanup hooks
  withHooks({
    onInit: ({ load }) => load(),
    onDestroy: () => console.log('Store destroyed'),
  })
);

Key Features:

  • Signals: Reactive properties
  • Entity management: Auto-normalized state
  • Methods: Encapsulated mutations
  • Storage: Automatic persistence
  • Hooks: Lifecycle management

Component Structure

Standalone Component Example

@Component({
  selector: 'oms-return-search',
  standalone: true,
  imports: [
    CommonModule,
    ReactiveFormsModule,
    // Shared components
    UiSearchBar,
    UiButton,
    OmsProductInfo,
    UiEmptyState,
  ],
  template: `
    <div class="container">
      <ui-search-bar (search)="onSearch($event)" />
      
      @if (store.receipts(); as receipts) {
        @if (receipts.length > 0) {
          <oms-product-info 
            *ngFor="let receipt of receipts"
            [receipt]="receipt"
          />
        } @else {
          <ui-empty-state title="Keine Belege" />
        }
      } @loading {
        <ui-skeleton-loader />
      }
    </div>
  `,
  styles: [`...`],
})
export class OmsReturnSearchComponent {
  protected store = inject(omsStore);
  private api = inject(OmsApiService);

  onSearch(term: string) {
    this.store.searchReceipts(term);
  }
}

Best Practices:

  • Standalone components only
  • Explicit imports
  • Inject store, not services
  • Use store methods directly
  • Let control flow (@if, @for)

Common Patterns

1. Search with Debouncing

export class SearchComponent {
  private searchTerm$ = new Subject<string>();
  
  results$ = this.searchTerm$.pipe(
    debounceTime(300),
    distinctUntilChanged(),
    switchMap((term) => this.api.search(term)),
    takeUntilKeydown('Escape')
  );

  onSearch(term: string) {
    this.searchTerm$.next(term);
  }
}

2. Modal/Dialog Handling

export class DialogComponent {
  private dialog = inject(DialogService);
  
  openRewardSelection() {
    this.dialog.open(RewardSelectionDialog, {
      data: { cart: this.cart },
    }).afterClosed$.subscribe((reward) => {
      if (reward) {
        this.store.selectReward(reward);
      }
    });
  }
}

3. Form Validation

export class ReturnProcessComponent {
  form = new FormGroup({
    reason: new FormControl('', [Validators.required]),
    quantity: new FormControl(1, [Validators.min(1)]),
    comments: new FormControl(''),
  });

  submit() {
    if (this.form.valid) {
      this.store.submitReturn(this.form.value);
    }
  }
}

4. Responsive Design

export class ResponsiveComponent {
  // Use breakpoint service instead of CSS-only
  isDesktop = breakpoint([
    Breakpoint.Desktop,
    Breakpoint.DesktopL,
    Breakpoint.DesktopXL,
  ]);

  template = `
    @if (isDesktop()) {
      <desktop-layout />
    } @else {
      <mobile-layout />
    }
  `;
}

Common Commands

Development

npm start                          # Start with SSL
npm test                           # Test all libraries
npm run build                      # Dev build
npm run build-prod                 # Production build

Testing

npx nx test oms-data-access --skip-nx-cache
npx nx affected:test --skip-nx-cache
npm run ci                         # CI with coverage

Code Quality

npm run lint                       # ESLint
npm run prettier                   # Format code
npm run docs:generate              # Update library ref

API & Swagger

npm run generate:swagger           # Regenerate all APIs
npm run fix:files:swagger          # Unicode cleanup

Dependency Analysis

npx nx graph                       # Visual dependency graph
npx nx show project oms-data-access --web false
npx nx affected:lint --skip-nx-cache

File Organization by Domain

OMS Domain Structure

libs/oms/
├── data-access/
│   └── src/
│       ├── index.ts
│       ├── stores/
│       │   ├── receipt.store.ts
│       │   └── return.store.ts
│       └── services/
│           ├── oms-api.service.ts
│           └── print.service.ts
├── feature/
│   ├── return-search/
│   ├── return-details/
│   ├── return-process/
│   ├── return-summary/
│   └── return-review/
├── shared/
│   ├── product-info/
│   └── task-list/
└── utils/
    └── translation/

UI Component Structure

libs/ui/buttons/
├── src/
│   ├── index.ts
│   ├── primary-button.component.ts
│   ├── secondary-button.component.ts
│   ├── ...
│   └── buttons.module.ts
├── README.md
├── project.json
└── ...

TypeScript Path Aliases

{
  "paths": {
    // Domain data-access
    "@isa/oms/data-access": ["libs/oms/data-access/src/index.ts"],
    "@isa/remission/data-access": ["libs/remission/data-access/src/index.ts"],
    
    // UI components
    "@isa/ui/buttons": ["libs/ui/buttons/src/index.ts"],
    "@isa/ui/dialog": ["libs/ui/dialog/src/index.ts"],
    
    // Core infrastructure
    "@isa/core/logging": ["libs/core/logging/src/index.ts"],
    "@isa/core/storage": ["libs/core/storage/src/index.ts"],
    
    // Generated APIs
    "@generated/swagger/oms-api": ["generated/swagger/oms-api/src/index.ts"]
  }
}

Styling & Design System

Tailwind Utilities (ISA-Specific)

<!-- Brand Colors -->
<div class="text-isa-accent-primary">Primary text</div>
<button class="bg-isa-accent-primary">Primary button</button>

<!-- Typography -->
<h1 class="isa-text-heading-1-bold">Large heading</h1>
<p class="isa-text-body-2-regular">Body text</p>

<!-- Custom Breakpoints -->
<div class="hidden isa-desktop:block">Desktop only</div>
<div class="block isa-desktop:hidden">Mobile only</div>

<!-- Custom Plugins -->
<button class="isa-button-primary">ISA Button</button>
<div class="isa-input-group">...</div>

Custom Tailwind Plugins

  1. button - Button styling
  2. typography - Text utilities
  3. menu - Menu styling
  4. label - Label & tag styling
  5. input - Input styling
  6. section - Section containers
  7. select-bullet - Select styling

Testing Approach

New Libraries (Vitest + Angular Testing Utils)

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { OmsReturnSearchComponent } from './oms-return-search.component';

describe('OmsReturnSearchComponent', () => {
  let component: OmsReturnSearchComponent;
  let fixture: ComponentFixture<OmsReturnSearchComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [OmsReturnSearchComponent],
    }).compileComponents();

    fixture = TestBed.createComponent(OmsReturnSearchComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

E2E Attributes

All templates must include data attributes:

<button 
  data-what="submit-return"
  data-which="primary-action"
  [attr.data-order-id]="orderId"
>
  Submit Return
</button>

Troubleshooting

Issue Solution
Build cache stale npx nx reset or --skip-nx-cache
Test failures Always use --skip-nx-cache
Import not found Check tsconfig.base.json path alias
Circular dependency Run npx nx lint to identify
SSL certificate error Accept localhost certificate in browser
State not persisting Check withStorage() in store
API 401 Unauthorized Verify OAuth2 token in auth service

  • Library Reference: /docs/library-reference.md
  • Architecture Analysis: /docs/architecture-analysis.md
  • Dependency Hierarchy: /docs/dependency-hierarchy.md
  • Testing Guidelines: /docs/guidelines/testing.md
  • Nx Documentation: https://nx.dev/
  • Angular Documentation: https://angular.io/
  • NgRx Signals: https://ngrx.io/guide/signals

Getting Help

  1. Check library README: libs/[domain]/[layer]/[feature]/README.md
  2. Review existing examples in similar domains
  3. Check npx nx show project [project-name]
  4. Read CLAUDE.md for project-specific conventions
  5. Review git history: git log --oneline libs/[domain]

Performance Budgets

  • Main bundle: 2MB warning, 5MB error (gzipped)
  • Initial load: < 2s on 4G
  • Core (after auth): < 5s

Bundle Analysis:

npx nx build isa-app --configuration=production --stats-json
webpack-bundle-analyzer dist/isa-app/browser/stats.json

Monorepo Statistics

Metric Count
Total Libraries 63
Feature Components 20
UI Components 17
Data Access 6
Core Infrastructure 5
Shared Components 7
Utilities 3
Generated APIs 10
Lines of Code ~500K+
TypeScript Files ~1,500
Test Files ~400
Generated Test Coverage Vitest: 34%, Jest: 65%