fix(auth): update logout response to include success message and adjust types

fix(tenant): add asset_url to Tenant interface and implement preconnect logic
This commit is contained in:
2026-09-07 09:30:06 -03:00
parent d7c015e71e
commit 8ba34c6c7a
6 changed files with 48 additions and 5 deletions

View File

@@ -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(['/']);

View File

@@ -33,6 +33,10 @@ export interface LoginResponse {
user: AuthUser;
}
export interface LogoutResponse {
message: string;
}
export interface RegisterResponse {
message: string;
data: AuthUser;

View File

@@ -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<void> {
logout(): Observable<LogoutResponse> {
if (!this.tokenState()) {
this.clearSession();
return of(void 0);
return of({ message: 'Sesión cerrada correctamente.' });
}
return this.http
.post<void>(`${environment.url}logout`, {})
.post<LogoutResponse>(`${environment.url}logout`, {})
.pipe(tap(() => this.clearSession()));
}

View File

@@ -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;

View File

@@ -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();
});

View File

@@ -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<HTMLLinkElement>('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');