codexly-ui 0.23.1 → 0.24.0

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.
@@ -17436,12 +17436,16 @@ class ClxProductTagService {
17436
17436
  badgesFor(ctx) {
17437
17437
  const styles = this._styles() ?? [];
17438
17438
  const manual = new Set(ctx.tags);
17439
+ const hidden = new Set(ctx.hiddenSystemTags ?? []);
17439
17440
  const units = ctx.stockQuantity;
17440
17441
  const low = styles.find(s => s.kind === 'LOW_STOCK');
17441
- // "Últimas unidades" replaces "N en stock" — both would say the same.
17442
- const isLow = !!low && ctx.inStock && units != null && units > 0 && units <= (low.stockThreshold ?? 0);
17442
+ const threshold = ctx.lowStockThreshold ?? low?.stockThreshold ?? 0;
17443
+ // "Últimas unidades" replaces "N en stock" — both would say the same (unless it's hidden here).
17444
+ const isLow = !!low && !hidden.has('LOW_STOCK') && ctx.inStock && units != null && units > 0 && units <= threshold;
17443
17445
  const out = [];
17444
17446
  for (const s of styles) {
17447
+ if (s.kind !== 'MANUAL' && hidden.has(s.kind))
17448
+ continue;
17445
17449
  let n = null;
17446
17450
  switch (s.kind) {
17447
17451
  case 'MANUAL':
@@ -17595,6 +17599,7 @@ class ClxProductComponent {
17595
17599
  return p
17596
17600
  ? this._tagSvc.badgesFor({
17597
17601
  tags: p.tags ?? [], inStock: p.in_stock, stockQuantity: p.stock_quantity, discountPercent: this._discountPct(),
17602
+ hiddenSystemTags: p.hidden_system_tags, lowStockThreshold: p.low_stock_threshold,
17598
17603
  })
17599
17604
  : [];
17600
17605
  }, ...(ngDevMode ? [{ debugName: "_badges" }] : /* istanbul ignore next */ []));
@@ -18195,18 +18200,21 @@ class ClxProductDetailComponent {
18195
18200
  }
18196
18201
  return 0;
18197
18202
  }, ...(ngDevMode ? [{ debugName: "discount" }] : /* istanbul ignore next */ []));
18198
- /** The host's configured tags (ClxProductTagService) for the selected variation, over the gallery. */
18203
+ /** The host's configured tags (ClxProductTagService) for the selected variation, over the gallery —
18204
+ * the variation's own tags and settings when the host sends them, else the product's. */
18199
18205
  _badges = computed(() => {
18200
18206
  const p = this.product();
18201
18207
  const v = this.activeVariation();
18202
18208
  if (!p || !v)
18203
18209
  return [];
18204
18210
  return this._tagSvc.badgesFor({
18205
- tags: p.tags ?? [],
18211
+ tags: v.tags ?? p.tags ?? [],
18206
18212
  inStock: v.in_stock,
18207
18213
  stockQuantity: v.stock_quantity,
18208
18214
  showStockCount: true,
18209
18215
  discountPercent: p.has_discount ? this.discount() : 0,
18216
+ hiddenSystemTags: v.hidden_system_tags ?? p.hidden_system_tags,
18217
+ lowStockThreshold: v.low_stock_threshold !== undefined ? v.low_stock_threshold : p.low_stock_threshold,
18210
18218
  });
18211
18219
  }, ...(ngDevMode ? [{ debugName: "_badges" }] : /* istanbul ignore next */ []));
18212
18220
  /** An option is available if some in-stock variation matches it together with the rest of the
@@ -18972,6 +18980,12 @@ class ClxCartComponent {
18972
18980
  : c.value;
18973
18981
  }, ...(ngDevMode ? [{ debugName: "_couponDiscount" }] : /* istanbul ignore next */ []));
18974
18982
  _total = computed(() => Math.max(0, this._subtotal() - this._couponDiscount()), ...(ngDevMode ? [{ debugName: "_total" }] : /* istanbul ignore next */ []));
18983
+ _exceedsStock(item) {
18984
+ return item.in_stock && item.max_quantity != null && item.quantity > item.max_quantity;
18985
+ }
18986
+ /** Lines that can't be bought as they are — out of stock, or more units than are left. While any
18987
+ * exists the checkout button stays disabled. */
18988
+ _blockedItems = computed(() => this.items().filter(i => !i.in_stock || this._exceedsStock(i)), ...(ngDevMode ? [{ debugName: "_blockedItems" }] : /* istanbul ignore next */ []));
18975
18989
  _totalUnits = computed(() => this.items().reduce((s, i) => s + i.quantity, 0), ...(ngDevMode ? [{ debugName: "_totalUnits" }] : /* istanbul ignore next */ []));
