Merge branch 'homologacion'
This commit is contained in:
@@ -29,7 +29,11 @@
|
|||||||
[subtotal]="cartSubtotal()"
|
[subtotal]="cartSubtotal()"
|
||||||
[discount]="cartDiscount()"
|
[discount]="cartDiscount()"
|
||||||
[total]="cartTotal()"
|
[total]="cartTotal()"
|
||||||
[readonly]="!cartEditingEnabled()"
|
[readonly]="!canModifyCart()"
|
||||||
|
[allowModify]="canModifyCart()"
|
||||||
|
[allowUpdateQuantity]="canUpdateCartQuantity()"
|
||||||
|
[allowUpdateVariant]="canUpdateCartVariant()"
|
||||||
|
[allowDelete]="canDeleteCartItems()"
|
||||||
[backgroundColor]="'#ffffff'"
|
[backgroundColor]="'#ffffff'"
|
||||||
(closed)="isCartOpen.set(false)"
|
(closed)="isCartOpen.set(false)"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ const tenant: Tenant = {
|
|||||||
footer_logo: 'https://example.com/footer.png',
|
footer_logo: 'https://example.com/footer.png',
|
||||||
header_bg_image: 'https://example.com/header-background.png',
|
header_bg_image: 'https://example.com/header-background.png',
|
||||||
footer_bg_image: 'https://example.com/footer-background.png',
|
footer_bg_image: 'https://example.com/footer-background.png',
|
||||||
|
cart_editing_policy: {
|
||||||
|
code: 'full',
|
||||||
|
allow_modify: true,
|
||||||
|
allow_delete: true,
|
||||||
|
allow_update_quantity: true,
|
||||||
|
allow_update_variant: true,
|
||||||
|
},
|
||||||
categories: [],
|
categories: [],
|
||||||
menues: [
|
menues: [
|
||||||
{
|
{
|
||||||
@@ -647,7 +654,16 @@ describe('StoreLayoutComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('hides quantity selectors when the tenant disables cart editing', () => {
|
it('hides quantity selectors when the tenant disables cart editing', () => {
|
||||||
tenantState.set({ ...tenant, cart_editing_enabled: false });
|
tenantState.set({
|
||||||
|
...tenant,
|
||||||
|
cart_editing_policy: {
|
||||||
|
code: 'disabled',
|
||||||
|
allow_modify: false,
|
||||||
|
allow_delete: false,
|
||||||
|
allow_update_quantity: false,
|
||||||
|
allow_update_variant: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
cartState.set({
|
cartState.set({
|
||||||
id: 1,
|
id: 1,
|
||||||
tenant_codigo: tenant.codigo,
|
tenant_codigo: tenant.codigo,
|
||||||
@@ -676,4 +692,62 @@ describe('StoreLayoutComponent', () => {
|
|||||||
expect(cartItem.componentInstance.readonly()).toBe(true);
|
expect(cartItem.componentInstance.readonly()).toBe(true);
|
||||||
expect(cartItem.nativeElement.querySelector('app-quantity-selector')).toBeNull();
|
expect(cartItem.nativeElement.querySelector('app-quantity-selector')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows variant selectors only for the full cart editing policy', () => {
|
||||||
|
const variantCart: Cart = {
|
||||||
|
id: 1,
|
||||||
|
tenant_codigo: tenant.codigo,
|
||||||
|
status: 'active',
|
||||||
|
subtotal: '100.00',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
cantidad: 1,
|
||||||
|
precio_unitario: '100.00',
|
||||||
|
catalog_item_id: 1,
|
||||||
|
variant_id: 10,
|
||||||
|
nombre: 'Producto',
|
||||||
|
imagen: null,
|
||||||
|
variant: { id: 10, precio: '100.00', stock_tecnico: 5, values: { talle: 'M' } },
|
||||||
|
variants: [
|
||||||
|
{ id: 10, precio: '100.00', stock_tecnico: 5, values: { talle: 'M' } },
|
||||||
|
{ id: 11, precio: '100.00', stock_tecnico: 5, values: { talle: 'L' } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
tenantState.set({
|
||||||
|
...tenant,
|
||||||
|
cart_editing_policy: {
|
||||||
|
code: 'quantity_and_remove',
|
||||||
|
allow_modify: true,
|
||||||
|
allow_delete: true,
|
||||||
|
allow_update_quantity: true,
|
||||||
|
allow_update_variant: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
cartState.set(variantCart);
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(StoreLayoutComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
(fixture.componentInstance as any).isCartOpen.set(true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.nativeElement.querySelector('app-variant-selector')).toBeNull();
|
||||||
|
expect(fixture.nativeElement.querySelector('app-quantity-selector')).not.toBeNull();
|
||||||
|
|
||||||
|
tenantState.set({
|
||||||
|
...tenant,
|
||||||
|
cart_editing_policy: {
|
||||||
|
code: 'full',
|
||||||
|
allow_modify: true,
|
||||||
|
allow_delete: true,
|
||||||
|
allow_update_quantity: true,
|
||||||
|
allow_update_variant: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.nativeElement.querySelector('app-variant-selector')).not.toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,8 +36,18 @@ export class StoreLayoutComponent implements OnInit {
|
|||||||
protected readonly isCartOpen = signal(false);
|
protected readonly isCartOpen = signal(false);
|
||||||
protected readonly isCreatingPurchase = signal(false);
|
protected readonly isCreatingPurchase = signal(false);
|
||||||
protected readonly displayCart = computed(() => this.tenant()?.display_cart ?? true);
|
protected readonly displayCart = computed(() => this.tenant()?.display_cart ?? true);
|
||||||
protected readonly cartEditingEnabled = computed(
|
protected readonly cartEditingPolicy = computed(() => this.tenant()?.cart_editing_policy ?? null);
|
||||||
() => this.tenant()?.cart_editing_enabled ?? true,
|
protected readonly canModifyCart = computed(
|
||||||
|
() => this.cartEditingPolicy()?.allow_modify ?? false,
|
||||||
|
);
|
||||||
|
protected readonly canDeleteCartItems = computed(
|
||||||
|
() => this.cartEditingPolicy()?.allow_delete ?? false,
|
||||||
|
);
|
||||||
|
protected readonly canUpdateCartQuantity = computed(
|
||||||
|
() => this.cartEditingPolicy()?.allow_update_quantity ?? false,
|
||||||
|
);
|
||||||
|
protected readonly canUpdateCartVariant = computed(
|
||||||
|
() => this.cartEditingPolicy()?.allow_update_variant ?? false,
|
||||||
);
|
);
|
||||||
|
|
||||||
protected readonly cartSubtotal = computed(() => {
|
protected readonly cartSubtotal = computed(() => {
|
||||||
@@ -92,6 +102,7 @@ export class StoreLayoutComponent implements OnInit {
|
|||||||
attributes,
|
attributes,
|
||||||
quantity: item.cantidad,
|
quantity: item.cantidad,
|
||||||
variantId: item.variant_id,
|
variantId: item.variant_id,
|
||||||
|
variants: item.variants,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface CartItem {
|
|||||||
nombre: string | null;
|
nombre: string | null;
|
||||||
imagen: string | null;
|
imagen: string | null;
|
||||||
variant: CartItemVariant | null;
|
variant: CartItemVariant | null;
|
||||||
|
variants?: CartItemVariant[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Cart {
|
export interface Cart {
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import { ApiResponse } from './api-response.interface';
|
import { ApiResponse } from './api-response.interface';
|
||||||
|
|
||||||
|
export type CartEditingPolicyCode = 'disabled' | 'quantity_and_remove' | 'full';
|
||||||
|
|
||||||
|
export interface CartEditingPolicy {
|
||||||
|
code: CartEditingPolicyCode;
|
||||||
|
allow_modify: boolean;
|
||||||
|
allow_delete: boolean;
|
||||||
|
allow_update_quantity: boolean;
|
||||||
|
allow_update_variant: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface BankAccount {
|
export interface BankAccount {
|
||||||
id: number;
|
id: number;
|
||||||
tenant_code: string;
|
tenant_code: string;
|
||||||
@@ -127,7 +137,7 @@ export interface Tenant {
|
|||||||
display_categories?: boolean;
|
display_categories?: boolean;
|
||||||
display_seach_bar?: boolean;
|
display_seach_bar?: boolean;
|
||||||
display_cart?: boolean;
|
display_cart?: boolean;
|
||||||
cart_editing_enabled?: boolean;
|
cart_editing_policy?: CartEditingPolicy;
|
||||||
display_cart_item_images?: boolean;
|
display_cart_item_images?: boolean;
|
||||||
social_media?: SocialMedia[];
|
social_media?: SocialMedia[];
|
||||||
menues?: Menu[];
|
menues?: Menu[];
|
||||||
|
|||||||
@@ -58,11 +58,13 @@
|
|||||||
[subtotal]="cartSubtotal()"
|
[subtotal]="cartSubtotal()"
|
||||||
[discount]="cartDiscount()"
|
[discount]="cartDiscount()"
|
||||||
[total]="cartTotal()"
|
[total]="cartTotal()"
|
||||||
[readonly]="!cartEditingEnabled()"
|
[readonly]="!canModifyCart()"
|
||||||
[allowEditing]="
|
[allowModify]="canModifyCart()"
|
||||||
|
[allowUpdateQuantity]="canUpdateCartQuantity()"
|
||||||
|
[requireEditingMode]="
|
||||||
createdPurchase()?.status === 'created' || createdPurchase()?.status === 'pending_payment'
|
createdPurchase()?.status === 'created' || createdPurchase()?.status === 'pending_payment'
|
||||||
"
|
"
|
||||||
[allowRemove]="false"
|
[allowDelete]="false"
|
||||||
[persistQuantityChanges]="false"
|
[persistQuantityChanges]="false"
|
||||||
[editing]="isEditingItems()"
|
[editing]="isEditingItems()"
|
||||||
[editingDisabled]="isUpdatingItem() || isPreparingItemEdit()"
|
[editingDisabled]="isUpdatingItem() || isPreparingItemEdit()"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { CartService } from '../../../../core/services/cart/cart.service';
|
|||||||
import { CheckoutService } from '../../../../core/services/checkout.service';
|
import { CheckoutService } from '../../../../core/services/checkout.service';
|
||||||
import { CatalogService } from '../../../../core/services/catalog/catalog.service';
|
import { CatalogService } from '../../../../core/services/catalog/catalog.service';
|
||||||
import { TenantService } from '../../../../core/services/tenant.service';
|
import { TenantService } from '../../../../core/services/tenant.service';
|
||||||
|
import { CartEditingPolicy } from '../../../../core/services/tenant.interface';
|
||||||
import { CheckoutPageComponent } from './checkout-page.component';
|
import { CheckoutPageComponent } from './checkout-page.component';
|
||||||
|
|
||||||
describe('CheckoutPageComponent payment validation', () => {
|
describe('CheckoutPageComponent payment validation', () => {
|
||||||
@@ -32,7 +33,12 @@ describe('CheckoutPageComponent payment validation', () => {
|
|||||||
let routerStub: { navigate: ReturnType<typeof vi.fn> };
|
let routerStub: { navigate: ReturnType<typeof vi.fn> };
|
||||||
let routeQueryParamMap: ReturnType<typeof convertToParamMap>;
|
let routeQueryParamMap: ReturnType<typeof convertToParamMap>;
|
||||||
let authUserState: ReturnType<typeof signal>;
|
let authUserState: ReturnType<typeof signal>;
|
||||||
let tenantState: ReturnType<typeof signal<{ codigo: string; cart_editing_enabled?: boolean }>>;
|
let tenantState: ReturnType<
|
||||||
|
typeof signal<{
|
||||||
|
codigo: string;
|
||||||
|
cart_editing_policy?: CartEditingPolicy;
|
||||||
|
}>
|
||||||
|
>;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
try {
|
try {
|
||||||
@@ -87,7 +93,16 @@ describe('CheckoutPageComponent payment validation', () => {
|
|||||||
routerStub = { navigate: vi.fn() };
|
routerStub = { navigate: vi.fn() };
|
||||||
routeQueryParamMap = convertToParamMap({});
|
routeQueryParamMap = convertToParamMap({});
|
||||||
authUserState = signal(null);
|
authUserState = signal(null);
|
||||||
tenantState = signal({ codigo: 'tenant-test' });
|
tenantState = signal({
|
||||||
|
codigo: 'tenant-test',
|
||||||
|
cart_editing_policy: {
|
||||||
|
code: 'full',
|
||||||
|
allow_modify: true,
|
||||||
|
allow_delete: true,
|
||||||
|
allow_update_quantity: true,
|
||||||
|
allow_update_variant: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [CheckoutPageComponent],
|
imports: [CheckoutPageComponent],
|
||||||
@@ -467,12 +482,22 @@ describe('CheckoutPageComponent payment validation', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not allow item editing when the tenant disables cart editing', async () => {
|
it('does not allow item editing when the tenant disables cart editing', async () => {
|
||||||
tenantState.set({ codigo: 'tenant-test', cart_editing_enabled: false });
|
tenantState.set({
|
||||||
|
codigo: 'tenant-test',
|
||||||
|
cart_editing_policy: {
|
||||||
|
code: 'disabled',
|
||||||
|
allow_modify: false,
|
||||||
|
allow_delete: false,
|
||||||
|
allow_update_quantity: false,
|
||||||
|
allow_update_variant: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
const { component } = createComponent();
|
const { component } = createComponent();
|
||||||
|
|
||||||
await component.onEditingItemsChange(true);
|
await component.onEditingItemsChange(true);
|
||||||
|
|
||||||
expect(component.cartEditingEnabled()).toBe(false);
|
expect(component.canUpdateCartQuantity()).toBe(false);
|
||||||
|
expect(component.canModifyCart()).toBe(false);
|
||||||
expect(component.isEditingItems()).toBe(false);
|
expect(component.isEditingItems()).toBe(false);
|
||||||
expect(checkoutServiceStub.prepareItemEditing).not.toHaveBeenCalled();
|
expect(checkoutServiceStub.prepareItemEditing).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -79,8 +79,11 @@ export class CheckoutPageComponent implements OnInit, OnDestroy {
|
|||||||
protected readonly createdPurchase = signal<PurchaseDetailResponse | null>(null);
|
protected readonly createdPurchase = signal<PurchaseDetailResponse | null>(null);
|
||||||
protected readonly isLoadingPurchase = signal(true);
|
protected readonly isLoadingPurchase = signal(true);
|
||||||
protected readonly checkoutStepIndex = signal(0);
|
protected readonly checkoutStepIndex = signal(0);
|
||||||
protected readonly cartEditingEnabled = computed(
|
protected readonly canUpdateCartQuantity = computed(
|
||||||
() => this.tenantService.tenant()?.cart_editing_enabled ?? true,
|
() => this.tenantService.tenant()?.cart_editing_policy?.allow_update_quantity ?? false,
|
||||||
|
);
|
||||||
|
protected readonly canModifyCart = computed(
|
||||||
|
() => this.tenantService.tenant()?.cart_editing_policy?.allow_modify ?? false,
|
||||||
);
|
);
|
||||||
|
|
||||||
protected readonly cartSubtotal = computed(() => {
|
protected readonly cartSubtotal = computed(() => {
|
||||||
@@ -181,7 +184,7 @@ export class CheckoutPageComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editing && !this.cartEditingEnabled()) {
|
if (editing && !this.canModifyCart()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +234,7 @@ export class CheckoutPageComponent implements OnInit, OnDestroy {
|
|||||||
const itemId = event.item.cartItemId;
|
const itemId = event.item.cartItemId;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!this.cartEditingEnabled() ||
|
!this.canUpdateCartQuantity() ||
|
||||||
!tenant ||
|
!tenant ||
|
||||||
!purchaseId ||
|
!purchaseId ||
|
||||||
!itemId ||
|
!itemId ||
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (hasVariantSelectors() && !quantityDisabled()) {
|
@if (hasVariantSelectors() && !variantDisabled()) {
|
||||||
<app-variant-selector
|
<app-variant-selector
|
||||||
class="cart-item-variant-selector"
|
class="cart-item-variant-selector"
|
||||||
[variants]="variants()"
|
[variants]="variants()"
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
(increase)="onIncrease()"
|
(increase)="onIncrease()"
|
||||||
(decrease)="onDecrease()"
|
(decrease)="onDecrease()"
|
||||||
/>
|
/>
|
||||||
@if (!quantityDisabled() && showRemove()) {
|
@if (!removeDisabled() && allowDelete()) {
|
||||||
<app-icon-button variant="trash" class="cart-item-remove-btn" (click)="onRemove()" />
|
<app-icon-button variant="trash" class="cart-item-remove-btn" (click)="onRemove()" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ export class CartItemComponent {
|
|||||||
readonly quantity = input<number>(1);
|
readonly quantity = input<number>(1);
|
||||||
readonly readonly = input<boolean>(false);
|
readonly readonly = input<boolean>(false);
|
||||||
readonly quantityDisabled = input<boolean>(false);
|
readonly quantityDisabled = input<boolean>(false);
|
||||||
readonly showRemove = input<boolean>(true);
|
readonly variantDisabled = input<boolean>(false);
|
||||||
|
readonly removeDisabled = input<boolean>(false);
|
||||||
|
readonly allowDelete = input<boolean>(true);
|
||||||
|
|
||||||
readonly quantityChange = output<number>();
|
readonly quantityChange = output<number>();
|
||||||
readonly remove = output<void>();
|
readonly remove = output<void>();
|
||||||
@@ -61,7 +63,7 @@ export class CartItemComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onVariantChange(variant: unknown): void {
|
protected onVariantChange(variant: unknown): void {
|
||||||
if (!this.quantityDisabled() && typeof variant === 'number') {
|
if (!this.variantDisabled() && typeof variant === 'number') {
|
||||||
this.variantChange.emit(variant);
|
this.variantChange.emit(variant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<h2 class="m-0 text-uppercase fw-bold cart-title">{{ title() }}</h2>
|
<h2 class="m-0 text-uppercase fw-bold cart-title">{{ title() }}</h2>
|
||||||
|
|
||||||
<div class="d-flex align-items-center cart-header-actions">
|
<div class="d-flex align-items-center cart-header-actions">
|
||||||
@if (!readonly() && editable() && allowEditing() && items().length > 0) {
|
@if (!readonly() && allowModify() && requireEditingMode() && items().length > 0) {
|
||||||
<button
|
<button
|
||||||
class="btn btn-link p-0 border-0 cart-edit-btn"
|
class="btn btn-link p-0 border-0 cart-edit-btn"
|
||||||
type="button"
|
type="button"
|
||||||
@@ -48,8 +48,22 @@
|
|||||||
[selectedVariant]="getItemVariant(item)"
|
[selectedVariant]="getItemVariant(item)"
|
||||||
[quantity]="getItemQuantity(item)"
|
[quantity]="getItemQuantity(item)"
|
||||||
[readonly]="readonly()"
|
[readonly]="readonly()"
|
||||||
[quantityDisabled]="!editable() || editingDisabled() || (allowEditing() && !editing())"
|
[quantityDisabled]="
|
||||||
[showRemove]="allowRemove()"
|
readonly() ||
|
||||||
|
!allowUpdateQuantity() ||
|
||||||
|
editingDisabled() ||
|
||||||
|
(requireEditingMode() && !editing())
|
||||||
|
"
|
||||||
|
[variantDisabled]="
|
||||||
|
readonly() ||
|
||||||
|
!allowUpdateVariant() ||
|
||||||
|
editingDisabled() ||
|
||||||
|
(requireEditingMode() && !editing())
|
||||||
|
"
|
||||||
|
[removeDisabled]="
|
||||||
|
readonly() || !allowDelete() || editingDisabled() || (requireEditingMode() && !editing())
|
||||||
|
"
|
||||||
|
[allowDelete]="allowDelete()"
|
||||||
(quantityChange)="onItemQuantityChange(idx, $event)"
|
(quantityChange)="onItemQuantityChange(idx, $event)"
|
||||||
(variantChange)="onItemVariantChange(idx, $event)"
|
(variantChange)="onItemVariantChange(idx, $event)"
|
||||||
(remove)="onItemRemove(idx)"
|
(remove)="onItemRemove(idx)"
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ describe('CartComponent', () => {
|
|||||||
quantity: 1,
|
quantity: 1,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
fixture.componentRef.setInput('allowEditing', true);
|
fixture.componentRef.setInput('requireEditingMode', true);
|
||||||
const editingChange = vi.fn();
|
const editingChange = vi.fn();
|
||||||
fixture.componentInstance.editing.subscribe(editingChange);
|
fixture.componentInstance.editing.subscribe(editingChange);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -408,7 +408,7 @@ describe('CartComponent', () => {
|
|||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('hides the edit toggle and disables quantity changes when editable is false', async () => {
|
it('hides the edit toggle and disables quantity changes when quantity updates are false', async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [CartComponent],
|
imports: [CartComponent],
|
||||||
providers: [
|
providers: [
|
||||||
@@ -441,8 +441,9 @@ describe('CartComponent', () => {
|
|||||||
quantity: 1,
|
quantity: 1,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
fixture.componentRef.setInput('allowEditing', true);
|
fixture.componentRef.setInput('requireEditingMode', true);
|
||||||
fixture.componentRef.setInput('editable', false);
|
fixture.componentRef.setInput('allowModify', false);
|
||||||
|
fixture.componentRef.setInput('allowUpdateQuantity', false);
|
||||||
const quantityChange = vi.fn();
|
const quantityChange = vi.fn();
|
||||||
fixture.componentInstance.itemQuantityChange.subscribe(quantityChange);
|
fixture.componentInstance.itemQuantityChange.subscribe(quantityChange);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|||||||
@@ -53,9 +53,11 @@ export class CartComponent {
|
|||||||
readonly total = input<number>(0);
|
readonly total = input<number>(0);
|
||||||
readonly backgroundColor = input<string>('#ffffff');
|
readonly backgroundColor = input<string>('#ffffff');
|
||||||
readonly readonly = input<boolean>(false);
|
readonly readonly = input<boolean>(false);
|
||||||
readonly editable = input<boolean>(true);
|
readonly allowUpdateQuantity = input<boolean>(true);
|
||||||
readonly allowEditing = input<boolean>(false);
|
readonly allowModify = input<boolean>(true);
|
||||||
readonly allowRemove = input<boolean>(true);
|
readonly requireEditingMode = input<boolean>(false);
|
||||||
|
readonly allowUpdateVariant = input<boolean>(true);
|
||||||
|
readonly allowDelete = input<boolean>(true);
|
||||||
readonly persistQuantityChanges = input<boolean>(true);
|
readonly persistQuantityChanges = input<boolean>(true);
|
||||||
readonly editingDisabled = input<boolean>(false);
|
readonly editingDisabled = input<boolean>(false);
|
||||||
readonly editing = model<boolean>(false);
|
readonly editing = model<boolean>(false);
|
||||||
@@ -125,7 +127,7 @@ export class CartComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onItemQuantityChange(index: number, newQuantity: number): void {
|
protected onItemQuantityChange(index: number, newQuantity: number): void {
|
||||||
if (!this.editable()) {
|
if (!this.allowUpdateQuantity()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +172,8 @@ export class CartComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onItemVariantChange(index: number, variantId: number): void {
|
protected onItemVariantChange(index: number, variantId: number): void {
|
||||||
|
if (this.readonly() || !this.allowUpdateVariant() || this.editingDisabled()) return;
|
||||||
|
|
||||||
const item = this.items()[index];
|
const item = this.items()[index];
|
||||||
const cartItemId = item?.cartItemId;
|
const cartItemId = item?.cartItemId;
|
||||||
|
|
||||||
@@ -200,6 +204,8 @@ export class CartComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onItemRemove(index: number): void {
|
protected onItemRemove(index: number): void {
|
||||||
|
if (this.readonly() || !this.allowDelete() || this.editingDisabled()) return;
|
||||||
|
|
||||||
const target = this.resolveRemoveTarget(index);
|
const target = this.resolveRemoveTarget(index);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
@@ -225,7 +231,7 @@ export class CartComponent {
|
|||||||
protected readonly formattedTotal = computed(() => this.formatCurrency(this.total()));
|
protected readonly formattedTotal = computed(() => this.formatCurrency(this.total()));
|
||||||
|
|
||||||
protected toggleEditing(): void {
|
protected toggleEditing(): void {
|
||||||
if (!this.editable() || this.editingDisabled()) {
|
if (!this.allowModify() || this.editingDisabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user