diff --git a/src/app/core/layout/store-layout/store-layout.component.ts b/src/app/core/layout/store-layout/store-layout.component.ts index b880ea9..01844c0 100644 --- a/src/app/core/layout/store-layout/store-layout.component.ts +++ b/src/app/core/layout/store-layout/store-layout.component.ts @@ -241,9 +241,10 @@ export class StoreLayoutComponent implements OnInit { } this.authService.logout().subscribe({ - next: () => { + next: ({ message }) => { this.cartService.clearCart(); this.isCartOpen.set(false); + this.toastService.success(message || 'Sesión cerrada correctamente.'); if (!isLeavingCheckout) { void this.router.navigate(['/']); diff --git a/src/app/core/services/auth/auth.interfaces.ts b/src/app/core/services/auth/auth.interfaces.ts index aa8d486..0dd0da9 100644 --- a/src/app/core/services/auth/auth.interfaces.ts +++ b/src/app/core/services/auth/auth.interfaces.ts @@ -33,6 +33,10 @@ export interface LoginResponse { user: AuthUser; } +export interface LogoutResponse { + message: string; +} + export interface RegisterResponse { message: string; data: AuthUser; diff --git a/src/app/core/services/auth/auth.service.ts b/src/app/core/services/auth/auth.service.ts index ae1d310..2983b21 100644 --- a/src/app/core/services/auth/auth.service.ts +++ b/src/app/core/services/auth/auth.service.ts @@ -10,6 +10,7 @@ import { AuthUser, LoginPayload, LoginResponse, + LogoutResponse, RegisterPayload, RegisterResponse, ResetPasswordPayload, @@ -155,14 +156,14 @@ export class AuthService extends BaseApiService { .pipe(tap((user) => this.userState.set(user))); } - logout(): Observable { + logout(): Observable { if (!this.tokenState()) { this.clearSession(); - return of(void 0); + return of({ message: 'Sesión cerrada correctamente.' }); } return this.http - .post(`${environment.url}logout`, {}) + .post(`${environment.url}logout`, {}) .pipe(tap(() => this.clearSession())); } diff --git a/src/app/core/services/tenant.interface.ts b/src/app/core/services/tenant.interface.ts index 6255c8c..5976260 100644 --- a/src/app/core/services/tenant.interface.ts +++ b/src/app/core/services/tenant.interface.ts @@ -113,6 +113,7 @@ export interface Tenant { dominio: string; base_path?: string; site_title?: string | null; + asset_url?: string | null; address?: string | null; phone?: string | null; favicon?: string | null; diff --git a/src/app/core/services/tenant.service.spec.ts b/src/app/core/services/tenant.service.spec.ts index 744a6b3..ed8680f 100644 --- a/src/app/core/services/tenant.service.spec.ts +++ b/src/app/core/services/tenant.service.spec.ts @@ -15,6 +15,7 @@ const tenant: Tenant = { codigo: 'test', nombre: 'Test Tenant', dominio: 'localhost', + asset_url: 'https://s3.example.com/assets', primary_color: '#6376F3', secondary_color: '#A0A0A0', danger_color: '#FF8888', @@ -44,6 +45,7 @@ const tenantResponse: TenantBootstrapResponse = { describe('TenantService', () => { beforeEach(() => { + document.head.querySelectorAll('link[rel="preconnect"]').forEach((link) => link.remove()); try { window.history.replaceState({}, '', 'http://localhost:4200/'); } catch (e) { @@ -72,6 +74,9 @@ describe('TenantService', () => { expect(service.status()).toBe('ready'); expect(service.tenant()).toEqual(tenant); expect(service.getTenant()).toEqual(tenant); + expect( + document.head.querySelector('link[rel="preconnect"][href="https://s3.example.com/"]'), + ).not.toBeNull(); httpController.verify(); }); diff --git a/src/app/core/services/tenant.service.ts b/src/app/core/services/tenant.service.ts index 28fdf05..748a06d 100644 --- a/src/app/core/services/tenant.service.ts +++ b/src/app/core/services/tenant.service.ts @@ -1,4 +1,4 @@ -import { isPlatformBrowser, isPlatformServer } from '@angular/common'; +import { DOCUMENT, isPlatformBrowser, isPlatformServer } from '@angular/common'; import { HttpErrorResponse } from '@angular/common/http'; import { inject, @@ -26,6 +26,7 @@ import { providedIn: 'root', }) export class TenantService extends BaseApiService { + private readonly document = inject(DOCUMENT); private readonly platformId = inject(PLATFORM_ID); private readonly request = inject(REQUEST, { optional: true }); private readonly responseInit = inject(RESPONSE_INIT, { optional: true }); @@ -182,10 +183,40 @@ export class TenantService extends BaseApiService { } private setReady(tenant: Tenant): void { + this.ensureAssetPreconnect(tenant.asset_url); this.tenantState.set(tenant); this.statusState.set('ready'); } + private ensureAssetPreconnect(assetUrl: string | null | undefined): void { + if (!assetUrl) { + return; + } + + let origin: string; + + try { + const url = new URL(assetUrl); + if (url.protocol !== 'http:' && url.protocol !== 'https:') { + return; + } + origin = url.origin; + } catch { + return; + } + + const existingPreconnects = + this.document.head.querySelectorAll('link[rel="preconnect"]'); + if ([...existingPreconnects].some((link) => link.href === `${origin}/`)) { + return; + } + + const link = this.document.createElement('link'); + link.rel = 'preconnect'; + link.href = origin; + this.document.head.append(link); + } + private setNotFound(): void { this.tenantState.set(null); this.statusState.set('not-found');