feat: implement store home page with product listing, pagination, and error handling

This commit is contained in:
2026-06-30 08:47:57 -03:00
parent b2796a2383
commit 74144b6d2c
4 changed files with 36 additions and 12 deletions

View File

@@ -31,6 +31,13 @@ function createTenantServiceStub(
tenant: tenantState.asReadonly(), tenant: tenantState.asReadonly(),
status: statusState.asReadonly(), status: statusState.asReadonly(),
getTenant: () => tenantState(), getTenant: () => tenantState(),
getTenantApiUrl: () => {
const tenantVal = tenantState();
if (!tenantVal) {
throw new Error('No se pudo resolver el tenant activo.');
}
return `http://localhost:8000/api/tenants/${tenantVal.codigo}`;
},
bootstrap: vi.fn().mockResolvedValue(undefined) bootstrap: vi.fn().mockResolvedValue(undefined)
}; };
} }

View File

@@ -1,11 +1,13 @@
export interface Product { export interface Product {
id: number; id: number;
tenant_codigo: string; tenant_codigo: string;
categoria_id: number; category_id: number;
brand_id: number | null;
slug: string; slug: string;
nombre: string; nombre: string;
descripcion?: string; descripcion: string;
precio: string; precio: string;
created_at?: string; category: string;
updated_at?: string; brand: string | null;
images: string[];
} }

View File

@@ -38,18 +38,28 @@ describe('StoreHomePageComponent', () => {
{ {
id: 1, id: 1,
tenant_codigo: 'test', tenant_codigo: 'test',
categoria_id: 10, category_id: 10,
brand_id: null,
slug: 'auriculares-bluetooth', slug: 'auriculares-bluetooth',
nombre: 'Auriculares Bluetooth', nombre: 'Auriculares Bluetooth',
precio: '24999' descripcion: 'Auriculares bluetooth de prueba',
precio: '24999',
category: 'Tecnología',
brand: null,
images: []
}, },
{ {
id: 2, id: 2,
tenant_codigo: 'test', tenant_codigo: 'test',
categoria_id: 11, category_id: 11,
brand_id: null,
slug: 'teclado-mecanico', slug: 'teclado-mecanico',
nombre: 'Teclado Mecanico', nombre: 'Teclado Mecanico',
precio: '18999' descripcion: 'Teclado mecánico de prueba',
precio: '18999',
category: 'Tecnología',
brand: null,
images: []
} }
]; ];
@@ -97,10 +107,15 @@ describe('StoreHomePageComponent', () => {
{ {
id: 3, id: 3,
tenant_codigo: 'test', tenant_codigo: 'test',
categoria_id: 12, category_id: 12,
brand_id: null,
slug: 'mouse-gamer', slug: 'mouse-gamer',
nombre: 'Mouse Gamer', nombre: 'Mouse Gamer',
precio: '15999' descripcion: 'Mouse gamer de prueba',
precio: '15999',
category: 'Tecnología',
brand: null,
images: []
} }
], ],
2, 2,

View File

@@ -13,7 +13,7 @@ interface StoreHomeProductCardViewModel {
originalPrice: number; originalPrice: number;
discount: null; discount: null;
transferPrice: null; transferPrice: null;
imageUrl: null; imageUrl: string | null;
} }
@Component({ @Component({
@@ -42,7 +42,7 @@ export class StoreHomePageComponent implements OnInit, OnDestroy {
originalPrice: this.parseProductPrice(product.precio), originalPrice: this.parseProductPrice(product.precio),
discount: null, discount: null,
transferPrice: null, transferPrice: null,
imageUrl: null imageUrl: product.images?.[0] ?? null
})) }))
); );