# 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 ```typescript 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() }), // 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( 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 ```typescript @Component({ selector: 'oms-return-search', standalone: true, imports: [ CommonModule, ReactiveFormsModule, // Shared components UiSearchBar, UiButton, OmsProductInfo, UiEmptyState, ], template: `
@if (store.receipts(); as receipts) { @if (receipts.length > 0) { } @else { } } @loading { }
`, 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 ```typescript export class SearchComponent { private searchTerm$ = new Subject(); 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 ```typescript 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 ```typescript 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 ```typescript export class ResponsiveComponent { // Use breakpoint service instead of CSS-only isDesktop = breakpoint([ Breakpoint.Desktop, Breakpoint.DesktopL, Breakpoint.DesktopXL, ]); template = ` @if (isDesktop()) { } @else { } `; } ``` --- ## Common Commands ### Development ```bash npm start # Start with SSL npm test # Test all libraries npm run build # Dev build npm run build-prod # Production build ``` ### Testing ```bash npx nx test oms-data-access --skip-nx-cache npx nx affected:test --skip-nx-cache npm run ci # CI with coverage ``` ### Code Quality ```bash npm run lint # ESLint npm run prettier # Format code npm run docs:generate # Update library ref ``` ### API & Swagger ```bash npm run generate:swagger # Regenerate all APIs npm run fix:files:swagger # Unicode cleanup ``` ### Dependency Analysis ```bash 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 ```json { "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) ```html
Primary text

Large heading

Body text

Mobile only
...
``` ### 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) ```typescript import { TestBed, ComponentFixture } from '@angular/core/testing'; import { OmsReturnSearchComponent } from './oms-return-search.component'; describe('OmsReturnSearchComponent', () => { let component: OmsReturnSearchComponent; let fixture: ComponentFixture; 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: ```html ``` --- ## 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 | --- ## Quick Links - **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:** ```bash 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% |