18976
18990
  applyCoupon() {
18977
18991
  const code = this._couponCode.trim();
@@ -19090,6 +19104,17 @@ class ClxCartComponent {
19090
19104
  <p class="text-sm text-clx-text-subtle truncate">{{ item.trademark }}</p>
19091
19105
  <h3 class="text-sm font-semibold text-clx-text-label leading-snug line-clamp-2">{{ item.name }}</h3>
19092
19106
  <p class="text-sm font-mono text-clx-text-subtle mt-0.5">{{ item.sku }}</p>
19107
+ @if (!item.in_stock) {
19108
+ <p class="flex items-center gap-1 text-xs font-medium text-red-600 mt-1">
19109
+ <span clx-icon name="block" size="xs"></span>
19110
+ Agotado — quítalo para continuar con tu compra
19111
+ </p>
19112
+ } @else if (_exceedsStock(item)) {
19113
+ <p class="flex items-center gap-1 text-xs font-medium text-amber-600 mt-1">
19114
+ <span clx-icon name="warning" size="xs"></span>
19115
+ Solo {{ item.max_quantity === 1 ? 'queda 1 disponible' : 'quedan ' + item.max_quantity + ' disponibles' }} — ajusta la cantidad
19116
+ </p>
19117
+ }
19093
19118
  </div>
19094
19119
 
19095
19120
  <!-- Price + Quantity row -->
@@ -19223,11 +19248,23 @@ class ClxCartComponent {
19223
19248
  </div>
19224
19249
  </dl>
19225
19250
 
19251
+ <!-- Stock problems block the checkout: the order would be rejected anyway -->
19252
+ @if (_blockedItems().length) {
19253
+ <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">
19254
+ <span clx-icon name="warning" size="sm" class="shrink-0 mt-px"></span>
19255
+ <span>
19256
+ {{ _blockedItems().length === 1 ? 'Un producto de tu carrito no está disponible' : _blockedItems().length + ' productos de tu carrito no están disponibles' }}
19257
+ en la cantidad elegida. Quítalo o ajusta la cantidad para continuar.
19258
+ </span>
19259
+ </div>
19260
+ }
19261
+
19226
19262
  <!-- Checkout -->
19227
19263
  <button
19228
19264
  clx-button type="button" [color]="color()" variant="solid" size="md"
19229
19265
  icon="arrow_forward" iconPosition="right" [block]="true"
19230
- (click)="onCheckout.emit()">
19266
+ [disabled]="_blockedItems().length > 0"
19267
+ (click)="_blockedItems().length === 0 && onCheckout.emit()">
19231
19268
  Proceder al pago
19232
19269
  </button>
19233
19270
 
@@ -19371,6 +19408,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
19371
19408
  <p class="text-sm text-clx-text-subtle truncate">{{ item.trademark }}</p>
19372
19409
  <h3 class="text-sm font-semibold text-clx-text-label leading-snug line-clamp-2">{{ item.name }}</h3>
19373
19410
  <p class="text-sm font-mono text-clx-text-subtle mt-0.5">{{ item.sku }}</p>
19411
+ @if (!item.in_stock) {
19412
+ <p class="flex items-center gap-1 text-xs font-medium text-red-600 mt-1">
19413
+ <span clx-icon name="block" size="xs"></span>
19414
+ Agotado — quítalo para continuar con tu compra
19415
+ </p>
19416
+ } @else if (_exceedsStock(item)) {
19417
+ <p class="flex items-center gap-1 text-xs font-medium text-amber-600 mt-1">
19418
+ <span clx-icon name="warning" size="xs"></span>
19419
+ Solo {{ item.max_quantity === 1 ? 'queda 1 disponible' : 'quedan ' + item.max_quantity + ' disponibles' }} — ajusta la cantidad
19420
+ </p>
19421
+ }
19374
19422
  </div>
19375
19423
 
19376
19424
  <!-- Price + Quantity row -->
@@ -19504,11 +19552,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
19504
19552
  </div>
19505
19553
  </dl>
19506
19554
 
19555
+ <!-- Stock problems block the checkout: the order would be rejected anyway -->
19556
+ @if (_blockedItems().length) {
19557
+ <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">
19558
+ <span clx-icon name="warning" size="sm" class="shrink-0 mt-px"></span>
19559
+ <span>
19560
+ {{ _blockedItems().length === 1 ? 'Un producto de tu carrito no está disponible' : _blockedItems().length + ' productos de tu carrito no están disponibles' }}
19561
+ en la cantidad elegida. Quítalo o ajusta la cantidad para continuar.
19562
+ </span>
19563
+ </div>
19564
+ }
19565
+
19507
19566
  <!-- Checkout -->
19508
19567
  <button
19509
19568
  clx-button type="button" [color]="color()" variant="solid" size="md"
19510
19569
  icon="arrow_forward" iconPosition="right" [block]="true"
19511
- (click)="onCheckout.emit()">
19570
+ [disabled]="_blockedItems().length > 0"
19571
+ (click)="_blockedItems().length === 0 && onCheckout.emit()">
19512
19572
  Proceder al pago
19513
19573
  </button>
19514
19574