feat(checkout): implement authentication guard for checkout route and add bank account service
This commit is contained in:
parent
0a2d999c00
commit
3971970975
|
|
@ -1,6 +1,10 @@
|
|||
import { RenderMode, ServerRoute } from '@angular/ssr';
|
||||
|
||||
export const serverRoutes: ServerRoute[] = [
|
||||
{
|
||||
path: 'checkout',
|
||||
renderMode: RenderMode.Client
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
renderMode: RenderMode.Server
|
||||
|
|
|
|||
|
|
@ -182,4 +182,16 @@ describe('app routes', () => {
|
|||
expect(compiled.querySelector('.tenant-status')).not.toBeNull();
|
||||
expect(compiled.textContent).toContain('No encontramos una tienda para este dominio');
|
||||
});
|
||||
|
||||
it('redirects unauthenticated users from /checkout to /login', async () => {
|
||||
const { router } = await renderAppAt('/checkout', createTenantServiceStub(), createAuthServiceStub(false));
|
||||
|
||||
expect(router.url).toBe('/login');
|
||||
});
|
||||
|
||||
it('allows authenticated users to access /checkout', async () => {
|
||||
const { router } = await renderAppAt('/checkout', createTenantServiceStub(), createAuthServiceStub(true));
|
||||
|
||||
expect(router.url).toBe('/checkout');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ describe('StoreLayoutComponent', () => {
|
|||
const fixture = TestBed.createComponent(StoreLayoutComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.componentInstance.isCartOpen.set(true);
|
||||
(fixture.componentInstance as any).isCartOpen.set(true);
|
||||
fixture.detectChanges();
|
||||
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
|
|
@ -166,6 +166,6 @@ describe('StoreLayoutComponent', () => {
|
|||
fixture.detectChanges();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/checkout']);
|
||||
expect(fixture.componentInstance.isCartOpen()).toBe(false);
|
||||
expect((fixture.componentInstance as any).isCartOpen()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import { inject, Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { BankAccount } from './tenant.interface';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CheckoutService {
|
||||
private readonly http = inject(HttpClient);
|
||||
|
||||
async getSelectedBankAccount(tenantCode: string): Promise<BankAccount> {
|
||||
const response = await firstValueFrom(
|
||||
this.http.get<{ data: BankAccount }>(`${environment.url}tenants/${tenantCode}/bank-accounts/selected`)
|
||||
);
|
||||
if (!response?.data) {
|
||||
throw new Error('No se encontraron los datos de la cuenta bancaria seleccionada.');
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,14 @@
|
|||
import { ApiResponse } from './api-response.interface';
|
||||
|
||||
export interface BankAccount {
|
||||
id: number;
|
||||
tenant_code: string;
|
||||
titular: string;
|
||||
entidad: string;
|
||||
alias: string;
|
||||
cvu: string;
|
||||
}
|
||||
|
||||
export interface Tenant {
|
||||
id: number;
|
||||
codigo: string;
|
||||
|
|
@ -13,6 +22,8 @@ export interface Tenant {
|
|||
footer_bg_color: string;
|
||||
header_logo: string;
|
||||
footer_logo: string;
|
||||
selected_bank_account_id?: number | null;
|
||||
selected_bank_account?: BankAccount | null;
|
||||
}
|
||||
|
||||
export type TenantBootstrapResponse = ApiResponse<Tenant>;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
[paymentMethods]="paymentMethods"
|
||||
[selectedPaymentMethod]="selectedPaymentMethod()"
|
||||
[copiedTransferField]="copiedTransferField()"
|
||||
[transferAccount]="transferAccount"
|
||||
[transferAccount]="transferAccount()"
|
||||
(paymentMethodChange)="selectPaymentMethod($event)"
|
||||
(copyTransferValue)="copyTransferValue($event.field, $event.value)"
|
||||
(cancelStep)="onCancel()"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import { Router } from '@angular/router';
|
|||
import { startWith } from 'rxjs';
|
||||
|
||||
import { CartService } from '../../../../core/services/cart/cart.service';
|
||||
import { TenantService } from '../../../../core/services/tenant.service';
|
||||
import { CheckoutService } from '../../../../core/services/checkout.service';
|
||||
import { BankAccount } from '../../../../core/services/tenant.interface';
|
||||
import { CartItem } from '../../../../core/services/cart/cart.interface';
|
||||
import { CartComponent, CartItemMock } from '../../../../shared/components/cart/cart.component';
|
||||
import { StepComponent } from '../../../../shared/components/stepper/step.component';
|
||||
|
|
@ -30,6 +33,8 @@ export class CheckoutPageComponent {
|
|||
private readonly formBuilder = inject(FormBuilder);
|
||||
private readonly cartService = inject(CartService);
|
||||
private readonly router = inject(Router);
|
||||
private readonly tenantService = inject(TenantService);
|
||||
private readonly checkoutService = inject(CheckoutService);
|
||||
|
||||
@ViewChild(StepperComponent) stepper!: StepperComponent;
|
||||
|
||||
|
|
@ -63,17 +68,36 @@ export class CheckoutPageComponent {
|
|||
];
|
||||
protected readonly selectedPaymentMethod = signal<PaymentMethod>('qr');
|
||||
protected readonly copiedTransferField = signal<TransferField | null>(null);
|
||||
protected readonly transferAccount: TransferAccount = {
|
||||
protected readonly transferAccount = signal<TransferAccount>({
|
||||
titular: 'Nombre y Apellido',
|
||||
entidad: 'TelePagos',
|
||||
cvu: '0000000000000000000000',
|
||||
alias: 'telepagos.ar'
|
||||
};
|
||||
});
|
||||
|
||||
constructor() {
|
||||
this.form.statusChanges
|
||||
.pipe(startWith(this.form.status))
|
||||
.subscribe(() => this.isStep1Valid.set(this.form.valid));
|
||||
|
||||
void this.loadSelectedBankAccount();
|
||||
}
|
||||
|
||||
private async loadSelectedBankAccount(): Promise<void> {
|
||||
const tenant = this.tenantService.tenant();
|
||||
if (!tenant) return;
|
||||
|
||||
try {
|
||||
const data = await this.checkoutService.getSelectedBankAccount(tenant.codigo);
|
||||
this.transferAccount.set({
|
||||
titular: data.titular,
|
||||
entidad: data.entidad,
|
||||
cvu: data.cvu,
|
||||
alias: data.alias
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to load selected bank account:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private mapCartItemToMock(item: CartItem): CartItemMock {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Routes } from '@angular/router';
|
|||
|
||||
import { AuthLayoutComponent } from '../../core/layout/auth-layout/auth-layout.component';
|
||||
import { StoreLayoutComponent } from '../../core/layout/store-layout/store-layout.component';
|
||||
import { guestOnlyGuard } from '../../core/services/auth/auth.guards';
|
||||
import { authGuard, guestOnlyGuard } from '../../core/services/auth/auth.guards';
|
||||
import { LoginPageComponent } from './pages/login-page/login-page.component';
|
||||
import { RegisterPageComponent } from './pages/register-page/register-page.component';
|
||||
import { StoreHomePageComponent } from './pages/store-home-page/store-home-page.component';
|
||||
|
|
@ -47,6 +47,7 @@ export const routes: Routes = [
|
|||
},
|
||||
{
|
||||
path: 'checkout',
|
||||
canActivate: [authGuard],
|
||||
loadComponent: () =>
|
||||
import('./pages/checkout-page/checkout-page.component').then(
|
||||
(m) => m.CheckoutPageComponent
|
||||
|
|
|
|||
Loading…
Reference in New Issue