diff --git a/src/app/features/admin/categories/components/admin-categories-list.component.html b/src/app/features/admin/categories/components/admin-categories-list.component.html index 082b62b..d765ab1 100644 --- a/src/app/features/admin/categories/components/admin-categories-list.component.html +++ b/src/app/features/admin/categories/components/admin-categories-list.component.html @@ -64,6 +64,8 @@ @for (i of [1,2,3,4]; track i) { } {{ 'common.loading' | translate }} + } @else if (error) { + } @else if (treeRows.length === 0) { diff --git a/src/app/features/admin/categories/components/admin-categories-list.component.ts b/src/app/features/admin/categories/components/admin-categories-list.component.ts index 5398b98..7cad1ba 100644 --- a/src/app/features/admin/categories/components/admin-categories-list.component.ts +++ b/src/app/features/admin/categories/components/admin-categories-list.component.ts @@ -51,6 +51,7 @@ export class AdminCategoriesListComponent { @Input() flatCategories: AdminCategory[] = []; @Input() filters!: { search: string; visibility: 'all' | 'visible' | 'hidden'; includeDeleted: boolean }; @Input() loading = false; + @Input() error: string | null = null; @Input() viewMode: AdminCategoriesViewMode = 'tree'; @Input() density: AdminCategoriesDensity = 'comfortable'; @Input() visibleColumns: AdminCategoryColumn[] = [...ALL_CATEGORY_COLUMNS]; diff --git a/src/app/features/admin/categories/facade/admin-categories.facade.ts b/src/app/features/admin/categories/facade/admin-categories.facade.ts index 79d9d76..ff9347f 100644 --- a/src/app/features/admin/categories/facade/admin-categories.facade.ts +++ b/src/app/features/admin/categories/facade/admin-categories.facade.ts @@ -131,6 +131,7 @@ export class AdminCategoriesFacade { readonly filters = signal({ search: '', visibility: 'all', includeDeleted: false }); readonly categories = signal([]); readonly loading = signal(false); + readonly error = signal(null); readonly draft = signal(null); readonly editorMode = signal('create'); readonly dirty = signal(false); @@ -174,6 +175,7 @@ export class AdminCategoriesFacade { */ loadList(): void { this.loading.set(true); + this.error.set(null); this.gateway.loadCategories({ search: '', visibility: 'all', includeDeleted: true }).pipe(take(1)).subscribe({ next: categories => { this.categories.set(categories); @@ -182,6 +184,7 @@ export class AdminCategoriesFacade { error: () => { this.categories.set([]); this.loading.set(false); + this.error.set('common.errorDescription'); } }); } diff --git a/src/app/features/admin/categories/pages/admin-categories-list-page.component.ts b/src/app/features/admin/categories/pages/admin-categories-list-page.component.ts index 00ee187..7306184 100644 --- a/src/app/features/admin/categories/pages/admin-categories-list-page.component.ts +++ b/src/app/features/admin/categories/pages/admin-categories-list-page.component.ts @@ -19,6 +19,7 @@ import { TranslatePipe } from '../../../../i18n/translate.pipe'; [allCategories]="facade.categories()" [filters]="facade.filters()" [loading]="facade.loading()" + [error]="facade.error()" [viewMode]="facade.viewMode()" [density]="facade.density()" [visibleColumns]="facade.visibleColumns()" diff --git a/src/app/features/admin/customers/facade/admin-customers.facade.ts b/src/app/features/admin/customers/facade/admin-customers.facade.ts index dbeab03..b58dbfc 100644 --- a/src/app/features/admin/customers/facade/admin-customers.facade.ts +++ b/src/app/features/admin/customers/facade/admin-customers.facade.ts @@ -10,8 +10,11 @@ export class AdminCustomersFacade { readonly customers = signal([]); readonly loading = signal(false); + readonly error = signal(null); readonly search = signal(''); readonly selected = signal(null); + readonly selectedLoading = signal(false); + readonly selectedError = signal(null); private buildCustomers(orders: AdminOrder[]): AdminCustomer[] { const byEmail = new Map(); @@ -41,6 +44,7 @@ export class AdminCustomersFacade { loadList(): void { this.loading.set(true); + this.error.set(null); this.ordersGateway.loadOrders({ search: '', status: 'all', page: 1, pageSize: 100000 }).pipe(take(1)).subscribe({ next: result => { this.customers.set(this.buildCustomers(result.items)); @@ -49,16 +53,24 @@ export class AdminCustomersFacade { error: () => { this.customers.set([]); this.loading.set(false); + this.error.set('common.errorDescription'); } }); } loadDetail(email: string): void { + this.selectedLoading.set(true); + this.selectedError.set(null); this.ordersGateway.loadOrders({ search: '', status: 'all', page: 1, pageSize: 100000 }).pipe(take(1)).subscribe({ next: result => { const decoded = decodeURIComponent(email); const customers = this.buildCustomers(result.items); this.selected.set(customers.find(customer => customer.email === decoded) ?? null); + this.selectedLoading.set(false); + }, + error: () => { + this.selectedLoading.set(false); + this.selectedError.set('common.errorDescription'); } }); } diff --git a/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html b/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html index f8698e7..7b8021c 100644 --- a/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html +++ b/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html @@ -48,6 +48,12 @@ +} @else if (facade.selectedError()) { + } @else {

{{ 'common.loading' | translate }}

} diff --git a/src/app/features/admin/customers/pages/admin-customers-list-page.component.html b/src/app/features/admin/customers/pages/admin-customers-list-page.component.html index 33f4237..86c36f2 100644 --- a/src/app/features/admin/customers/pages/admin-customers-list-page.component.html +++ b/src/app/features/admin/customers/pages/admin-customers-list-page.component.html @@ -8,6 +8,8 @@ @for (i of [1,2,3,4]; track i) { } {{ 'common.loading' | translate }} + } @else if (facade.error()) { + } @else if (facade.filteredCustomers().length === 0) { } @else { diff --git a/src/app/features/admin/orders/facade/admin-orders.facade.ts b/src/app/features/admin/orders/facade/admin-orders.facade.ts index 002688f..6ea263f 100644 --- a/src/app/features/admin/orders/facade/admin-orders.facade.ts +++ b/src/app/features/admin/orders/facade/admin-orders.facade.ts @@ -37,7 +37,10 @@ export class AdminOrdersFacade { readonly orders = signal([]); readonly total = signal(0); readonly loading = signal(false); + readonly error = signal(null); readonly selected = signal(null); + readonly selectedLoading = signal(false); + readonly selectedError = signal(null); readonly viewMode = signal((this.localStorage.getItem(VIEW_MODE_KEY) as AdminOrdersViewMode) || 'table'); readonly density = signal((this.localStorage.getItem(DENSITY_KEY) as AdminOrdersDensity) || 'comfortable'); @@ -76,6 +79,7 @@ export class AdminOrdersFacade { loadList(): void { this.loading.set(true); + this.error.set(null); this.gateway.loadOrders(this.filters()).pipe(take(1)).subscribe({ next: result => { this.orders.set(result.items); @@ -86,6 +90,7 @@ export class AdminOrdersFacade { this.orders.set([]); this.total.set(0); this.loading.set(false); + this.error.set('common.errorDescription'); } }); } @@ -96,7 +101,18 @@ export class AdminOrdersFacade { } loadDetail(id: string): void { - this.gateway.loadOrder(id).pipe(take(1)).subscribe({ next: order => this.selected.set(order) }); + this.selectedLoading.set(true); + this.selectedError.set(null); + this.gateway.loadOrder(id).pipe(take(1)).subscribe({ + next: order => { + this.selected.set(order); + this.selectedLoading.set(false); + }, + error: () => { + this.selectedLoading.set(false); + this.selectedError.set('common.errorDescription'); + } + }); } setStatus(id: string, status: AdminOrderStatus): void { diff --git a/src/app/features/admin/orders/pages/admin-order-detail-page.component.html b/src/app/features/admin/orders/pages/admin-order-detail-page.component.html index 50e0c11..31f8b00 100644 --- a/src/app/features/admin/orders/pages/admin-order-detail-page.component.html +++ b/src/app/features/admin/orders/pages/admin-order-detail-page.component.html @@ -103,6 +103,12 @@ (confirmed)="confirmRefund()" (cancelled)="pendingRefundId.set(null)" /> +} @else if (facade.selectedError()) { + } @else {

{{ 'common.loading' | translate }}

} diff --git a/src/app/features/admin/orders/pages/admin-orders-list-page.component.html b/src/app/features/admin/orders/pages/admin-orders-list-page.component.html index 0ecaec4..958cd9b 100644 --- a/src/app/features/admin/orders/pages/admin-orders-list-page.component.html +++ b/src/app/features/admin/orders/pages/admin-orders-list-page.component.html @@ -61,6 +61,8 @@ @for (i of [1,2,3,4]; track i) { } {{ 'common.loading' | translate }} + } @else if (facade.error()) { + } @else if (facade.orders().length === 0) { } @else { diff --git a/src/app/features/admin/products/components/admin-products-list.component.html b/src/app/features/admin/products/components/admin-products-list.component.html index b426390..36f16a2 100644 --- a/src/app/features/admin/products/components/admin-products-list.component.html +++ b/src/app/features/admin/products/components/admin-products-list.component.html @@ -78,6 +78,8 @@ } {{ 'common.loading' | translate }} + } @else if (error) { + } @else if (products.length === 0) { diff --git a/src/app/features/admin/products/components/admin-products-list.component.ts b/src/app/features/admin/products/components/admin-products-list.component.ts index f333c2f..0288c23 100644 --- a/src/app/features/admin/products/components/admin-products-list.component.ts +++ b/src/app/features/admin/products/components/admin-products-list.component.ts @@ -44,6 +44,7 @@ export class AdminProductsListComponent { @Input() total = 0; @Input() selectedIds: string[] = []; @Input() loading = false; + @Input() error: string | null = null; @Input() infiniteScroll = false; @Input() viewMode: AdminProductsViewMode = 'table'; @Input() density: AdminProductsDensity = 'comfortable'; diff --git a/src/app/features/admin/products/facade/admin-products.facade.ts b/src/app/features/admin/products/facade/admin-products.facade.ts index 3998260..f7bc50b 100644 --- a/src/app/features/admin/products/facade/admin-products.facade.ts +++ b/src/app/features/admin/products/facade/admin-products.facade.ts @@ -91,6 +91,7 @@ export class AdminProductsFacade { readonly infiniteScroll = signal(false); readonly categories = signal([]); readonly loading = signal(false); + readonly error = signal(null); readonly selectedIds = signal([]); readonly draft = signal(null); readonly dirty = signal(false); @@ -100,6 +101,7 @@ export class AdminProductsFacade { loadList(): void { this.loading.set(true); + this.error.set(null); this.gateway.loadProducts(this.filters()).pipe(take(1)).subscribe({ next: result => { this.products.set(result.items); @@ -110,6 +112,7 @@ export class AdminProductsFacade { this.products.set([]); this.total.set(0); this.loading.set(false); + this.error.set('common.errorDescription'); } }); } diff --git a/src/app/features/admin/products/pages/admin-products-list-page.component.ts b/src/app/features/admin/products/pages/admin-products-list-page.component.ts index 6483e2e..3676f3c 100644 --- a/src/app/features/admin/products/pages/admin-products-list-page.component.ts +++ b/src/app/features/admin/products/pages/admin-products-list-page.component.ts @@ -17,6 +17,7 @@ import { TranslatePipe } from '../../../../i18n/translate.pipe'; [total]="facade.total()" [selectedIds]="facade.selectedIds()" [loading]="facade.loading()" + [error]="facade.error()" [infiniteScroll]="facade.infiniteScroll()" [viewMode]="facade.viewMode()" [density]="facade.density()" diff --git a/src/app/features/admin/transactions/facade/admin-transactions.facade.ts b/src/app/features/admin/transactions/facade/admin-transactions.facade.ts index 038689f..da8de06 100644 --- a/src/app/features/admin/transactions/facade/admin-transactions.facade.ts +++ b/src/app/features/admin/transactions/facade/admin-transactions.facade.ts @@ -11,9 +11,11 @@ export class AdminTransactionsFacade { readonly transactions = signal([]); readonly total = signal(0); readonly loading = signal(false); + readonly error = signal(null); loadList(): void { this.loading.set(true); + this.error.set(null); this.gateway.loadTransactions(this.filters()).pipe(take(1)).subscribe({ next: result => { this.transactions.set(result.items); @@ -24,6 +26,7 @@ export class AdminTransactionsFacade { this.transactions.set([]); this.total.set(0); this.loading.set(false); + this.error.set('common.errorDescription'); } }); } diff --git a/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html b/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html index cd19f32..61c9d96 100644 --- a/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html +++ b/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html @@ -22,6 +22,8 @@ @for (i of [1,2,3,4]; track i) { } {{ 'common.loading' | translate }} + } @else if (facade.error()) { + } @else if (facade.transactions().length === 0) { } @else {