codexly-ui 0.23.0 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14075,11 +14075,6 @@ class ClxPaginationComponent {
14075
14075
  _destroyRef = inject(DestroyRef);
14076
14076
  // ── FormControl interno para el select de pageSize ─────────────────────────
14077
14077
  _pageSizeCtrl = new FormControl(null);
14078
- /** True once the user has explicitly picked a pageSize from the select — after that, their
14079
- * choice is respected even if a later filter shrinks totalItems below it. Until then, a
14080
- * caller-provided default (e.g. 20) that exceeds a small totalItems is auto-corrected down
14081
- * to the smallest available option, so the select never opens pre-selected on the largest value. */
14082
- _userTouchedPageSize = false;
14083
14078
  constructor() {
14084
14079
  // Sincroniza el pageSize model → FormControl cada vez que cambia desde afuera
14085
14080
  effect(() => {
@@ -14088,31 +14083,14 @@ class ClxPaginationComponent {
14088
14083
  this._pageSizeCtrl.setValue(ps, { emitEvent: false });
14089
14084
  }
14090
14085
  });
14091
- // Mientras el usuario no haya elegido un pageSize a propósito, si el default provisto por el
14092
- // padre excede totalItems, se ajusta al más pequeño disponible en vez de quedar seleccionado
14093
- // como si fuera el "más grande elegido". Debe emitir pageChange/sizeChange igual que la
14094
- // selección manual — si no, el consumidor (ej. clx-table → su padre real) nunca se entera
14095
- // del nuevo tamaño y sigue pidiendo datos al backend con el size viejo.
14096
- effect(() => {
14097
- if (this._userTouchedPageSize)
14098
- return;
14099
- const total = this.totalItems();
14100
- if (!total || total <= 0)
14101
- return;
14102
- const smallest = this._pageSizeOptions()[0]?.value;
14103
- if (smallest != null && this.pageSize() > total && smallest !== this.pageSize()) {
14104
- this.pageSize.set(smallest);
14105
- this.currentPage.set(1);
14106
- this.sizeChange.emit({ pageSize: smallest });
14107
- this.pageChange.emit({ page: 1, pageSize: smallest });
14108
- }
14109
- });
14086
+ // El pageSize solo cambia cuando el usuario lo elige: nunca se ajusta solo según totalItems.
14087
+ // Antes se reducía a la opción más pequeña cuando había menos registros que el pageSize, lo
14088
+ // que mostraba 5 por página donde cabían todos y obligaba al consumidor a pedir los datos de nuevo.
14110
14089
  // Sincroniza el FormControl → pageSize model cuando el usuario elige
14111
14090
  this._pageSizeCtrl.valueChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(val => {
14112
14091
  const newSize = Number(val);
14113
14092
  if (!val || !Number.isFinite(newSize) || newSize <= 0 || newSize === this.pageSize())
14114
14093
  return;
14115
- this._userTouchedPageSize = true;
14116
14094
  this.pageSize.set(newSize);
14117
14095
  this.currentPage.set(1);
14118
14096
  this.sizeChange.emit({ pageSize: newSize });
@@ -18994,6 +18972,12 @@ class ClxCartComponent {
18994
18972
  : c.value;
18995
18973
  }, ...(ngDevMode ? [{ debugName: "_couponDiscount" }] : /* istanbul ignore next */ []));
18996
18974
  _total = computed(() => Math.max(0, this._subtotal() - this._couponDiscount()), ...(ngDevMode ? [{ debugName: "_total" }] : /* istanbul ignore next */ []));
18975
+ _exceedsStock(item) {
18976
+ return item.in_stock && item.max_quantity != null && item.quantity > item.max_quantity;
18977
+ }
18978
+ /** Lines that can't be bought as they are — out of stock, or more units than are left. While any
18979
+ * exists the checkout button stays disabled. */
18980
+ _blockedItems = computed(() => this.items().filter(i => !i.in_stock || this._exceedsStock(i)), ...(ngDevMode ? [{ debugName: "_blockedItems" }] : /* istanbul ignore next */ []));
18997
18981
  _totalUnits = computed(() => this.items().reduce((s, i) => s + i.quantity, 0), ...(ngDevMode ? [{ debugName: "_totalUnits" }] : /* istanbul ignore next */ []));
18998
18982
  applyCoupon() {
18999
18983
  const code = this._couponCode.trim();
@@ -19112,6 +19096,17 @@ class ClxCartComponent {
19112
19096
  <p class="text-sm text-clx-text-subtle truncate">{{ item.trademark }}</p>
19113
19097
  <h3 class="text-sm font-semibold text-clx-text-label leading-snug line-clamp-2">{{ item.name }}</h3>
19114
19098
  <p class="text-sm font-mono text-clx-text-subtle mt-0.5">{{ item.sku }}</p>
19099
+ @if (!item.in_stock) {
19100
+ <p class="flex items-center gap-1 text-xs font-medium text-red-600 mt-1">
19101
+ <span clx-icon name="block" size="xs"></span>
19102
+ Agotado — quítalo para continuar con tu compra
19103
+ </p>
19104
+ } @else if (_exceedsStock(item)) {
19105
+ <p class="flex items-center gap-1 text-xs font-medium text-amber-600 mt-1">
19106
+ <span clx-icon name="warning" size="xs"></span>
19107
+ Solo {{ item.max_quantity === 1 ? 'queda 1 disponible' : 'quedan ' + item.max_quantity + ' disponibles' }} — ajusta la cantidad
19108
+ </p>
19109
+ }
19115
19110
  </div>
19116
19111
 
19117
19112
  <!-- Price + Quantity row -->
@@ -19245,11 +19240,23 @@ class ClxCartComponent {
19245
19240
  </div>
19246
19241
  </dl>
19247
19242
 
19243
+ <!-- Stock problems block the checkout: the order would be rejected anyway -->
19244
+ @if (_blockedItems().length) {
19245
+ <div class="flex items-start gap-2 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2.5 text-xs text-amber-800">
19246
+ <span clx-icon name="warning" size="sm" class="shrink-0 mt-px"></span>
19247
+ <span>
19248
+ {{ _blockedItems().length === 1 ? 'Un producto de tu carrito no está disponible' : _blockedItems().length + ' productos de tu carrito no están disponibles' }}
19249
+ en la cantidad elegida. Quítalo o ajusta la cantidad para continuar.
19250
+ </span>
19251
+ </div>
19252
+ }
19253
+
19248
19254
  <!-- Checkout -->
19249
19255
  <button
19250
19256
  clx-button type="button" [color]="color()" variant="solid" size="md"
19251
19257
  icon="arrow_forward" iconPosition="right" [block]="true"
19252
- (click)="onCheckout.emit()">
19258
+ [disabled]="_blockedItems().length > 0"
19259
+ (click)="_blockedItems().length === 0 && onCheckout.emit()">
19253
19260
  Proceder al pago
19254
19261
  </button>
19255
19262
 
@@ -19393,6 +19400,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
19393
19400
  <p class="text-sm text-clx-text-subtle truncate">{{ item.trademark }}</p>
19394
19401
  <h3 class="text-sm font-semibold text-clx-text-label leading-snug line-clamp-2">{{ item.name }}</h3>
19395
19402
  <p class="text-sm font-mono text-clx-text-subtle mt-0.5">{{ item.sku }}</p>
19403
+ @if (!item.in_stock) {
19404
+ <p class="flex items-center gap-1 text-xs font-medium text-red-600 mt-1">
19405
+ <span clx-icon name="block" size="xs"></span>
19406
+ Agotado — quítalo para continuar con tu compra
19407
+ </p>
19408
+ } @else if (_exceedsStock(item)) {
19409
+ <p class="flex items-center gap-1 text-xs font-medium text-amber-600 mt-1">
19410
+ <span clx-icon name="warning" size="xs"></span>
19411
+ Solo {{ item.max_quantity === 1 ? 'queda 1 disponible' : 'quedan ' + item.max_quantity + ' disponibles' }} — ajusta la cantidad
19412
+ </p>
19413
+ }
19396
19414
  </div>
19397
19415
 
19398
19416
  <!-- Price + Quantity row -->
@@ -19526,11 +19544,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
19526
19544
  </div>
19527
19545
  </dl>
19528
19546
 
19547
+ <!-- Stock problems block the checkout: the order would be rejected anyway -->
19548
+ @if (_blockedItems().length) {
19549
+ <div class="flex items-start gap-2 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2.5 text-xs text-amber-800">
19550
+ <span clx-icon name="warning" size="sm" class="shrink-0 mt-px"></span>
19551
+ <span>
19552
+ {{ _blockedItems().length === 1 ? 'Un producto de tu carrito no está disponible' : _blockedItems().length + ' productos de tu carrito no están disponibles' }}
19553
+ en la cantidad elegida. Quítalo o ajusta la cantidad para continuar.
19554
+ </span>
19555
+ </div>
19556
+ }
19557
+
19529
19558
  <!-- Checkout -->
19530
19559
  <button
19531
19560
  clx-button type="button" [color]="color()" variant="solid" size="md"
19532
19561
  icon="arrow_forward" iconPosition="right" [block]="true"
19533
- (click)="onCheckout.emit()">
19562
+ [disabled]="_blockedItems().length > 0"
19563
+ (click)="_blockedItems().length === 0 && onCheckout.emit()">
19534
19564
  Proceder al pago
19535
19565
  </button>
19536
19566