feat(cart): refactor cart item structure and update related components for consistency
This commit is contained in:
@@ -1,4 +1,14 @@
|
||||
import { ChangeDetectionStrategy, Component, computed, effect, inject, OnInit, signal, untracked, ViewChild } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
effect,
|
||||
inject,
|
||||
OnInit,
|
||||
signal,
|
||||
untracked,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { FormBuilder, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { startWith } from 'rxjs';
|
||||
@@ -14,7 +24,13 @@ import { StepComponent } from '../../../../shared/components/stepper/step.compon
|
||||
import { StepperComponent } from '../../../../shared/components/stepper/stepper.component';
|
||||
import { CheckoutDataStepComponent } from './checkout-data-step.component';
|
||||
import { CheckoutPaymentStepComponent } from './checkout-payment-step.component';
|
||||
import { CheckoutForm, PaymentMethod, PaymentMethodOption, TransferAccount, TransferField } from './checkout-page.models';
|
||||
import {
|
||||
CheckoutForm,
|
||||
PaymentMethod,
|
||||
PaymentMethodOption,
|
||||
TransferAccount,
|
||||
TransferField,
|
||||
} from './checkout-page.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-checkout-page',
|
||||
@@ -24,11 +40,11 @@ import { CheckoutForm, PaymentMethod, PaymentMethodOption, TransferAccount, Tran
|
||||
StepperComponent,
|
||||
StepComponent,
|
||||
CheckoutDataStepComponent,
|
||||
CheckoutPaymentStepComponent
|
||||
CheckoutPaymentStepComponent,
|
||||
],
|
||||
templateUrl: './checkout-page.component.html',
|
||||
styleUrl: './checkout-page.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CheckoutPageComponent implements OnInit {
|
||||
private readonly formBuilder = inject(FormBuilder);
|
||||
@@ -44,7 +60,7 @@ export class CheckoutPageComponent implements OnInit {
|
||||
nombre: ['', [Validators.required]],
|
||||
email: ['', [Validators.required, Validators.email]],
|
||||
dni: ['', [Validators.required]],
|
||||
telefono: ['', [Validators.required]]
|
||||
telefono: ['', [Validators.required]],
|
||||
});
|
||||
|
||||
protected readonly cartSubtotal = computed(() => {
|
||||
@@ -66,7 +82,7 @@ export class CheckoutPageComponent implements OnInit {
|
||||
protected readonly paymentMethods: ReadonlyArray<PaymentMethodOption> = [
|
||||
{ id: 'qr', label: 'QR' },
|
||||
{ id: 'transfer', label: 'Transferencia' },
|
||||
{ id: 'telepagos', label: 'TelePagos' }
|
||||
{ id: 'telepagos', label: 'TelePagos' },
|
||||
];
|
||||
protected readonly selectedPaymentMethod = signal<PaymentMethod>('qr');
|
||||
protected readonly copiedTransferField = signal<TransferField | null>(null);
|
||||
@@ -74,13 +90,15 @@ export class CheckoutPageComponent implements OnInit {
|
||||
titular: 'Nombre y Apellido',
|
||||
entidad: 'TelePagos',
|
||||
cvu: '0000000000000000000000',
|
||||
alias: 'telepagos.ar'
|
||||
alias: 'telepagos.ar',
|
||||
});
|
||||
|
||||
protected readonly isCreatingPurchase = signal(false);
|
||||
protected readonly createdPurchaseId = signal<number | null>(null);
|
||||
protected readonly isGeneratingIntent = signal(false);
|
||||
protected readonly isPaymentLoading = computed(() => this.isGeneratingIntent() || this.cartService.isUpdating());
|
||||
protected readonly isPaymentLoading = computed(
|
||||
() => this.isGeneratingIntent() || this.cartService.isUpdating(),
|
||||
);
|
||||
protected readonly qrData = signal<string | null>(null);
|
||||
|
||||
constructor() {
|
||||
@@ -88,7 +106,7 @@ export class CheckoutPageComponent implements OnInit {
|
||||
// We only want to trigger the intent generation when the cart changes.
|
||||
// So we track the cart, but untrack the other signals to prevent duplicate calls.
|
||||
const cart = this.cartService.cart();
|
||||
|
||||
|
||||
untracked(() => {
|
||||
const purchaseId = this.createdPurchaseId();
|
||||
if (cart && purchaseId) {
|
||||
@@ -108,7 +126,7 @@ export class CheckoutPageComponent implements OnInit {
|
||||
nombre: user.nombre_apellido,
|
||||
email: user.email,
|
||||
dni: user.dni ?? '',
|
||||
telefono: user.telefono ?? ''
|
||||
telefono: user.telefono ?? '',
|
||||
});
|
||||
this.form.controls.nombre.disable();
|
||||
this.form.controls.email.disable();
|
||||
@@ -138,14 +156,14 @@ export class CheckoutPageComponent implements OnInit {
|
||||
}
|
||||
|
||||
return {
|
||||
productVariantId: item.product_variant_id,
|
||||
cartItemId: item.id,
|
||||
imageUrl: item.product?.imagen ?? null,
|
||||
product,
|
||||
originalPrice: null,
|
||||
discountedPrice: parseFloat(item.precio_unitario),
|
||||
discountPercentage: null,
|
||||
attributes,
|
||||
quantity: item.cantidad
|
||||
quantity: item.cantidad,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -174,12 +192,11 @@ export class CheckoutPageComponent implements OnInit {
|
||||
|
||||
const response = await this.checkoutService.createPurchase(tenant.codigo, payload);
|
||||
this.createdPurchaseId.set(response.id);
|
||||
|
||||
|
||||
this.stepper.next();
|
||||
|
||||
|
||||
// Auto trigger intent for default option
|
||||
void this.selectPaymentMethod(this.selectedPaymentMethod());
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to create purchase:', error);
|
||||
// Here we could show an alert or toast
|
||||
@@ -205,8 +222,12 @@ export class CheckoutPageComponent implements OnInit {
|
||||
this.isGeneratingIntent.set(true);
|
||||
|
||||
try {
|
||||
const response = await this.checkoutService.generatePaymentIntent(tenant.codigo, purchaseId, method);
|
||||
|
||||
const response = await this.checkoutService.generatePaymentIntent(
|
||||
tenant.codigo,
|
||||
purchaseId,
|
||||
method,
|
||||
);
|
||||
|
||||
if (method === 'qr' && response.qr_data?.qr_code) {
|
||||
this.qrData.set(response.qr_data.qr_code);
|
||||
} else if (method === 'transfer' && response.transfer_data) {
|
||||
@@ -214,7 +235,7 @@ export class CheckoutPageComponent implements OnInit {
|
||||
titular: response.transfer_data.titular,
|
||||
entidad: response.transfer_data.entidad,
|
||||
cvu: response.transfer_data.cvu,
|
||||
alias: response.transfer_data.alias
|
||||
alias: response.transfer_data.alias,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -427,7 +427,7 @@ describe('ProductDetailPageComponent', () => {
|
||||
addToCartButton.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(cartServiceStub.addItem).toHaveBeenCalledWith(123, 3);
|
||||
expect(cartServiceStub.addItem).toHaveBeenCalledWith('variant', 123, 3);
|
||||
expect(toastServiceStub.success).toHaveBeenCalledWith('Producto agregado al carrito');
|
||||
});
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ export class ProductDetailPageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.addingToCart.set(true);
|
||||
this.cartService.addItem(variant.variant_id, this.quantity()).subscribe({
|
||||
this.cartService.addItem('variant', variant.variant_id, this.quantity()).subscribe({
|
||||
next: (res) => {
|
||||
const msg = res.message || 'Producto agregado al carrito';
|
||||
this.toastService.success(msg);
|
||||
|
||||
Reference in New Issue
Block a user