# 🎯 CQRS Pattern Implementation - PraFrota Frontend ## Overview This document outlines how the PraFrota frontend implements the Command Query Responsibility Segregation (CQRS) pattern to align with our backend architecture. ## 🏗️ Service Layer Structure ### Query Services ```typescript @Injectable({ providedIn: 'root' }) export class VehicleQueryService { constructor(private http: HttpClient) {} // Query Methods (Read Operations) getVehicles(filters: VehicleFilters): Observable> { return this.http.get>('/api/vehicle', { params: filters }); } getVehicleById(id: string): Observable> { return this.http.get>(`/api/vehicle/${id}`); } searchVehicles(query: string): Observable> { return this.http.get>('/api/vehicle/search', { params: { query } }); } } ``` ### Command Services ```typescript @Injectable({ providedIn: 'root' }) export class VehicleCommandService { constructor(private http: HttpClient) {} // Command Methods (Write Operations) createVehicle(vehicle: CreateVehicleDto): Observable> { return this.http.post>('/api/vehicle', vehicle); } updateVehicle(id: string, vehicle: UpdateVehicleDto): Observable> { return this.http.put>(`/api/vehicle/${id}`, vehicle); } deleteVehicle(id: string): Observable> { return this.http.delete>(`/api/vehicle/${id}`); } } ``` ## 📦 Service Adapters Service adapters bridge between our CQRS services and the BaseDomainComponent: ```typescript @Injectable({ providedIn: 'root' }) export class VehicleServiceAdapter implements IDomainServiceAdapter { constructor( private queryService: VehicleQueryService, private commandService: VehicleCommandService ) {} // Query Operations getList(filters: any): Observable> { return this.queryService.getVehicles(filters); } getById(id: string): Observable> { return this.queryService.getVehicleById(id); } // Command Operations create(data: CreateVehicleDto): Observable> { return this.commandService.createVehicle(data); } update(id: string, data: UpdateVehicleDto): Observable> { return this.commandService.updateVehicle(id, data); } delete(id: string): Observable> { return this.commandService.deleteVehicle(id); } } ``` ## 🔄 Component Integration ### BaseDomainComponent Usage ```typescript @Component({ selector: 'app-vehicle', standalone: true, imports: [CommonModule, TabSystemComponent], templateUrl: './vehicle.component.html' }) export class VehicleComponent extends BaseDomainComponent { constructor( private queryService: VehicleQueryService, private commandService: VehicleCommandService, titleService: TitleService, headerActionsService: HeaderActionsService, cdr: ChangeDetectorRef ) { super( titleService, headerActionsService, cdr, new VehicleServiceAdapter(queryService, commandService) ); } } ``` ## 📊 State Management ### Query State ```typescript interface QueryState { data: T[]; loading: boolean; error: any; filters: any; pagination: { currentPage: number; pageSize: number; totalCount: number; }; } ``` ### Command State ```typescript interface CommandState { data: T | null; loading: boolean; error: any; success: boolean; } ``` ## 🔐 Error Handling ### Query Error Handling ```typescript @Injectable({ providedIn: 'root' }) export class QueryErrorHandler { handleError(error: HttpErrorResponse): Observable { // Handle query-specific errors if (error.status === 404) { // Handle not found } return throwError(() => error); } } ``` ### Command Error Handling ```typescript @Injectable({ providedIn: 'root' }) export class CommandErrorHandler { handleError(error: HttpErrorResponse): Observable { // Handle command-specific errors if (error.status === 409) { // Handle conflicts } return throwError(() => error); } } ``` ## 📝 Best Practices 1. **Service Organization**: - Separate query and command services - Use service adapters for component integration - Implement proper error handling 2. **State Management**: - Maintain separate states for queries and commands - Use proper loading states - Handle errors appropriately 3. **Type Safety**: - Use proper TypeScript interfaces - Implement proper DTOs - Use proper response types 4. **Performance**: - Implement proper caching - Use proper pagination - Optimize queries ## 🔄 Implementation Checklist When implementing CQRS in a new domain: 1. [ ] Create Query Service 2. [ ] Create Command Service 3. [ ] Create Service Adapter 4. [ ] Implement proper error handling 5. [ ] Add proper loading states 6. [ ] Implement proper caching 7. [ ] Add proper validation 8. [ ] Test all scenarios ## 📚 Additional Resources - Backend CQRS Documentation: `/docs/mcp/CQRS_PATTERN.md` - Frontend Architecture: `/docs/ARCHITECTURE.md` - Service Adapter Pattern: `/docs/SERVICE_ADAPTER_PATTERN.md`