Overview
The frontend uses a service-oriented architecture for data fetching, business logic, and state management. All services are provided at the root level and use Angular’sHttpClient for API communication.
Service Architecture
Service Pattern
All services follow a consistent pattern:providedIn: 'root'- Singleton serviceinject()function - Modern dependency injection- Type-safe HTTP calls with generics
- Environment-based API URL configuration
HTTP Services
ProductService
Location:src/app/services/product.service.ts
Purpose: Fetch product data
GET /api/products
Usage:
StoreService
Location:src/app/services/store.service.ts
Purpose: Fetch store locations
GET /api/stores
Returns: Array of stores with id, country, latitude, longitude
WarehouseService
Location:src/app/services/warehouse.service.ts
Purpose: Fetch warehouse locations
GET /api/warehouses
Returns: Array of warehouses with id, country, latitude, longitude
StockAssignmentService
Location:src/app/services/stock-assignment.service.ts
Purpose: Fetch stock assignments with optional filtering
GET /api/stock-assignments
Query Parameters:
storeId(optional) - Filter by storewarehouseId(optional) - Filter by warehouseproductId(optional) - Filter by product
MetricsService
Location:src/app/services/metrics.service.ts
Purpose: Fetch global and detailed metrics
GET /api/metrics/global- Global metrics (no filters)GET /api/metrics/detailed- Filtered detailed metrics
RxJS Patterns
Parallel Requests with forkJoin
Load multiple resources simultaneously:- All requests fire simultaneously
- Result emits only when all complete
- Single error handler for all requests
- Loading state managed with
finalize()
Memory Leak Prevention
UsetakeUntil() to automatically unsubscribe:
Loading State Management
Usefinalize() to ensure loading state is updated:
Error Handling
Consistent error handling pattern:State Management Approach
Component-Based State
The application uses a simple component-based state management approach:- State owned by parent component
- Data flows down via
@Input() - Events bubble up via
@Output() - Services are stateless data providers
Data Flow Pattern
Why Not NgRx?
For this application’s scope:- Simple state: Single parent component owns state
- Clear data flow: Parent → children → parent
- No complex state: No need for time-travel debugging
- Fewer dependencies: Reduced bundle size
- Multiple components need shared mutable state
- Complex state transitions with side effects
- Need for state snapshots and undo/redo
Environment Configuration
Development Environment
Location:src/environments/environment.ts
Production Environment
Location:src/environments/environment.prod.ts
File Replacement
Configured inangular.json:
Error Handling Patterns
Service-Level Errors
Services let errors propagate to components:Component-Level Errors
Components handle errors and update UI state:Global Error Handling
For application-wide error handling, implementErrorHandler:
HTTP Interceptors
Adding Interceptors
For cross-cutting concerns (auth, logging, caching):Testing Services
Unit Test Example
Next Steps
- Review Component Architecture
- Explore API Endpoints
- Learn about Backend Services