From ac48799d9ae4c3c239ca5e6902927e5ba8353cc9 Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Fri, 3 Jul 2026 02:01:01 +0400 Subject: [PATCH] arch(sprint1): decouple backoffice facade from http provider --- .../backoffice-data-provider.token.ts | 8 +++++ .../backoffice/backoffice-data.service.ts | 17 ++++++++++ .../providers/api-backoffice-data.provider.ts | 18 ++++++++++ .../backoffice-data-provider.interface.ts | 7 ++++ .../mock-backoffice-data.provider.ts | 21 ++++++++++++ .../facades/backoffice/backoffice.facade.ts | 8 ++--- src/assets/mock/bootstrap/categories.json | 16 --------- src/assets/mock/bootstrap/products.json | 34 ------------------- 8 files changed, 75 insertions(+), 54 deletions(-) create mode 100644 src/app/core/backoffice/backoffice-data-provider.token.ts create mode 100644 src/app/core/backoffice/backoffice-data.service.ts create mode 100644 src/app/core/backoffice/providers/api-backoffice-data.provider.ts create mode 100644 src/app/core/backoffice/providers/backoffice-data-provider.interface.ts create mode 100644 src/app/core/backoffice/providers/mock-backoffice-data.provider.ts delete mode 100644 src/assets/mock/bootstrap/categories.json delete mode 100644 src/assets/mock/bootstrap/products.json diff --git a/src/app/core/backoffice/backoffice-data-provider.token.ts b/src/app/core/backoffice/backoffice-data-provider.token.ts new file mode 100644 index 0000000..2c18d5b --- /dev/null +++ b/src/app/core/backoffice/backoffice-data-provider.token.ts @@ -0,0 +1,8 @@ +import { InjectionToken, inject } from '@angular/core'; +import { BackofficeDataProvider } from './providers/backoffice-data-provider.interface'; +import { MockBackofficeDataProvider } from './providers/mock-backoffice-data.provider'; + +export const BACKOFFICE_DATA_PROVIDER = new InjectionToken('BACKOFFICE_DATA_PROVIDER', { + providedIn: 'root', + factory: () => inject(MockBackofficeDataProvider) +}); diff --git a/src/app/core/backoffice/backoffice-data.service.ts b/src/app/core/backoffice/backoffice-data.service.ts new file mode 100644 index 0000000..78bf6a7 --- /dev/null +++ b/src/app/core/backoffice/backoffice-data.service.ts @@ -0,0 +1,17 @@ +import { Injectable, inject } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ProductCardConfig, CategoryCardConfig } from '../../shared/models/ui'; +import { BACKOFFICE_DATA_PROVIDER } from './backoffice-data-provider.token'; + +@Injectable({ providedIn: 'root' }) +export class BackofficeDataService { + private readonly provider = inject(BACKOFFICE_DATA_PROVIDER); + + loadProducts(): Observable { + return this.provider.loadProducts(); + } + + loadCategories(): Observable { + return this.provider.loadCategories(); + } +} diff --git a/src/app/core/backoffice/providers/api-backoffice-data.provider.ts b/src/app/core/backoffice/providers/api-backoffice-data.provider.ts new file mode 100644 index 0000000..ca6d16e --- /dev/null +++ b/src/app/core/backoffice/providers/api-backoffice-data.provider.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { ProductCardConfig, CategoryCardConfig } from '../../../shared/models/ui'; +import { BackofficeDataProvider } from './backoffice-data-provider.interface'; + +@Injectable({ providedIn: 'root' }) +export class ApiBackofficeDataProvider implements BackofficeDataProvider { + constructor(private readonly http: HttpClient) {} + + loadProducts(): Observable { + return this.http.get('/api/backoffice/products'); + } + + loadCategories(): Observable { + return this.http.get('/api/backoffice/categories'); + } +} diff --git a/src/app/core/backoffice/providers/backoffice-data-provider.interface.ts b/src/app/core/backoffice/providers/backoffice-data-provider.interface.ts new file mode 100644 index 0000000..3b25451 --- /dev/null +++ b/src/app/core/backoffice/providers/backoffice-data-provider.interface.ts @@ -0,0 +1,7 @@ +import { Observable } from 'rxjs'; +import { ProductCardConfig, CategoryCardConfig } from '../../../shared/models/ui'; + +export interface BackofficeDataProvider { + loadProducts(): Observable; + loadCategories(): Observable; +} \ No newline at end of file diff --git a/src/app/core/backoffice/providers/mock-backoffice-data.provider.ts b/src/app/core/backoffice/providers/mock-backoffice-data.provider.ts new file mode 100644 index 0000000..e4c665b --- /dev/null +++ b/src/app/core/backoffice/providers/mock-backoffice-data.provider.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { ProductCardConfig, CategoryCardConfig } from '../../../shared/models/ui'; +import { BackofficeDataProvider } from './backoffice-data-provider.interface'; + +@Injectable({ providedIn: 'root' }) +export class MockBackofficeDataProvider implements BackofficeDataProvider { + private readonly productsUrl = '/assets/mock/backoffice/products/list.json'; + private readonly categoriesUrl = '/assets/mock/backoffice/categories/list.json'; + + constructor(private readonly http: HttpClient) {} + + loadProducts(): Observable { + return this.http.get(this.productsUrl); + } + + loadCategories(): Observable { + return this.http.get(this.categoriesUrl); + } +} diff --git a/src/app/facades/backoffice/backoffice.facade.ts b/src/app/facades/backoffice/backoffice.facade.ts index 44fa4b9..e2b3688 100644 --- a/src/app/facades/backoffice/backoffice.facade.ts +++ b/src/app/facades/backoffice/backoffice.facade.ts @@ -1,6 +1,6 @@ import { Injectable, signal } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; import { ProductCardConfig, CategoryCardConfig } from '../../shared/models/ui'; +import { BackofficeDataService } from '../../core/backoffice/backoffice-data.service'; @Injectable({ providedIn: 'root' }) export class BackofficeFacade { @@ -8,12 +8,12 @@ export class BackofficeFacade { readonly categories = signal([]); readonly loading = signal(false); - constructor(private readonly http: HttpClient) {} + constructor(private readonly backofficeDataService: BackofficeDataService) {} load(): void { this.loading.set(true); - this.http.get('/assets/mock/bootstrap/products.json').subscribe({ + this.backofficeDataService.loadProducts().subscribe({ next: (products) => { this.products.set(products ?? []); this.loadCategories(); @@ -26,7 +26,7 @@ export class BackofficeFacade { } private loadCategories(): void { - this.http.get('/assets/mock/bootstrap/categories.json').subscribe({ + this.backofficeDataService.loadCategories().subscribe({ next: (categories) => { this.categories.set(categories ?? []); this.loading.set(false); diff --git a/src/assets/mock/bootstrap/categories.json b/src/assets/mock/bootstrap/categories.json deleted file mode 100644 index eac9d5f..0000000 --- a/src/assets/mock/bootstrap/categories.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "id": "cat-001", - "title": "Electronics", - "description": "Phones, laptops and accessories", - "imageUrl": "https://images.unsplash.com/photo-1498049794561-7780e7231661?w=400&h=300&fit=crop", - "itemsCount": 120 - }, - { - "id": "cat-002", - "title": "Clothing", - "description": "Fashion for everyone", - "imageUrl": "https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=400&h=300&fit=crop", - "itemsCount": 80 - } -] diff --git a/src/assets/mock/bootstrap/products.json b/src/assets/mock/bootstrap/products.json deleted file mode 100644 index 125f16d..0000000 --- a/src/assets/mock/bootstrap/products.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "id": "prod-001", - "sku": "SKU-001", - "title": "Demo Product 1", - "subtitle": "Platform product mock", - "imageUrl": "https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=600&h=400&fit=crop", - "badges": ["new"], - "tags": ["featured"], - "rating": 4.8, - "reviewsCount": 15, - "price": { - "amount": 149990, - "currency": "RUB", - "originalAmount": 169990 - }, - "stockStatus": "in_stock" - }, - { - "id": "prod-002", - "sku": "SKU-002", - "title": "Demo Product 2", - "imageUrl": "https://images.unsplash.com/photo-1496181133206-80ce9b88a853?w=600&h=400&fit=crop", - "badges": ["sale"], - "tags": ["bestseller"], - "rating": 4.6, - "reviewsCount": 8, - "price": { - "amount": 89990, - "currency": "RUB" - }, - "stockStatus": "low_stock" - } -]