Compare commits
3 Commits
38a57adf55
...
d0b1607ff4
| Author | SHA1 | Date | |
|---|---|---|---|
| d0b1607ff4 | |||
| 92546a28c0 | |||
| ce26fb5d1a |
@@ -22,14 +22,18 @@
|
|||||||
|
|
||||||
<div class="col-12 col-md-6 col-xl-5 d-grid gap-3 align-content-start store-layout__contact">
|
<div class="col-12 col-md-6 col-xl-5 d-grid gap-3 align-content-start store-layout__contact">
|
||||||
<div class="d-grid gap-2 store-layout__contact-details">
|
<div class="d-grid gap-2 store-layout__contact-details">
|
||||||
<div class="d-flex align-items-center gap-2">
|
@if (address) {
|
||||||
<i class="fa-solid fa-location-dot" aria-hidden="true"></i>
|
<div class="d-flex align-items-center gap-2">
|
||||||
<span>Av. San Lorenzo 1542, Rosario</span>
|
<i class="fa-solid fa-location-dot" aria-hidden="true"></i>
|
||||||
</div>
|
<span>{{ address }}</span>
|
||||||
<div class="d-flex align-items-center gap-2">
|
</div>
|
||||||
<i class="fa-solid fa-phone" aria-hidden="true"></i>
|
}
|
||||||
<span>54 9 (0341) 6658247</span>
|
@if (phone) {
|
||||||
</div>
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<i class="fa-solid fa-phone" aria-hidden="true"></i>
|
||||||
|
<span>{{ phone }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="mb-0 small store-layout__muted-text store-layout__copyright">
|
<p class="mb-0 small store-layout__muted-text store-layout__copyright">
|
||||||
|
|||||||
@@ -27,5 +27,7 @@ export class StoreFooterComponent {
|
|||||||
@Input() logoUrl: string | null = null;
|
@Input() logoUrl: string | null = null;
|
||||||
@Input() backgroundImageUrl: string | null = null;
|
@Input() backgroundImageUrl: string | null = null;
|
||||||
@Input() storeName: string | null = null;
|
@Input() storeName: string | null = null;
|
||||||
|
@Input() address: string | null = null;
|
||||||
|
@Input() phone: string | null = null;
|
||||||
readonly logoutClick = output<void>();
|
readonly logoutClick = output<void>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,8 @@
|
|||||||
[logoUrl]="tenant()?.footer_logo ?? null"
|
[logoUrl]="tenant()?.footer_logo ?? null"
|
||||||
[backgroundImageUrl]="tenant()?.footer_bg_image ?? null"
|
[backgroundImageUrl]="tenant()?.footer_bg_image ?? null"
|
||||||
[storeName]="tenant()?.nombre ?? null"
|
[storeName]="tenant()?.nombre ?? null"
|
||||||
|
[address]="tenant()?.address ?? null"
|
||||||
|
[phone]="tenant()?.phone ?? null"
|
||||||
(logoutClick)="onLogoutClick()"
|
(logoutClick)="onLogoutClick()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ const tenant: Tenant = {
|
|||||||
codigo: 'test',
|
codigo: 'test',
|
||||||
nombre: 'Test Tenant',
|
nombre: 'Test Tenant',
|
||||||
dominio: 'localhost',
|
dominio: 'localhost',
|
||||||
|
address: 'Calle Test 123, Rosario',
|
||||||
|
phone: '+54 341 555 1234',
|
||||||
primary_color: '#6376F3',
|
primary_color: '#6376F3',
|
||||||
secondary_color: '#A0A0A0',
|
secondary_color: '#A0A0A0',
|
||||||
danger_color: '#FF8888',
|
danger_color: '#FF8888',
|
||||||
@@ -299,6 +301,12 @@ describe('StoreLayoutComponent', () => {
|
|||||||
expect(compiled.querySelector('.fa-whatsapp')).not.toBeNull();
|
expect(compiled.querySelector('.fa-whatsapp')).not.toBeNull();
|
||||||
expect(compiled.querySelector('.fa-facebook')).not.toBeNull();
|
expect(compiled.querySelector('.fa-facebook')).not.toBeNull();
|
||||||
expect(compiled.querySelector('.fa-linkedin-in')).not.toBeNull();
|
expect(compiled.querySelector('.fa-linkedin-in')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.store-layout__contact-details')?.textContent).toContain(
|
||||||
|
tenant.address,
|
||||||
|
);
|
||||||
|
expect(compiled.querySelector('.store-layout__contact-details')?.textContent).toContain(
|
||||||
|
tenant.phone,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates to search results when the search button is clicked', () => {
|
it('navigates to search results when the search button is clicked', () => {
|
||||||
|
|||||||
@@ -187,8 +187,8 @@ export class StoreLayoutComponent implements OnInit {
|
|||||||
protected async onLogoutClick(): Promise<void> {
|
protected async onLogoutClick(): Promise<void> {
|
||||||
const isLeavingCheckout = this.router.url.startsWith('/checkout');
|
const isLeavingCheckout = this.router.url.startsWith('/checkout');
|
||||||
|
|
||||||
// Checkout must be left while the authenticated session is still valid so
|
// Leave checkout before closing the authenticated session so its component
|
||||||
// its CanDeactivate guard can cancel the pending purchase.
|
// can stop payment polling cleanly. The checkout itself remains pending.
|
||||||
if (isLeavingCheckout) {
|
if (isLeavingCheckout) {
|
||||||
const navigationSucceeded = await this.router.navigate(['/']);
|
const navigationSucceeded = await this.router.navigate(['/']);
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ export type CatalogFeaturedItems =
|
|||||||
|
|
||||||
export interface CatalogFeaturedGroup {
|
export interface CatalogFeaturedGroup {
|
||||||
id: number;
|
id: number;
|
||||||
|
code: string;
|
||||||
title: string;
|
title: string;
|
||||||
layout: CatalogProductLayout;
|
layout: CatalogProductLayout;
|
||||||
group_layout: CatalogGroupLayout;
|
group_layout: CatalogGroupLayout;
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ export interface Tenant {
|
|||||||
dominio: string;
|
dominio: string;
|
||||||
base_path?: string;
|
base_path?: string;
|
||||||
site_title?: string | null;
|
site_title?: string | null;
|
||||||
|
address?: string | null;
|
||||||
|
phone?: string | null;
|
||||||
favicon?: string | null;
|
favicon?: string | null;
|
||||||
primary_color: string;
|
primary_color: string;
|
||||||
secondary_color: string;
|
secondary_color: string;
|
||||||
|
|||||||
@@ -608,14 +608,14 @@ describe('CheckoutPageComponent payment validation', () => {
|
|||||||
expect(component.stepper.next).toHaveBeenCalledOnce();
|
expect(component.stepper.next).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('cancels the pending purchase before allowing navigation away', async () => {
|
it('keeps the checkout purchase intact when navigating away', async () => {
|
||||||
const { component } = createComponent();
|
const { component } = createComponent();
|
||||||
|
|
||||||
await expect(component.canDeactivate()).resolves.toBe(true);
|
await expect(component.canDeactivate()).resolves.toBe(true);
|
||||||
|
|
||||||
expect(checkoutServiceStub.cancelPurchase).toHaveBeenCalledWith('tenant-test', 25);
|
expect(checkoutServiceStub.cancelPurchase).not.toHaveBeenCalled();
|
||||||
expect(cartServiceStub.loadCart).toHaveBeenCalled();
|
expect(cartServiceStub.loadCart).toHaveBeenCalled();
|
||||||
expect(cartServiceStub.clearCart).not.toHaveBeenCalled();
|
expect(cartServiceStub.clearCart).not.toHaveBeenCalled();
|
||||||
expect(component.createdPurchaseId()).toBeNull();
|
expect(component.createdPurchaseId()).toBe(25);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -398,29 +398,15 @@ export class CheckoutPageComponent implements OnInit, OnDestroy {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const purchaseId = this.createdPurchaseId();
|
// The checkout cart remains attached to its purchase. Once the user adds a
|
||||||
const tenant = this.tenantService.tenant();
|
// new item, the cart API creates a separate active cart automatically.
|
||||||
|
|
||||||
if (!purchaseId || !tenant) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.checkoutService.cancelPurchase(tenant.codigo, purchaseId);
|
await firstValueFrom(this.cartService.loadCart());
|
||||||
this.createdPurchaseId.set(null);
|
|
||||||
this.createdPurchase.set(null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await firstValueFrom(this.cartService.loadCart());
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to restore cart after cancelling checkout:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to cancel purchase:', error);
|
console.error('Failed to load the active cart after leaving checkout:', error);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async selectPaymentMethod(method: PaymentMethod): Promise<void> {
|
protected async selectPaymentMethod(method: PaymentMethod): Promise<void> {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</p>
|
</p>
|
||||||
} @else {
|
} @else {
|
||||||
@for (group of catalog(); track group.id) {
|
@for (group of catalog(); track group.id) {
|
||||||
<app-store-section [title]="group.title">
|
<app-store-section [attr.id]="group.code" [title]="group.title">
|
||||||
<app-product-list
|
<app-product-list
|
||||||
[layout]="group.layout"
|
[layout]="group.layout"
|
||||||
[groupLayout]="group.group_layout"
|
[groupLayout]="group.group_layout"
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ app-store-section + app-store-section {
|
|||||||
margin-top: clamp(3rem, 6vw, 5rem);
|
margin-top: clamp(3rem, 6vw, 5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app-store-section[id] {
|
||||||
|
scroll-margin-top: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
:host > .store-home__additional-info:not(:first-child) {
|
:host > .store-home__additional-info:not(:first-child) {
|
||||||
margin-top: clamp(3rem, 6vw, 5rem);
|
margin-top: clamp(3rem, 6vw, 5rem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ function createCatalog(
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 7,
|
id: 7,
|
||||||
|
code: 'destacados',
|
||||||
title: 'Destacados',
|
title: 'Destacados',
|
||||||
layout: 'column_with_image',
|
layout: 'column_with_image',
|
||||||
group_layout: 'paginated',
|
group_layout: 'paginated',
|
||||||
@@ -149,6 +150,7 @@ describe('StoreHomePageComponent', () => {
|
|||||||
const element = fixture.nativeElement as HTMLElement;
|
const element = fixture.nativeElement as HTMLElement;
|
||||||
|
|
||||||
expect(catalogServiceStub.getCatalog).not.toHaveBeenCalled();
|
expect(catalogServiceStub.getCatalog).not.toHaveBeenCalled();
|
||||||
|
expect(element.querySelector('app-store-section')?.id).toBe('destacados');
|
||||||
expect(element.querySelector('.store-section__title')?.textContent?.trim()).toBe('Destacados');
|
expect(element.querySelector('.store-section__title')?.textContent?.trim()).toBe('Destacados');
|
||||||
expect(element.querySelectorAll('app-product-column-with-image')).toHaveLength(2);
|
expect(element.querySelectorAll('app-product-column-with-image')).toHaveLength(2);
|
||||||
expect(element.textContent).toContain('Auriculares Bluetooth');
|
expect(element.textContent).toContain('Auriculares Bluetooth');
|
||||||
|
|||||||
Reference in New Issue
Block a user