{"version":3,"sources":["webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/brand-filter.ts","webpack:///./src/components/product/brand-filter.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/filter-value-order.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-filter.ts","webpack:///./src/components/product/product-filter.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/add-to-cart.ts","webpack:///./src/components/product/product-list/add-to-cart.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/copy-to-clipboard.ts","webpack:///./src/components/product/product-list/copy-to-clipboard.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/extra-row.ts","webpack:///./src/components/product/product-list/extra-row.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/gallery.ts","webpack:///./src/components/product/product-list/gallery.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/price.ts","webpack:///./src/components/product/product-list/price.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/product-list.ts","webpack:///./src/components/product/product-list/product-list.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/report-button.ts","webpack:///./src/components/product/product-list/report-button.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/stock.ts","webpack:///./src/components/product/product-list/stock.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/search/categories.ts","webpack:///./src/components/product/search/categories.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/search/search-bar.ts","webpack:///./src/components/product/search/search-bar.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/sale/order/order-list.ts","webpack:///./src/components/sale/order/order-list.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/sale/order/order-search-bar.ts","webpack:///./src/components/sale/order/order-search-bar.html"],"names":["log","getLogger","chosenBrands","uid","instanceCount","brandSearch","BrandFilterCustomElement","resetView","this","toggleButton","getOrCreateInstance","hide","undefined","possibleBrands","term","trim","toLowerCase","length","filter","brand","includes","openDropdown","load","isChosen","indexOf","toggleBrand","chosen","notifyChanged","resetChosenBrands","changed","brands","defaultBindingMode","twoWay","module","exports","compareNumericSize","a","b","left","String","right","leftNumber","Number","rightNumber","leftIsNumber","isFinite","rightIsNumber","NUMERIC_SIZE_FILTERS","Set","eventAggregator","i18n","disabledFilters","filtersPending","pendingGroup","chosenFiltersCount","sortingFilters","attached","updateChosenFiltersCount","sortPossibleFilters","createSliders","prefillFilters","categoryIdChanged","newValue","oldValue","resetChosenFilters","possibleFiltersChanged","possibleFilters","sortedPossibleFilters","key","values","Array","isArray","sorted","has","slice","sort","areAllNumbers","some","value","index","Object","keys","array","every","isNaN","shouldUseSlider","categoryId","document","querySelectorAll","forEach","container","getAttribute","filterValues","min","Math","max","createSlider","slider","create","start","range","connect","tooltips","direction","orientation","format","decimals","step","pips","mode","Positions","stepped","density","on","chooseFilter","chosenFilters","clearFilterBadges","entries","prefillFilter","temporaryPossibleFilters","sliders","prefillSliders","item","addFilterBadge","join","target","noUiSlider","chosenMin","chosenMax","options","set","isFilterValueChosen","chosenValue","areFilterValuesEqual","isFilterValueDisabled","isOptionDisabled","isFilterValueLocked","pending","isOptionLocked","firstValue","secondValue","text","filterBadge","getElementByKey","keyName","translateKey","displayText","translateBadgeValues","innerText","style","display","split","map","part","translateValue","filterValueLabel","filterEntries","seasonEntries","nested","element","getElementById","i","children","child","nodeName","clearElement","clearFilterBadge","innerHTML","HTMLInputElement","applySeasonFamily","classList","contains","getSliderFilterValues","getCheckboxFilterValues","updateChosenFilters","chosenValues","get","parseInt","push","clicked","boxes","from","available","box","selected","checked","next","seasonChoice","checkedBoxes","publishChosenFiltersChanged","removeSliders","getElementsByClassName","destroy","publish","TKEvent","chosenFiltersChanged","reduce","sum","ProductFilterCustomElement","rowSequence","cartProductService","appConfig","rowUid","currencyFormat","gate","getUniqueProductId","product","source","id","foundBy","code","tryAddToCart","ensureValidMinimumQuantity","busy","cartWarningNeeded","confirmModalEl","requestConfirm","show","addToCart","confirmAddToCart","takeConfirm","cancelConfirm","quantity","toCartQuantity","buttons","addToCartButtonEl","addToCartWarnButtonEl","begin","disabled","post","getRequestData","then","showSuccessToast","tr","cartProductsChanged","catch","showErrorToast","finally","end","getMinimumQuantity","selectedStock","showsMinimumQuantityHint","isValidMinimumQuantity","toString","data","warehouseId","warehouse","isExternalWarehouse","externalWarehouseId","otherWarehouseWarningNeeded","otherWarehouseIdWarningNeeded","isExternal","userWarehouseId","userSettings","externalWarehouseGroupId","hasStockWarning","hasRefundableDeposit","hasExternalStockWarning","getSelectedRefundableDepositSource","getRefundableDeposit","getRefundableDepositLabel","refundableDeposit","toView","getRefundableDepositWarningText","lines","price","getStockWarningText","groupId","getExternalWarningGroupId","stockWarehouseId","getWarehouseWarningId","AddToCartCustomElement","Element","copyToClipboard","navigator","clipboard","writeText","CopyToClipboardCustomElement","router","bindingEngine","oeNumberTree","oeNumbersSubscription","subscribeToOeNumbers","buildOeNumberTree","detached","disposeOeNumbersSubscription","productChanged","propertyObserver","subscribe","dispose","oeNumbers","manufacturerIndex","manufacturer","name","oeNumber","oeNumberIndex","query","infoLabel","info","translateInfoPair","infoValue","infoHref","openDocument","productId","win","startsWith","window","open","apiUrl","focus","showGallery","loadVehicle","navigateToRoute","vehicleId","searchOeNumber","page","type","TecDoc","searchOeTreeItem","ExtraRowCustomElement","priceTooltip","pricesToTooltip","bind","updateRefundableDepositInfo","pricesChanged","prices","displayPrice","stockItemChanged","hasAmountDependentPrice","refundableDepositSource","getRefundableDepositSource","getPriceTooltip","priceLines","getRefundableDepositLine","stockItem","PriceCustomElement","productService","warehouseService","currentPage","lastPage","orderBy","Default","orderReversed","pageHasEan","pageHasBrand","pageHasInPackage","colSpan","imageRowspan","showAmount","showSum","showAddToCart","warehouses","SearchOrder","settingsSubscription","userSettingsLoaded","formatPrice","productsChanged","prepareProductsForBinding","processResult","products","stock","externalStock","vehicleIdChanged","loadInfoBatch","loadImagesBatch","loadSortables","moveRowsListener","detailsInProductPage","imagesInProductPage","renderColumnsConditionally","getWarehouses","hasTkItem","formatStockPrices","fillDefaultSelectedStock","isPositive","highlightSearchQuery","loadThumbnail","loadExternalStockBatch","remove","append","find","addClass","Promise","resolve","warehousesRequest","result","debug","imageLoadingCount","fetchThumbnail","thumbnailVersion","thumbnail","error","handleRequestNoise","getErrorMessage","thumbnailFailed","thumbnailLoaded","trigger","closest","getInstance","content","html","tkItems","p","rows","byId","fetchImagesBatch","request","images","batchFailed","oldVehicleId","fetchInfoBatch","isArrayEmpty","extractEanFromInfo","lastBatchError","loadDescription","oldCategoryId","fetchDescriptionWithCategory","fetchDescription","description","afterLoading","loadDocuments","fetchDocumentsWithCategory","fetchDocuments","documents","loadOeNumbers","fetchOeNumbers","isObjectEmpty","loadCars","fetchCars","cars","fetchExternalStockBatch","existingExternalStock","cached","preserveExternalStockRefundableDeposit","x","isInStock","s","getFallbackStock","ean","eanIndex","findIndex","at","splice","changeOrder","clickedElement","parentElement","toggleExtraRow","prop","productWrappers","areExtrasLoaded","is","tryOpenExtraRow","shouldExtraRowOpen","showDetails","showImages","anyDataInExtraRow","noHiddenData","inPackage","noHiddenDetails","noDescriptions","noHiddenImages","noExtras","isAnyExtras","regex","RegExp","escapeRegex","replace","classToRemove","removeClass","isUserToggle","extraRow","querySelector","parent","toggle","each","attr","insertAfter","formatProductsPrices","pageHasEANChecker","pageHasBrandChecker","pageHasInPackageChecker","resetConditionalColumnRendering","activateExtendedSearch","extendedSearch","cat","ProductListCustomElement","sendProductReport","reportText","postReportError","ReportButtonCustomElement","getValue","takeIntoStockUserWish","productCode","confirm","postProductStockRequest","getStockQuantity","updateStockFromWarehouse","updateStock","isAllowed","snapToCartQuantityToMinimum","fallbackStock","cartProductsWarehouseChanged","allWarehousesNotAllowed","getNotAllowedStock","externalStockLabel","getExternalWarehouseLabel","getExternalStockByGroup","groupIds","otherStockWarningNeeded","StockCustomElement","categoryService","activate","isLoggedIn","loadCategoryMenu","event","instruction","config","categories","fetchCategories","positionSubmenu","openCategory","category","position","panel","level1","group","level1Rect","getBoundingClientRect","groupRect","visibleTop","top","maxHeight","innerHeight","minHeight","clientHeight","css","width","panelRect","getComputedStyle","contentRight","neededWidth","parseFloat","paddingRight","borderRightWidth","viewportWidth","documentElement","clientWidth","availableWidth","ceil","scrollHeight","scrollbar","offsetWidth","hasClass","parents","first","subMenu","toggleClass","menu","prev","Categories","searchDelayMilliseconds","searchNow","hasFocus","subscribeOnce","defaultSearchLimitation","currentRoute","currentParams","params","updateFromRoute","currentInstruction","getAllInstructions","queryChanged","newQuery","oldQuery","clearTimeout","searchTimer","pendingSearch","delayedSearch","typeChanged","newType","oldType","now","run","search","setTimeout","pasted","keyDown","routeQuery","All","SearchBar","orderService","showInvoiceId","showWarehouse","showTransport","showAddToReturn","showConvertToCart","orders","order","originalId","convertToCart","convertRvsOrderToCart","toggleProductList","productListElement","canConvertToCart","amount","OrderListCustomElement"],"mappings":"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","file":"app~558ff103.314c0c9a2d854bdaccb4.chunk.js","sourcesContent":["import { LogManager, autoinject, bindable, bindingMode, computedFrom } from \"aurelia-framework\";\nimport { Dropdown } from \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.components.brand-filter\");\n\n@autoinject\nexport class BrandFilterCustomElement {\n  // undefined = not loaded yet (spinner shown while the dropdown is open)\n  @bindable possibleBrands?: string[];\n  @bindable({ defaultBindingMode: bindingMode.twoWay }) chosenBrands: string[] = [];\n  @bindable load: () => void;\n  // The two-way chosenBrands binding only propagates to the parent as a microtask,\n  // so the fresh selection is also passed directly as a call argument.\n  @bindable changed: (args: { brands: string[] }) => void;\n\n  // Unique per instance so checkbox label \"for\" ids can't collide if the\n  // element is ever instantiated twice on one page\n  private static instanceCount = 0;\n  uid = ++BrandFilterCustomElement.instanceCount;\n\n  brandSearch = \"\";\n  toggleButton: HTMLButtonElement;\n\n  // Called by the page when the search scope changes: the loaded brand list no\n  // longer applies, so collapse the dropdown (a dropdown left open here would\n  // keep showing the old list and reappear mispositioned) and clear the filter\n  // text. The next open fetches the new scope's list.\n  resetView() {\n    this.brandSearch = \"\";\n    if (this.toggleButton) Dropdown.getOrCreateInstance(this.toggleButton).hide();\n  }\n\n  @computedFrom(\"possibleBrands\", \"brandSearch\")\n  get filteredBrands(): string[] {\n    if (this.possibleBrands === undefined) return [];\n\n    const term = this.brandSearch.trim().toLowerCase();\n    if (term.length == 0) return this.possibleBrands;\n\n    return this.possibleBrands.filter(brand => brand.toLowerCase().includes(term));\n  }\n\n  openDropdown(): boolean {\n    if (this.load) this.load();\n\n    // Let the bootstrap dropdown toggle proceed\n    return true;\n  }\n\n  // The template passes chosenBrands as an argument so the binding re-evaluates\n  // when the array is replaced - Aurelia only observes a call's arguments.\n  isChosen(brand: string, chosenBrands: string[] = this.chosenBrands): boolean {\n    return chosenBrands.indexOf(brand) !== -1;\n  }\n\n  toggleBrand(brand: string): boolean {\n    if (this.isChosen(brand)) {\n      this.chosenBrands = this.chosenBrands.filter(chosen => chosen !== brand);\n    } else {\n      this.chosenBrands = [...this.chosenBrands, brand];\n    }\n\n    this.notifyChanged();\n\n    // Let the checkbox update itself\n    return true;\n  }\n\n  resetChosenBrands() {\n    if (this.chosenBrands.length == 0) return;\n\n    this.chosenBrands = [];\n    this.notifyChanged();\n  }\n\n  private notifyChanged() {\n    if (this.changed) this.changed({ brands: this.chosenBrands });\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"/node_modules/bootstrap-icons/font/bootstrap-icons.css\\\"></require>\\n\\n  <!-- Laid out as a full-width filter bar to match the tyre category filters\\n       (see product-filter.html): the shared \\\"Filtrid:\\\" header, a growing\\n       spacer cell that stretches the bar to full width, then the Bränd\\n       dropdown on the right. Its menu opens leftward (see the button and the\\n       #brand-filter rule in style.css) so it doesn't run off the right edge.\\n       Distance to the search bar above is 1.5rem: search-box pb (0.25rem)\\n       + main mt-3 (1rem) + pt-1 here (0.25rem). -->\\n  <div class=\\\"pt-1 pb-3 w-100\\\">\\n    <div class=\\\"input-group mx-auto\\\" id=\\\"brand-filter\\\">\\n      <span class=\\\"input-group-text\\\">${'pages.category.filters.header' & t}</span>\\n\\n      <span class=\\\"input-group-text form-control\\\"></span>\\n\\n      <div class=\\\"dropdown\\\">\\n        <!-- data-bs-display=\\\"static\\\" turns off Popper positioning for this\\n             menu; Popper aligned it to the left here (running off the right\\n             edge), so the menu is right-aligned deterministically via CSS\\n             instead (#brand-filter .dropdown-menu in style.css). -->\\n        <button class=\\\"btn btn-outline-primary dropdown-toggle\\\" type=\\\"button\\\" ref=\\\"toggleButton\\\"\\n                data-bs-toggle=\\\"dropdown\\\" data-bs-auto-close=\\\"outside\\\" data-bs-display=\\\"static\\\"\\n                click.delegate=\\\"openDropdown()\\\">\\n          ${'components.brand-filter.title' & t}\\n          <span if.bind=\\\"chosenBrands.length > 0\\\" class=\\\"badge rounded-pill badge-outline-primary ms-1\\\">${chosenBrands.length}</span>\\n        </button>\\n\\n        <div class=\\\"dropdown-menu dropdown-menu-end p-2\\\" style=\\\"min-width: 16rem;\\\">\\n          <input class=\\\"form-control form-control-sm mb-2\\\" type=\\\"text\\\"\\n                 placeholder=\\\"${'components.brand-filter.search' & t}\\\"\\n                 value.bind=\\\"brandSearch & debounce:200\\\">\\n\\n          <div if.bind=\\\"possibleBrands === undefined\\\" class=\\\"text-center text-muted py-2\\\">\\n            <span class=\\\"spinner-border spinner-border-sm\\\"></span>\\n          </div>\\n\\n          <div else style=\\\"max-height: 18rem; overflow-y: auto;\\\">\\n            <div if.bind=\\\"filteredBrands.length == 0\\\" class=\\\"text-muted small px-1\\\">\\n              ${'components.brand-filter.empty' & t}\\n            </div>\\n\\n            <div repeat.for=\\\"brand of filteredBrands\\\" class=\\\"form-check\\\">\\n              <input class=\\\"form-check-input\\\" type=\\\"checkbox\\\" id=\\\"brand-check-${uid}-${$index}\\\"\\n                     checked.one-way=\\\"isChosen(brand, chosenBrands)\\\"\\n                     change.delegate=\\\"toggleBrand(brand)\\\">\\n              <label class=\\\"form-check-label\\\" for=\\\"brand-check-${uid}-${$index}\\\">${brand}</label>\\n            </div>\\n          </div>\\n        </div>\\n      </div>\\n    </div>\\n\\n    <!-- Chosen brands are already visible as checked checkboxes in the\\n         dropdown, so only a reset-all control remains here, shown once it\\n         saves work (from two selections up). -->\\n    <div class=\\\"input-group pt-2\\\" id=\\\"chosen-brands\\\">\\n      <a if.bind=\\\"chosenBrands.length > 1\\\" href=\\\"#\\\" class=\\\"link-danger align-middle\\\" click.delegate=\\\"resetChosenBrands()\\\">\\n        <i class=\\\"bi bi-x-lg\\\"></i>\\n      </a>\\n    </div>\\n  </div>\\n</template>\\n\";","// Tyre size facets are stored as text (\"015\", \"02\") so a plain string sort\n// puts 385 before 70. Compare the numeric value and keep the original text.\n\nexport function compareNumericSize(a: unknown, b: unknown): number {\n  const left = String(a);\n  const right = String(b);\n  const leftNumber = Number(left);\n  const rightNumber = Number(right);\n  const leftIsNumber = left.trim() !== \"\" && Number.isFinite(leftNumber);\n  const rightIsNumber = right.trim() !== \"\" && Number.isFinite(rightNumber);\n\n  if (leftIsNumber && rightIsNumber) {\n    if (leftNumber !== rightNumber) {\n      return leftNumber - rightNumber;\n    }\n    return left < right ? -1 : left > right ? 1 : 0;\n  }\n  if (leftIsNumber) {\n    return -1;\n  }\n  if (rightIsNumber) {\n    return 1;\n  }\n  return left < right ? -1 : left > right ? 1 : 0;\n}\n","import { I18N } from 'aurelia-i18n';\nimport { observable } from 'aurelia-framework';\nimport { TKEvent } from 'utils/enums/TKEvent';\nimport { EventAggregator } from 'aurelia-event-aggregator';\nimport { autoinject, bindable } from 'aurelia-framework';\nimport noUiSlider, { PipsMode } from \"nouislider\";\nimport wNumb from 'wnumb';\nimport { TireFilterHelper } from 'utils/helpers/tire-filter-helper';\nimport { compareNumericSize } from './filter-value-order';\n\nconst NUMERIC_SIZE_FILTERS = new Set(['width', 'height', 'diameter']);\n\n@autoinject\nexport class ProductFilterCustomElement {\n  @bindable @observable categoryId: number;\n  @bindable possibleFilters: any;\n  @bindable chosenFilters: any;\n  /** SAL-313: group -> values that would return no in-stock tyre with the other chosen filters. */\n  @bindable disabledFilters: Record<string, string[]> | null = null;\n  /** SAL-313 r2: a Filters request for the newest selection is in flight. */\n  @bindable filtersPending = false;\n  /** SAL-313 r2: the group the user just changed; it stays clickable while pending. */\n  @bindable pendingGroup: string | null = null;\n\n  chosenFiltersCount: number = 0;\n  private sortingFilters = false;\n\n  constructor(\n    private eventAggregator: EventAggregator,\n    private i18n: I18N\n  ) { }\n\n  attached() {\n    this.updateChosenFiltersCount();\n    this.sortPossibleFilters();\n    this.createSliders();\n    this.prefillFilters();\n  }\n\n  categoryIdChanged(newValue: number, oldValue: number) {\n    if (oldValue === undefined)\n      return;\n\n    this.resetChosenFilters();\n  }\n\n  // Runs while the filter property is bound, before the dropdown repeat paints.\n  // attached() is too late: the list has already rendered in arrival order.\n  possibleFiltersChanged() {\n    this.sortPossibleFilters();\n  }\n\n  sortPossibleFilters() {\n    if (!this.possibleFilters || this.sortingFilters) {\n      return;\n    }\n\n    const sortedPossibleFilters: any = {};\n    let changed = false;\n\n    for (const key of Object.keys(this.possibleFilters)) {\n      const values = this.possibleFilters[key];\n      if (!Array.isArray(values)) {\n        sortedPossibleFilters[key] = values;\n        continue;\n      }\n\n      const sorted = NUMERIC_SIZE_FILTERS.has(key)\n        ? values.slice().sort(compareNumericSize)\n        : this.areAllNumbers(values)\n          ? values.slice().sort((a: number, b: number) => Number(a) - Number(b))\n          : values.slice().sort();\n      sortedPossibleFilters[key] = sorted;\n      if (sorted.length !== values.length || sorted.some((value, index) => value !== values[index])) {\n        changed = true;\n      }\n    }\n\n    if (!changed) {\n      return;\n    }\n\n    this.sortingFilters = true;\n    this.possibleFilters = sortedPossibleFilters;\n    this.sortingFilters = false;\n  }\n\n  areAllNumbers(array: []) {\n    return array.every((value: any) => !isNaN(value));\n  }\n\n  /**\n   * SAL-270 reopen / SAL-313: category 10 sizes are always checkboxes, never the range slider.\n   */\n  shouldUseSlider(key: string): boolean {\n    // SAL-313: tyres never use the slider, so every size value can be greyed out.\n    if (Number(this.categoryId) === 10) {\n      return false;\n    }\n    const values = this.possibleFilters?.[key];\n    return Array.isArray(values) && values.length > 25 && this.areAllNumbers(values);\n  }\n\n\n  createSliders() {\n    const containers = document.querySelectorAll('.slider');\n    containers.forEach(container => {\n      const key = container.getAttribute('data-key')!;\n      const filterValues = this.possibleFilters[key];\n\n      const min = Math.min(...filterValues);\n      const max = Math.max(...filterValues);\n\n      this.createSlider(container, min, max);\n    });\n  }\n\n  createSlider(slider: any, min: number, max: number) {\n    noUiSlider.create(slider, {\n      start: [min, max],\n      range: { min, max },\n      connect: true,\n      tooltips: true,\n      direction: 'rtl',\n      orientation: 'vertical',\n      format: wNumb({ decimals: 0 }),\n      step: 1,\n      pips: {\n        mode: PipsMode.Positions as any,\n        values: [0, 25, 50, 75, 100],\n        stepped: true,\n        density: 5\n      }\n    }).on('change', () => {\n      this.chooseFilter(slider);\n    });\n  }\n\n  prefillFilters() {\n    if (this.possibleFilters === undefined || this.chosenFilters === undefined)\n      return;\n\n    this.clearFilterBadges();\n\n    Object.entries(this.chosenFilters).forEach(([key, values]: [string, string[]]) => this.prefillFilter(key, values));\n  }\n\n  prefillFilter(key: string, values: string[]) {\n    let temporaryPossibleFilters = this.possibleFilters;\n    this.possibleFilters = {}; // Clear previous filters\n    this.possibleFilters = temporaryPossibleFilters;\n\n    const sliders = document.querySelectorAll(`.slider[data-key=\"${key}\"]`);\n\n    if (sliders.length > 0)\n      this.prefillSliders(sliders.item(0), key, values);\n    else\n      this.addFilterBadge(key, (values as []).join(\", \"));\n  }\n\n  prefillSliders(target: Element, key: string, values: string[]) {\n    const slider = (target as any).noUiSlider;\n\n    const chosenMin = Math.min(...values as []);\n    const chosenMax = Math.max(...values as []);\n\n    const range = slider.options.range;\n    if (chosenMin != range.min || chosenMax != range.max)\n      this.addFilterBadge(key, `${chosenMin}...${chosenMax}`);\n\n    slider.set([chosenMin, chosenMax]);\n  }\n\n  isFilterValueChosen(key: string, value: any) {\n    if (!this.chosenFilters || !this.chosenFilters[key])\n      return false;\n\n    return (this.chosenFilters[key] as []).some((chosenValue) => this.areFilterValuesEqual(chosenValue, value));\n  }\n\n  /** SAL-313: disabledFilters is passed in so the binding re-runs when it is replaced. */\n  isFilterValueDisabled(key: string, value: any, disabledFilters: Record<string, string[]> | null): boolean {\n    return TireFilterHelper.isOptionDisabled(disabledFilters, this.chosenFilters, key, value);\n  }\n\n  /** SAL-313 r2: dimmed and not clickable while the newest Filters request is in flight. */\n  isFilterValueLocked(key: string, value: any, pending: boolean, pendingGroup: string | null): boolean {\n    return TireFilterHelper.isOptionLocked(pending, pendingGroup, this.chosenFilters, key, value);\n  }\n\n  areFilterValuesEqual(firstValue: any, secondValue: any) {\n    return `${firstValue}` === `${secondValue}`;\n  }\n\n  addFilterBadge(key: string, text: string) {\n    const filterBadge = this.getElementByKey(key);\n    const keyName = TireFilterHelper.translateKey(this.categoryId, key, this.i18n);\n    const displayText = this.translateBadgeValues(key, text);\n\n    filterBadge.innerText = `${keyName}: ${displayText}`;\n    filterBadge.style.display = \"block\";\n  }\n\n  translateBadgeValues(key: string, text: string): string {\n    if (Number(this.categoryId) !== 10) return text;\n    if (text.includes('...')) return text;\n    return text\n      .split(',')\n      .map(part => TireFilterHelper.translateValue(this.categoryId, key, part.trim(), this.i18n))\n      .join(', ');\n  }\n\n  filterValueLabel(key: string, value: string): string {\n    if (Number(this.categoryId) !== 10) return value;\n    return TireFilterHelper.translateValue(this.categoryId, key, String(value), this.i18n);\n  }\n\n  filterEntries(key: string): { value: string; nested: boolean }[] {\n    const values = this.possibleFilters?.[key] ?? [];\n    if (Number(this.categoryId) === 10 && key === 'season') {\n      return TireFilterHelper.seasonEntries(values);\n    }\n    return values.map((value: string) => ({ value: String(value), nested: false }));\n  }\n\n  clearFilterBadges() {\n    const element = document.getElementById(\"chosen-filters\");\n    if (!element) return;\n\n    for (let i = 0; i < element.children.length; i++) {\n      let child = element.children[i];\n      if (child.nodeName == \"SPAN\")\n        this.clearElement(child as HTMLSpanElement);\n    }\n  }\n\n  clearFilterBadge(key: string) {\n    const element = this.getElementByKey(key);\n    this.clearElement(element);\n  }\n\n  clearElement(element: HTMLElement) {\n    if (!element) return;\n    element.style.display = \"none\";\n    element.innerHTML = \"\";\n  }\n\n  chooseFilter(target: HTMLElement) {\n    let values: string[] = [];\n    let key = target.getAttribute('data-key')!;\n\n    if (target instanceof HTMLInputElement && Number(this.categoryId) === 10 && key === 'season') {\n      this.applySeasonFamily(target);\n    }\n\n    this.clearFilterBadge(key);\n\n    if (target.classList.contains(\"slider\")) {\n      values = this.getSliderFilterValues(target, key);\n    } else {\n      values = this.getCheckboxFilterValues(key);\n    }\n\n    this.updateChosenFilters(values, key);\n  }\n\n  getSliderFilterValues(target: HTMLElement, key: string): string[] {\n    const values: string[] = [];\n\n    const chosenValues = (target as any).noUiSlider.get(true);\n    const chosenMin = parseInt(chosenValues[0]);\n    const chosenMax = parseInt(chosenValues[1]);\n\n    const range = (target as any).noUiSlider.options.range;\n    if (chosenMin == range.min && chosenMax == range.max)\n      return values;\n\n    this.addFilterBadge(key, `${chosenMin}...${chosenMax}`);\n\n    for (let value of this.possibleFilters[key]) {\n      value = Number(value);\n\n      if (value >= chosenMin && value <= chosenMax)\n        values.push(value);\n    }\n\n    return values;\n  }\n\n  /** Keep the Talv checkbox and its children in step before the checked boxes are read. */\n  applySeasonFamily(target: HTMLInputElement) {\n    const clicked = target.getAttribute('data-value') || '';\n    const boxes = Array.from(document.querySelectorAll<HTMLInputElement>('input[data-key=\"season\"]'));\n    const available = boxes.map(box => box.getAttribute('data-value') || '');\n    const selected = boxes.filter(box => box.checked).map(box => box.getAttribute('data-value') || '');\n    const next = new Set(TireFilterHelper.seasonChoice(selected, clicked, target.checked, available));\n    boxes.forEach(box => {\n      box.checked = next.has(box.getAttribute('data-value') || '');\n    });\n  }\n\n  getCheckboxFilterValues(key: string): string[] {\n    let values: string[] = [];\n    let checkedBoxes: NodeListOf<Element> = document.querySelectorAll(`input[data-key=\"${key}\"]:checked`);\n\n    if (checkedBoxes.length == 0)\n      return [];\n\n    checkedBoxes.forEach((element: HTMLInputElement) => values.push(element.getAttribute(\"data-value\")!));\n    this.addFilterBadge(key, (values as []).join(\", \"));\n\n    return values;\n  }\n\n  updateChosenFilters(values: string[], key: string) {\n    if (this.chosenFilters == undefined)\n      this.chosenFilters = {};\n\n    if (values.length == 0)\n      delete this.chosenFilters[key];\n    else\n      this.chosenFilters[key] = values;\n\n    this.updateChosenFiltersCount();\n    this.publishChosenFiltersChanged();\n  }\n\n  getElementByKey(key: string) {\n    return document.querySelectorAll(`#chosen-filters span[data-key=\"${key}\"]`)[0] as HTMLSpanElement;\n  }\n\n  resetChosenFilters() {\n    this.chosenFilters = {};\n    this.clearFilterBadges();\n    // SAL-296: Clear must uncheck the boxes, not only hide the chip. The one-way\n    // checked binding does not re-sync from chosenFilters on this click.\n    document.querySelectorAll('#product-filter input[type=\"checkbox\"]').forEach(box => {\n      (box as HTMLInputElement).checked = false;\n    });\n    this.removeSliders();\n    this.publishChosenFiltersChanged();\n    this.attached();\n  }\n\n  removeSliders() {\n    const sliders = document.getElementsByClassName(\"slider\");\n    for (var i = 0; i < sliders.length; i++)\n      (sliders.item(i) as any).noUiSlider.destroy();\n  }\n\n  publishChosenFiltersChanged() {\n    this.eventAggregator.publish(TKEvent.chosenFiltersChanged, {\n      categoryId: this.categoryId,\n      chosenFilters: this.chosenFilters\n    });\n  }\n\n  updateChosenFiltersCount() {\n    this.chosenFiltersCount = Object.values(this.chosenFilters ?? {})\n      .reduce((sum: number, values: any) => sum + (values as []).length, 0);\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"nouislider/dist/nouislider.css\\\"></require>\\n  <require from=\\\"/node_modules/bootstrap-icons/font/bootstrap-icons.css\\\"></require>\\n\\n  <div class=\\\"pt-1 pb-3 w-100\\\">\\n    <div class=\\\"input-group mx-auto\\\" id=\\\"product-filter\\\">\\n      <span class=\\\"input-group-text\\\">${'pages.category.filters.header' & t}</span>\\n\\n      <span class=\\\"input-group-text form-control\\\"></span>\\n\\n      <div repeat.for=\\\"key of possibleFilters | objectKeys\\\" class=\\\"dropdown\\\">\\n        <button class=\\\"btn btn-outline-primary dropdown-toggle\\\" type=\\\"button\\\" data-bs-toggle=\\\"dropdown\\\">\\n          ${('pages.category.filters.' + categoryId + '.' + key) & t}\\n        </button>\\n\\n        <ul class=\\\"dropdown-menu\\\">\\n          <let outer-index=\\\"${$index}\\\"></let>\\n          <li if.bind=\\\"shouldUseSlider(key)\\\">\\n            <div type=\\\"input\\\" class=\\\"slider mx-auto mx-1 my-4\\\" change.delegate=\\\"chooseFilter($event.target)\\\"\\n              data-key=\\\"${key}\\\"></div>\\n          </li>\\n          <!-- The chosen value rides on data-value, not value. A bound \\\"value\\\" gives\\n               Aurelia's CheckedObserver a value observer to subscribe to, and that\\n               subscription re-synchronises \\\"checked\\\" from the (still unchanged) model\\n               on the element's own change event - before the delegated chooseFilter\\n               handler runs, so it would always read zero checked boxes. -->\\n          <!-- SAL-313: while the newest Filters request is in flight (r2), unchosen values of the\\n               other groups are dimmed and disabled until the response or an error lands.\\n               SAL-313: a value that would return no in-stock tyre with the other chosen\\n               filters is greyed out and disabled, not hidden. Chosen values stay enabled. -->\\n          <li else repeat.for=\\\"entry of filterEntries(key)\\\"\\n            class=\\\"${entry.nested ? 'dropdown-item ps-4' : 'dropdown-item'} ${isFilterValueDisabled(key, entry.value, disabledFilters) ? 'disabled text-muted' : ''} ${isFilterValueLocked(key, entry.value, filtersPending, pendingGroup) ? 'disabled opacity-50' : ''}\\\"\\n            aria-disabled.bind=\\\"isFilterValueDisabled(key, entry.value, disabledFilters) || isFilterValueLocked(key, entry.value, filtersPending, pendingGroup)\\\"\\n            aria-busy.bind=\\\"filtersPending\\\">\\n            <input class=\\\"form-check-input\\\" change.delegate=\\\"chooseFilter($event.target)\\\" type=\\\"checkbox\\\"\\n              id=\\\"value-${outerIndex}-${$index}\\\" data-key=\\\"${key}\\\" data-value=\\\"${entry.value}\\\"\\n              disabled.bind=\\\"isFilterValueDisabled(key, entry.value, disabledFilters) || isFilterValueLocked(key, entry.value, filtersPending, pendingGroup)\\\"\\n              checked.one-way=\\\"isFilterValueChosen(key, entry.value)\\\">${filterValueLabel(key, entry.value)}\\n          </li>\\n        </ul>\\n      </div>\\n    </div>\\n\\n    <div class=\\\"input-group pt-2\\\" id=\\\"chosen-filters\\\">\\n      <a if.bind=\\\"chosenFiltersCount > 0\\\" href=\\\"#\\\" class=\\\"link-danger\\\" click.delegate=\\\"resetChosenFilters()\\\">\\n        <i class=\\\"bi bi-x-lg\\\"></i>\\n      </a>\\n      <span repeat.for=\\\"key of possibleFilters | objectKeys\\\" class=\\\"badge rounded-pill badge-outline-primary ms-1\\\"\\n        style=\\\"display: none\\\" data-key.bind=\\\"key\\\"></span>\\n    </div>\\n  </div>\\n\\n</template>\";","import { autoinject, LogManager, bindable } from \"aurelia-framework\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { CartProductService } from \"services/cart/cart-product-service\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { AppConfig } from \"app-config\";\nimport { ICartProduct } from \"domain/Cart/ICartProduct\";\nimport { IStockItem } from \"domain/Product/IStockItem\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\nimport { CurrencyFormatValueConverter } from \"utils/classes/value-converters\";\nimport { Modal } from \"bootstrap\";\nimport { AddToCartGate } from \"utils/helpers/toast-helper\";\n\nexport const log = LogManager.getLogger(\"app.components.add-to-cart\");\n\ntype CartProductCandidate = IProduct & Partial<ICartProduct>;\n\n// SAL-319: every rendered row gets its own sequence number, so two rows with the same code\n// (e.g. an RVS product and a partner row) never share a button or modal id.\nlet rowSequence = 0;\n\n@autoinject\nexport class AddToCartCustomElement {\n  @bindable product: CartProductCandidate;\n  productCode: string;\n  readonly rowUid = ++rowSequence;\n  // SAL-319: component-scoped refs; never look the modal up by a (possibly shared) DOM id.\n  confirmModalEl?: HTMLElement;\n  addToCartButtonEl?: HTMLButtonElement;\n  addToCartWarnButtonEl?: HTMLButtonElement;\n  private currencyFormat = new CurrencyFormatValueConverter();\n\n  /** SAL-283 QA: Lisa opened the confirm modal and only its OK may add; one add at a time. */\n  private gate = new AddToCartGate();\n\n  constructor(\n    private element: Element,\n    private cartProductService: CartProductService,\n    private eventAggregator: EventAggregator,\n    private appConfig: AppConfig,\n    private i18n: I18N,\n  ) {}\n\n  getUniqueProductId(product: CartProductCandidate) {\n    const source = product.id ?? product.foundBy ?? \"x\";\n    return `${product.code}-${source}-${this.rowUid}`;\n  }\n\n  tryAddToCart(product: CartProductCandidate) {\n    if (!this.ensureValidMinimumQuantity(product)) return;\n\n    if (this.gate.busy) return;\n\n    if (this.cartWarningNeeded(product)) {\n      // SAL-319: this component's own modal (ref), never one looked up by a shared id.\n      // SAL-283 QA: only the OK of the modal opened by this Lisa click may add.\n      if (this.confirmModalEl && this.gate.requestConfirm()) Modal.getOrCreateInstance(this.confirmModalEl).show();\n      return;\n    }\n\n    this.addToCart(product);\n  }\n\n  /** OK in this component's confirm modal: adds once for the Lisa click that opened it. */\n  confirmAddToCart(product: CartProductCandidate) {\n    if (!this.gate.takeConfirm()) return;\n    this.addToCart(product);\n  }\n\n  /** Modal closed without OK: the pending Lisa click is dropped. */\n  cancelConfirm() {\n    this.gate.cancelConfirm();\n  }\n\n  addToCart(product: CartProductCandidate) {\n    if (this.gate.busy) return;\n    if (!this.ensureValidMinimumQuantity(product)) return;\n    const quantity = parseInt(product.toCartQuantity ?? \"1\", 10);\n\n    const buttons = [this.addToCartButtonEl, this.addToCartWarnButtonEl].filter(\n      (b): b is HTMLButtonElement => !!b,\n    );\n    if (!this.gate.begin()) return;\n    buttons.forEach(b => (b.disabled = true));\n\n    this.cartProductService\n      .post(this.getRequestData(product, quantity))\n      .then(() => {\n        Utils.showSuccessToast(this.i18n.tr(\"components.products.messages.added-to-cart\"));\n\n        this.eventAggregator.publish(TKEvent.cartProductsChanged);\n      })\n      .catch(() => {\n        Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.add-to-cart\"));\n      })\n      .finally(() => {\n        this.gate.end();\n        buttons.forEach(b => (b.disabled = false));\n      });\n  }\n\n  getMinimumQuantity(product: CartProductCandidate): number {\n    return ProductExtraHelper.getMinimumQuantity(product.selectedStock);\n  }\n\n  showsMinimumQuantityHint(product: CartProductCandidate): boolean {\n    return this.getMinimumQuantity(product) > 1;\n  }\n\n  private ensureValidMinimumQuantity(product: CartProductCandidate): boolean {\n    const quantity = parseInt(product.toCartQuantity ?? \"\", 10);\n    if (ProductExtraHelper.isValidMinimumQuantity(quantity, product.selectedStock)) return true;\n\n    product.toCartQuantity = this.getMinimumQuantity(product).toString();\n    Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.minimum-quantity\"));\n    return false;\n  }\n\n  getRequestData(product: CartProductCandidate, quantity: number): any {\n    const data = {\n      id: product.id,\n      foundBy: product.foundBy,\n      code: product.code,\n      quantity,\n      warehouseId: product.selectedStock?.warehouse?.id ?? product.warehouseId ?? 0,\n    } as any;\n\n    if (this.isExternalWarehouse(product.selectedStock?.warehouse) || product.externalWarehouseId) {\n      data.warehouseId = 0;\n      data.externalWarehouseId = product.selectedStock?.warehouse?.id ?? product.externalWarehouseId;\n    }\n\n    return data;\n  }\n\n  private otherWarehouseWarningNeeded(warehouse: IWarehouse | undefined) {\n    if (!warehouse) return false;\n    if (this.isExternalWarehouse(warehouse)) return true;\n\n    return this.otherWarehouseIdWarningNeeded(warehouse.id);\n  }\n\n  private isExternalWarehouse(warehouse: IWarehouse | undefined) {\n    const isExternal = warehouse?.isExternal as unknown;\n    return (\n      isExternal === true ||\n      isExternal === \"true\" ||\n      isExternal === 1 ||\n      isExternal === \"1\"\n    );\n  }\n\n  private otherWarehouseIdWarningNeeded(warehouseId: number) {\n    const userWarehouseId = this.appConfig.userSettings.warehouseId;\n    const isCentralWarehouse = warehouseId === 1;\n    const isMustamaeWarehouse = warehouseId === 3;\n    const isTartuWarehouse = warehouseId === 21;\n    // SAL-296: Rehviladu always shows the +2 / 16:30 note.\n    if (warehouseId === 40) return true;\n\n    return (\n      warehouseId !== userWarehouseId &&\n      !isCentralWarehouse &&\n      !isMustamaeWarehouse &&\n      !isTartuWarehouse\n    );\n  }\n\n  cartWarningNeeded(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    return (\n      this.hasStockWarning(\n        product,\n        selectedStock,\n        warehouseId,\n        externalWarehouseId,\n        externalWarehouseGroupId,\n      ) || this.hasRefundableDeposit(product, selectedStock)\n    );\n  }\n\n  hasStockWarning(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    if (selectedStock?.warehouse) {\n      return this.otherWarehouseWarningNeeded(selectedStock.warehouse);\n    }\n\n    if (externalWarehouseId != null || externalWarehouseGroupId != null) {\n      return true;\n    }\n\n    return warehouseId == null ? false : this.otherWarehouseIdWarningNeeded(warehouseId);\n  }\n\n  hasExternalStockWarning(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    if (\n      !this.hasStockWarning(\n        product,\n        selectedStock,\n        product.warehouseId,\n        externalWarehouseId,\n        externalWarehouseGroupId,\n      )\n    ) {\n      return false;\n    }\n\n    if (selectedStock?.warehouse) return this.isExternalWarehouse(selectedStock.warehouse);\n\n    return externalWarehouseId != null || externalWarehouseGroupId != null;\n  }\n\n  hasRefundableDeposit(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    return ProductExtraHelper.hasRefundableDeposit(\n      ProductExtraHelper.getSelectedRefundableDepositSource(product, selectedStock),\n    );\n  }\n\n  getRefundableDeposit(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    return ProductExtraHelper.getRefundableDeposit(\n      ProductExtraHelper.getSelectedRefundableDepositSource(product, selectedStock),\n    );\n  }\n\n  getRefundableDepositLabel(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    const refundableDeposit = this.getRefundableDeposit(product, selectedStock);\n    return refundableDeposit == null ? \"\" : this.currencyFormat.toView(refundableDeposit);\n  }\n\n  getRefundableDepositWarningText(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    const refundableDeposit = this.getRefundableDeposit(product, selectedStock);\n    const lines = [this.i18n.tr(\"components.products.tooltips.casing.order-delay\")];\n\n    if (refundableDeposit != null) {\n      lines.push(\n        this.i18n.tr(\"components.products.tooltips.casing.price-line\", {\n          price: this.getRefundableDepositLabel(product, selectedStock),\n        }),\n      );\n    } else {\n      lines.push(this.i18n.tr(\"components.products.tooltips.casing.included-without-price\"));\n    }\n\n    return lines.join(\"<br>\");\n  }\n\n  getStockWarningText(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    if (\n      this.hasExternalStockWarning(\n        product,\n        selectedStock,\n        externalWarehouseId,\n        externalWarehouseGroupId,\n      )\n    ) {\n      const groupId = this.getExternalWarningGroupId(\n        product,\n        selectedStock,\n        externalWarehouseGroupId,\n      );\n\n      return this.i18n.tr(`components.products.tooltips.other-stock-warning.external.${groupId}`);\n    }\n\n    const stockWarehouseId = this.getWarehouseWarningId(product, selectedStock, warehouseId);\n    return this.i18n.tr(\n      `components.products.tooltips.other-stock-warning.warehouses.${stockWarehouseId}`,\n    );\n  }\n\n  getExternalWarningGroupId(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    return selectedStock?.warehouse?.groupId || externalWarehouseGroupId || 2;\n  }\n\n  getWarehouseWarningId(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n  ) {\n    return selectedStock?.warehouse?.id || warehouseId;\n  }\n}\n","module.exports = \"<template>\\n  <div>\\n    <div class=\\\"input-group mx-auto add-to-cart-form\\\">\\n    <input\\n      type=\\\"number\\\"\\n      class=\\\"form-control form-control-sm\\\"\\n      min.bind=\\\"getMinimumQuantity(product)\\\"\\n      step.bind=\\\"getMinimumQuantity(product)\\\"\\n      value.bind=\\\"product.toCartQuantity\\\" />\\n    <div class=\\\"input-group-append\\\">\\n      <button\\n        id=\\\"addToCart-${getUniqueProductId(product)}-warn\\\"\\n        ref=\\\"addToCartWarnButtonEl\\\"\\n        type=\\\"button\\\"\\n        class=\\\"btn btn-success btn-sm clickable-important\\\"\\n        if.bind=\\\"cartWarningNeeded(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"\\n        click.trigger=\\\"tryAddToCart(product)\\\">\\n        ${'components.products.buttons.add-to-cart' & t}\\n      </button>\\n      <button\\n        id=\\\"addToCart-${getUniqueProductId(product)}\\\"\\n        ref=\\\"addToCartButtonEl\\\"\\n        type=\\\"button\\\"\\n        class=\\\"btn btn-success btn-sm clickable-important\\\"\\n        click.trigger=\\\"tryAddToCart(product)\\\"\\n        else>\\n        ${'components.products.buttons.add-to-cart' & t}\\n      </button>\\n    </div>\\n    </div>\\n    <div\\n      if.bind=\\\"showsMinimumQuantityHint(product)\\\"\\n      class=\\\"text-muted small text-center mt-1 minimum-quantity-hint\\\">\\n      ${'components.products.fields.minimum-quantity-hint' & t: {'quantity': getMinimumQuantity(product)}}\\n    </div>\\n  </div>\\n\\n  <div\\n    class=\\\"modal fade text-wrap\\\"\\n    id=\\\"confirmModal-${getUniqueProductId(product)}\\\"\\n    ref=\\\"confirmModalEl\\\"\\n    hidden.bs.modal.trigger=\\\"cancelConfirm()\\\"\\n    tabindex=\\\"-1\\\"\\n    aria-hidden=\\\"true\\\">\\n    <div class=\\\"modal-dialog modal-dialog-centered\\\">\\n      <div class=\\\"modal-content\\\">\\n        <div class=\\\"modal-header d-flex text-center\\\">\\n          <h5\\n            if.bind=\\\"hasStockWarning(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"\\n            class=\\\"modal-title inline\\\"\\n            innerhtml.bind=\\\"i18n.tr('components.products.tooltips.other-stock-warning.general')\\\"></h5>\\n          <h5\\n            else\\n            class=\\\"modal-title inline\\\">\\n            ${'components.products.tooltips.info-modal.product-info' & t}\\n          </h5>\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn-close clickable-important mt-0 mb-auto\\\"\\n            data-bs-dismiss=\\\"modal\\\"\\n            aria-label=\\\"Close\\\"></button>\\n        </div>\\n        <div class=\\\"modal-body text-center\\\">\\n          <div\\n            if.bind=\\\"hasStockWarning(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"\\n            class=\\\"product-info-modal-section\\\">\\n            <h6 class=\\\"product-info-modal-heading\\\">\\n              ${'components.products.tooltips.info-modal.stock-selection' & t}\\n            </h6>\\n            <p\\n              class=\\\"product-info-modal-warning-text\\\"\\n              innerhtml.bind=\\\"getStockWarningText(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"></p>\\n          </div>\\n          <div if.bind=\\\"hasRefundableDeposit(product, product.selectedStock)\\\" class=\\\"product-info-modal-section\\\">\\n            <h6 class=\\\"product-info-modal-heading\\\">\\n              ${'components.products.tooltips.info-modal.additional-component' & t}\\n            </h6>\\n            <p\\n              class=\\\"product-info-modal-warning-text\\\"\\n              innerhtml.bind=\\\"getRefundableDepositWarningText(product, product.selectedStock)\\\"></p>\\n          </div>\\n        </div>\\n        <div class=\\\"modal-footer d-flex align-items-center\\\">\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-secondary clickable-important\\\"\\n            data-bs-dismiss=\\\"modal\\\">\\n            ${'components.report-modal.close-button' & t}\\n          </button>\\n          <button\\n            id=\\\"addToCartConfirm-${getUniqueProductId(product)}\\\"\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-primary clickable-important\\\"\\n            click.trigger=\\\"confirmAddToCart(product)\\\"\\n            data-bs-dismiss=\\\"modal\\\">\\n            OK\\n          </button>\\n        </div>\\n      </div>\\n    </div>\\n  </div>\\n</template>\\n\";","import { autoinject, bindable } from 'aurelia-framework';\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\n\n@autoinject\nexport class CopyToClipboardCustomElement {\n  @bindable text: string;\n\n  constructor(\n    private i18n: I18N\n  ) {}\n  \n  copyToClipboard() {\n    navigator.clipboard.writeText(this.text)\n    Utils.showSuccessToast(this.i18n.tr('components.products.messages.code-copied-to-clipboard'));\n  }\n}\n","module.exports = \"<template>\\n\\n  <a class=\\\"icon-link icon-link-hover text-reset\\\" click.trigger=\\\"copyToClipboard()\\\">\\n    <i class=\\\"bi bi-copy clickable-important\\\"></i>\\n  </a>\\n\\n</template>\\n\";","import { encodeSearchRouteQuery } from \"utils/helpers/search-route\";\nimport { SearchType } from 'utils/enums/SearchType';\nimport { IParentItem } from 'domain/Base/IParentItem';\nimport { Router } from 'aurelia-router';\nimport { AppConfig } from 'app-config';\nimport { autoinject, observable, LogManager, bindable, BindingEngine } from 'aurelia-framework';\nimport { IProduct } from 'domain/Product/IProduct';\nimport { Utils } from 'utils/helpers/utils';\nimport { TireFilterHelper } from 'utils/helpers/tire-filter-helper';\nimport { I18N } from 'aurelia-i18n';\n\nexport const log = LogManager.getLogger('app.components.extra-row');\n\ninterface IOeTreeItem extends IParentItem {\n  query?: string;\n}\n\n@autoinject\nexport class ExtraRowCustomElement {\n  @bindable @observable product: IProduct;\n  oeNumberTree: IOeTreeItem[] = [];\n  private oeNumbersSubscription: { dispose(): void } | null = null;\n\n  attached() {\n    this.subscribeToOeNumbers();\n    this.buildOeNumberTree();\n  }\n\n  detached() {\n    this.disposeOeNumbersSubscription();\n  }\n\n  productChanged() {\n    this.subscribeToOeNumbers();\n    this.buildOeNumberTree();\n  }\n\n  private subscribeToOeNumbers() {\n    this.disposeOeNumbersSubscription();\n\n    if (!this.product) {\n      return;\n    }\n\n    this.oeNumbersSubscription = this.bindingEngine\n      .propertyObserver(this.product, 'oeNumbers')\n      .subscribe(() => this.buildOeNumberTree());\n  }\n\n  private disposeOeNumbersSubscription() {\n    this.oeNumbersSubscription?.dispose();\n    this.oeNumbersSubscription = null;\n  }\n\n  private buildOeNumberTree() {\n    this.oeNumberTree = (this.product?.oeNumbers ?? []).map(([manufacturer, oeNumbers], manufacturerIndex) => ({\n      id: manufacturerIndex,\n      name: manufacturer,\n      children: oeNumbers.map((oeNumber, oeNumberIndex) => ({\n        id: manufacturerIndex * 1000 + oeNumberIndex,\n        name: oeNumber,\n        query: oeNumber,\n        children: []\n      }))\n    }));\n  }\n\n  constructor(\n    private appConfig: AppConfig,\n    private router: Router,\n    private bindingEngine: BindingEngine,\n    private i18n: I18N,\n  ) { }\n\n  infoLabel(info: [string, string]): string {\n    return TireFilterHelper.translateInfoPair(info, this.i18n)[0];\n  }\n\n  infoValue(info: [string, string]): string {\n    return TireFilterHelper.translateInfoPair(info, this.i18n)[1];\n  }\n\n  infoHref(info: [string, string]): string | null {\n    return TireFilterHelper.infoHref(info);\n  }\n\n  openDocument(productId: number, document: [string, string], index: number) {\n    const data = document[1];\n    let win: Window | null;\n\n    if (data && data.toLowerCase().startsWith(\"http\")) {\n      win = window.open(data, \"_blank\");\n    } else {\n      win = window.open(`${this.appConfig.apiUrl}/Product/${productId}/Document/${index}`, \"_blank\");\n    }\n\n    if (win != null)\n      win.focus();\n  }\n\n  showGallery(product: IProduct) {\n    Utils.showGallery(product);\n  }\n\n  loadVehicle(item: IParentItem) {\n    this.router.navigateToRoute('catalogueList', { vehicleId: item.id });\n  }\n\n  searchOeNumber(query: string) {\n    this.router.navigateToRoute('searchResult', {\n      query: encodeSearchRouteQuery(query),\n      page: 1,\n      type: SearchType.TecDoc\n    });\n  }\n\n  searchOeTreeItem(item: IOeTreeItem) {\n    if (item.query) {\n      this.searchOeNumber(item.query);\n    }\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"components/general/simple-tree\\\"></require>\\n  <require from=\\\"components/product/product-list/stock\\\"></require>\\n  <require from=\\\"components/product/product-list/price\\\"></require>\\n  <require from=\\\"resources/style.css\\\"></require>\\n\\n  <div class=\\\"collapse\\\" data-bs-parent=\\\"#accordion\\\" data-extra.bind=\\\"product.id\\\">\\n    <p if.bind=\\\"!!product.description\\\" class=\\\"row p-2\\\" innerhtml.bind=\\\"product.description\\\"></p>\\n    <div class=\\\"row p-2\\\">\\n      <div class=\\\"col\\\">\\n        <div\\n          if.bind=\\\"!appConfig.userSettings.imagesInProductPage && product.thumbnail\\\"\\n          class=\\\"col product-image-wrapper\\\"\\n          click.trigger=\\\"showGallery(product)\\\"\\n          data-image.bind=\\\"product.id\\\">\\n          <span>\\n            <img class=\\\"mx-auto product-image\\\" src.bind=\\\"product.thumbnail\\\" loading=\\\"lazy\\\" />\\n          </span>\\n        </div>\\n\\n        <div>\\n          <span\\n            if.bind=\\\"!appConfig.userSettings.detailsInProductPage\\\"\\n            repeat.for=\\\"info of product.info\\\"\\n            class=\\\"text-muted small mx-1\\\">\\n            <a if.bind=\\\"infoHref(info)\\\" href.bind=\\\"infoHref(info)\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">${infoLabel(info)}</a>\\n            <template else><b>${infoLabel(info)}</b>: ${infoValue(info)}</template><br />\\n          </span>\\n          <span if.bind=\\\"product.ean\\\" class=\\\"text-muted small mx-1 d-lg-none\\\">\\n            ${'components.products.headers.ean' & t}:\\n            <b>${product.ean}</b> </span\\n          ><br />\\n          <span if.bind=\\\"product.inPackage\\\" class=\\\"text-muted small mx-1 d-lg-none\\\">\\n            ${'components.products.headers.in-package' & t}:\\n            <b>${product.inPackage}</b>\\n          </span>\\n        </div>\\n        <span\\n          if.bind=\\\"!appConfig.userSettings.detailsInProductPage && !appConfig.userSettings.imagesInProductPage\\\"\\n          class=\\\"text-muted small\\\"\\n          data-extra-not-found.bind=\\\"product.id\\\"></span>\\n\\n        <dl if.bind=\\\"product.documents !== undefined && product.documents.length != 0\\\" class=\\\"row\\\">\\n          <dt repeat.for=\\\"document of product.documents\\\" class=\\\"col-12\\\">\\n            <a click.delegate=\\\"openDocument(product.id, document, $index)\\\" href=\\\"\\\">\\n              ${document[0]}\\n            </a>\\n          </dt>\\n        </dl>\\n      </div>\\n\\n      <div class=\\\"col\\\" if.bind=\\\"product.oeNumbers !== undefined && product.oeNumbers.length != 0\\\">\\n        <strong class=\\\"d-block mb-2\\\">${'components.products.headers.oe-numbers' & t}</strong>\\n        <simple-tree\\n          list.bind=\\\"oeNumberTree\\\"\\n          depth.bind=\\\"0\\\"\\n          click-function.call=\\\"searchOeTreeItem(item)\\\">\\n        </simple-tree>\\n      </div>\\n\\n      <div class=\\\"col\\\">\\n        <!-- Loading state -->\\n        <template if.bind=\\\"product.cars === undefined\\\">\\n          <strong class=\\\"d-block mb-2\\\">${'components.products.headers.fits-cars' & t}</strong>\\n          <div class=\\\"text-muted\\\">\\n            <span class=\\\"spinner-border spinner-border-sm me-2\\\" role=\\\"status\\\"></span>\\n          </div>\\n        </template>\\n        <!-- Loaded state with cars -->\\n        <template if.bind=\\\"product.cars !== undefined && product.cars.length != 0\\\">\\n          <strong class=\\\"d-block mb-2\\\">${'components.products.headers.fits-cars' & t}</strong>\\n          <simple-tree\\n            list.bind=\\\"product.cars\\\"\\n            depth.bind=\\\"0\\\"\\n            click-function.call=\\\"loadVehicle(item)\\\">\\n          </simple-tree>\\n        </template>\\n      </div>\\n    </div>\\n  </div>\\n</template>\\n\";","import { IProduct } from 'domain/Product/IProduct';\nimport { observable } from 'aurelia-framework';\nimport { LogManager } from 'aurelia-framework';\nimport { bindable } from 'aurelia-framework';\n\nexport var log = LogManager.getLogger('app.components.gallery');\n\nexport class GalleryCustomElement {\n  @bindable @observable products: IProduct[];\n}\n","module.exports = \"<template>\\n\\n  <div repeat.for=\\\"product of products\\\" class=\\\"modal fade\\\" data-gallery-wrapper.bind=\\\"product.id\\\"\\n       tabindex=\\\"-1\\\">\\n    <div class=\\\"modal-dialog modal-lg\\\">\\n      <div class=\\\"modal-content\\\">\\n        <div data-gallery=\\\"${product.id}\\\" class=\\\"carousel slide\\\" data-bs-interval=\\\"false\\\">\\n          <ol class=\\\"carousel-indicators\\\">\\n            <li repeat.for=\\\"image of product.images\\\" class=\\\"${$index == 0 ? 'active' : ''}\\\"\\n                data-bs-target=\\\"[data-gallery='${product.id}']\\\" data-bs-slide-to=\\\"${$index}\\\"></li>\\n          </ol>\\n          <div class=\\\"carousel-inner\\\">\\n            <div repeat.for=\\\"image of product.images\\\"\\n                 class=\\\"carousel-item ${$index == 0 ? 'active' : ''}\\\">\\n              <img class=\\\"d-block mx-auto mw-100\\\" src=\\\"${image}\\\">\\n            </div>\\n          </div>\\n          <a class=\\\"carousel-control-prev\\\" href=\\\"#\\\" data-bs-target=\\\"[data-gallery='${product.id}']\\\"\\n             role=\\\"button\\\" data-bs-slide=\\\"prev\\\">\\n            <span class=\\\"carousel-control-prev-icon\\\"></span>\\n          </a>\\n          <a class=\\\"carousel-control-next\\\" href=\\\"#\\\" data-bs-target=\\\"[data-gallery='${product.id}']\\\"\\n             role=\\\"button\\\" data-bs-slide=\\\"next\\\">\\n            <span class=\\\"carousel-control-next-icon\\\"></span>\\n          </a>\\n        </div>\\n      </div>\\n    </div>\\n  </div>\\n\\n</template>\\n\";","import { autoinject, observable, bindable, LogManager } from 'aurelia-framework';\nimport { I18N } from 'aurelia-i18n';\nimport { Utils } from 'utils/helpers/utils';\nimport { IPrice } from 'domain/Product/IPrice';\nimport { hasAmountDependentPrice } from 'domain/Product/PriceDisplay';\nimport { IProduct } from 'domain/Product/IProduct';\nimport { IStockItem } from 'domain/Product/IStockItem';\nimport { ProductExtraHelper } from 'utils/helpers/product-extra-helper';\nimport { CurrencyFormatValueConverter, PricesToTooltipValueConverter } from 'utils/classes/value-converters';\n\nexport const log = LogManager.getLogger('app.components.price');\n\n@autoinject\nexport class PriceCustomElement {\n  @bindable @observable prices: IPrice[];\n  @bindable displayPrice: number | null;\n  @bindable product: IProduct | null;\n  @bindable stockItem: IStockItem | null;\n  hasRefundableDeposit = false;\n  refundableDeposit: number | null = null;\n  priceTooltip = '';\n  private currencyFormat = new CurrencyFormatValueConverter();\n  private pricesToTooltip = new PricesToTooltipValueConverter();\n\n  constructor(\n    private i18n: I18N\n  ) {}\n\n  // #region MAIN\n\n  bind() {\n    this.updateRefundableDepositInfo();\n  }\n\n  pricesChanged() {\n    // SAL-283 QA r6: a cart line without a stock row has no prices but a stored price; not an error.\n    if (this.prices == null && this.displayPrice == null)\n      Utils.showErrorToast(log, this.i18n.tr('components.price.errors.load'));\n\n    this.updateRefundableDepositInfo();\n  }\n\n  productChanged() {\n    this.updateRefundableDepositInfo();\n  }\n\n  stockItemChanged() {\n    this.updateRefundableDepositInfo();\n  }\n  \n  hasAmountDependentPrice(prices: IPrice[] | null | undefined) {\n    return hasAmountDependentPrice(prices);\n  }\n\n  updateRefundableDepositInfo() {\n    const refundableDepositSource = this.getRefundableDepositSource();\n\n    this.hasRefundableDeposit = ProductExtraHelper.hasRefundableDeposit(refundableDepositSource);\n    this.refundableDeposit = ProductExtraHelper.getRefundableDeposit(refundableDepositSource);\n    this.priceTooltip = this.getPriceTooltip();\n  }\n\n  /** Prices plus the refundable deposit, so the whole price field has one tooltip. */\n  getPriceTooltip() {\n    const priceLines = this.pricesToTooltip.toView(this.prices, this.i18n);\n    if (!this.hasRefundableDeposit) return priceLines;\n\n    return priceLines + this.getRefundableDepositLine();\n  }\n\n  private getRefundableDepositLine() {\n    if (this.refundableDeposit == null)\n      return this.i18n.tr('components.products.tooltips.casing.included-without-price');\n\n    return this.i18n.tr('components.products.tooltips.casing.price-line', {\n      price: this.currencyFormat.toView(this.refundableDeposit),\n    });\n  }\n\n  private getRefundableDepositSource() {\n    return ProductExtraHelper.getSelectedRefundableDepositSource(this.product, this.stockItem);\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n\\n  <span if.bind=\\\"displayPrice == null\\\">\\n    ${displayPrice | currencyFormat}\\n  </span>\\n  <span else tooltip.bind=\\\"priceTooltip\\\">\\n    <span>\\n      <i if.bind=\\\"hasAmountDependentPrice(prices)\\\" class=\\\"bi bi-bar-chart\\\"></i>\\n      ${displayPrice | currencyFormat}\\n    </span>\\n    <span if.bind=\\\"hasRefundableDeposit\\\" class=\\\"product-extra-price\\\">\\n      + ${refundableDeposit | currencyFormat}\\n    </span>\\n  </span>\\n\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { TireFilterHelper } from \"utils/helpers/tire-filter-helper\";\nimport { AppConfig } from \"app-config\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { isRequestNoise } from \"utils/helpers/request-errors\";\nimport { EventAggregator, Subscription } from \"aurelia-event-aggregator\";\nimport { LogManager, autoinject, observable, bindable } from \"aurelia-framework\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { ProductService } from \"services/product/product-service\";\nimport { PriceHelper } from \"utils/helpers/price-helper\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport $ from \"jquery\";\nimport { Collapse, Popover } from \"bootstrap\";\nimport { SearchOrder } from \"utils/enums/SearchOrder\";\nimport { isEmpty } from \"lodash\";\nimport { WarehouseService } from \"services/client/warehouse-service\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\n\nexport const log = LogManager.getLogger(\"app.components.product-list\");\n\n@autoinject\nexport class ProductListCustomElement {\n  @bindable @observable products: IProduct[];\n  @bindable currentPage = 1;\n  @bindable lastPage = 1;\n  @bindable query = \"\";\n  @bindable @observable vehicleId: number | undefined;\n  @bindable @observable categoryId: number | undefined;\n  @bindable orderBy = SearchOrder.Default;\n  @bindable orderReversed = false;\n  pageHasEan = false;\n  pageHasBrand = false;\n  pageHasInPackage = false;\n  @bindable extendedSearch: boolean;\n\n  colSpan = 9;\n  imageRowspan = 2;\n\n  @bindable options = {\n    showAmount: false,\n    showSum: false,\n    showAddToCart: false,\n  };\n\n  warehouses: IWarehouse[] = [];\n  // SAL-341: a request the search page started together with the search (optional)\n  @bindable warehousesRequest?: Promise<IWarehouse[]>;\n\n  private settingsSubscription: Subscription;\n\n  // https://discourse.aurelia.io/t/have-access-to-the-values-of-an-enum-in-a-html-page/831\n  SearchOrder = SearchOrder;\n\n  constructor(\n    private productService: ProductService,\n    private warehouseService: WarehouseService,\n    private appConfig: AppConfig,\n    private eventAggregator: EventAggregator,\n    private i18n: I18N,\n  ) {\n    // Not subscribeOnce: settings also load again on re-login and after they are saved,\n    // and the displayed prices have to follow\n    this.settingsSubscription = this.eventAggregator.subscribe(TKEvent.userSettingsLoaded, () => {\n      this.formatPrice();\n    });\n  }\n\n  attached() {\n    $(() => {\n      this.colSpan = $(\"#product-list-header-row\").children().length;\n    });\n  }\n\n  detached() {\n    this.settingsSubscription?.dispose();\n  }\n\n  // #region MAIN\n\n  productsChanged() {\n    this.prepareProductsForBinding();\n    this.processResult();\n  }\n\n  prepareProductsForBinding() {\n    if (!this.products) return;\n\n    this.products.forEach(product => {\n      if (!(\"selectedStock\" in product)) product.selectedStock = null;\n      if (!product.stock) product.stock = [];\n      if (!product.externalStock) product.externalStock = [];\n    });\n  }\n\n  // When the result is processed for the first time, vehicleId is not available yet\n  // So we need to update it once when the vehicle id is loaded\n  vehicleIdChanged(newValue: string, oldValue: string) {\n    if (oldValue !== undefined) return;\n\n    if (!this.products) return;\n    this.loadInfoBatch(this.products);\n  }\n\n  // When the result is processed for the first time, categoryId is not available yet\n  // So we need to update it once when the category id is loaded\n  categoryIdChanged(newValue: string, oldValue: string) {\n    if (oldValue !== undefined) return;\n\n    if (!this.products) return;\n    this.loadImagesBatch(this.products, this.categoryId);\n    // Without a vehicle the info request does not depend on the category; processResult loads it.\n    if (this.vehicleId) this.loadInfoBatch(this.products);\n  }\n\n  processResult() {\n    this.loadSortables();\n    this.moveRowsListener();\n    this.formatPrice();\n\n    this.imageRowspan =\n      this.appConfig.userSettings.detailsInProductPage ||\n      this.appConfig.userSettings.imagesInProductPage\n        ? 2\n        : 1;\n\n    this.renderColumnsConditionally();\n    if (this.products) {\n      // SAL-335 (TKCLIENT-1GV): a new search can replace or clear `products` while the\n      // warehouses load. Work on the list this call started with, and drop it if superseded.\n      const products = this.products;\n      this.getWarehouses().finally(() => {\n        if (this.products !== products || !products) return;\n        products.forEach(product => {\n          const hasTkItem = ProductExtraHelper.hasTkItem(product);\n          if (!hasTkItem) {\n            // SAL-270: partner-only row - its own partner qty/price already came with the search\n            // result (externalStock). Never refetch by id: GET 0/ExternalStock would wipe it.\n            // Bridge can send stock/externalStock as null; fillDefaultSelectedStock calls .find.\n            product.stock = product.stock ?? [];\n            product.externalStock = product.externalStock ?? [];\n            PriceHelper.formatStockPrices(product.externalStock, this.appConfig.userSettings, this.i18n);\n          }\n          this.fillDefaultSelectedStock(product);\n\n          // Fill out the cart amount input\n          if (!Utils.isPositive(product.toCartQuantity)) {\n            product.toCartQuantity = String(ProductExtraHelper.getMinimumQuantity(product.selectedStock));\n          }\n\n          this.highlightSearchQuery(product);\n\n          if (!hasTkItem) return;\n          this.loadThumbnail(product);\n        });\n\n        // SAL-165: one call per kind for the whole page, after the rows are on screen.\n        this.loadExternalStockBatch(products);\n        this.loadImagesBatch(products, this.categoryId);\n        this.loadInfoBatch(products);\n      });\n    }\n  }\n  // #endregion\n\n  // #region LOAD\n  loadSortables() {\n    $(() => {\n      const bsIconsClasses = \".bi-filter, .bi-sort-down, .bi-sort-up\";\n      $(\"th[data-sort]\").children(bsIconsClasses).remove();\n\n      const headers = $(\"th[data-sort]:not(:has(i))\");\n      headers.append(' <i class=\"bi-filter\"></i>');\n\n      const clickedElement = $(\"th[data-sort=\" + this.orderBy + \"]\").find(bsIconsClasses);\n      clickedElement.addClass(this.orderReversed ? \"bi-sort-up\" : \"bi-sort-down\");\n    });\n  }\n\n  getWarehouses(): Promise<IWarehouse[] | void> {\n    if (this.warehouses?.length > 0) return Promise.resolve(this.warehouses);\n\n    // One microtask later, so a warehousesRequest bound after `products` is already set\n    return Promise.resolve()\n      .then(() => this.warehousesRequest ?? this.warehouseService.getWarehouses())\n      .then(result => {\n        this.warehouses = Array.isArray(result) ? result : [];\n        log.debug(\"load warehouses\", this.warehouses);\n      })\n      .catch(() => Utils.showErrorToast(log, this.i18n.tr(\"components.warehouses.errors.load\")));\n  }\n\n  loadThumbnail(product: IProduct) {\n    product.imageLoadingCount = (product.imageLoadingCount ?? 0) + 1;\n\n    this.productService\n      .fetchThumbnail(product.id, product.thumbnailVersion)\n      .then(result => {\n        if (result == \"\") return;\n        // SAL-266: an <img src> URL; the browser loads and caches the bytes.\n        product.thumbnail = result;\n      })\n      .finally(() => {\n        product.imageLoadingCount = Math.max((product.imageLoadingCount ?? 1) - 1, 0);\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) return Utils.handleRequestNoise(log, error, this.i18n);\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      });\n  }\n\n  /** SAL-266: no thumbnail (404) or a broken one: show nothing instead of a broken image. */\n  thumbnailFailed(product: IProduct) {\n    product.thumbnail = null;\n  }\n\n  /** SAL-266: large thumbnail on hover, only once the image has really loaded. */\n  thumbnailLoaded(product: IProduct, element: HTMLElement) {\n    const trigger = element?.closest(`[data-image=\"${product.id}\"]`) as HTMLElement | null;\n    if (!trigger || Popover.getInstance(trigger)) return;\n    new Popover(trigger, {\n      content: `<img class=\"thumbnail-hover-image\" src=\"${product.thumbnail}\"></img>`,\n      trigger: \"hover focus\",\n      container: trigger,\n      html: true,\n    });\n  }\n\n  /** SAL-165: the TK-item rows of a page; partner-only rows have nothing to ask by id. */\n  private tkItems(products: IProduct[]): IProduct[] {\n    return (products ?? []).filter(p => ProductExtraHelper.hasTkItem(p));\n  }\n\n  /** SAL-165: images for the whole page (one call for the uncached rows). */\n  loadImagesBatch(products: IProduct[], categoryId?: number) {\n    const rows = this.tkItems(products);\n    if (rows.length === 0) return;\n    const byId = this.productService.fetchImagesBatch(\n      rows.map(p => p.id),\n      categoryId,\n    );\n\n    rows.forEach(product => {\n      const request = byId.get(Number(product.id));\n      if (!request) return;\n      product.imageLoadingCount = (product.imageLoadingCount ?? 0) + 1;\n      request\n        .then(result => {\n          if (this.products !== products) return;\n          // Category images come first in the category answer; replacing (not appending) keeps\n          // the plain list from being shown twice once the category id arrives.\n          product.images = result;\n        })\n        .finally(() => {\n          product.imageLoadingCount = Math.max((product.imageLoadingCount ?? 1) - 1, 0);\n        })\n        .catch(error => this.batchFailed(error));\n    });\n  }\n\n  /** SAL-165: extra info for the whole page (one call for the uncached rows). */\n  loadInfoBatch(products: IProduct[]) {\n    const rows = this.tkItems(products);\n    if (rows.length === 0) return;\n    const oldVehicleId = this.vehicleId;\n    const byId = this.productService.fetchInfoBatch(\n      rows.map(p => p.id),\n      this.vehicleId,\n      this.categoryId,\n    );\n\n    rows.forEach(product => {\n      byId\n        .get(Number(product.id))\n        ?.then(result => {\n          // A different vehicle invalidates the response. Category id arriving must not:\n          // the filtered tyre list has to keep the same extra info as code search (SAL-296).\n          if (this.vehicleId != oldVehicleId) return;\n\n          if (Utils.isArrayEmpty(result)) {\n            if (product.info && product.info.length > 0) return;\n            result = [];\n          }\n\n          product.info = result;\n          this.extractEanFromInfo(product);\n        })\n        .catch(error => this.batchFailed(error));\n    });\n  }\n\n  /** SAL-165: one toast per failed batch, not one per product. */\n  private lastBatchError: any;\n  private batchFailed(error: any) {\n    if (isRequestNoise(error)) return Utils.handleRequestNoise(log, error, this.i18n);\n    if (error === this.lastBatchError) return;\n    this.lastBatchError = error;\n    Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n  }\n\n  loadDescription(product: IProduct) {\n    const oldCategoryId = this.categoryId;\n\n    const fetch = this.categoryId\n      ? this.productService.fetchDescriptionWithCategory(product.id, this.categoryId)\n      : this.productService.fetchDescription(product.id);\n\n    fetch\n      .then(result => {\n        // Check if categoryId has showed up while waiting for response - if yes, then abort\n        if (this.categoryId != oldCategoryId) return;\n\n        product.description = result ? result : null;\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) {\n          product.description = null;\n          return Utils.handleRequestNoise(log, error, this.i18n);\n        }\n        product.description = null;\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      })\n      .finally(() => {\n        this.afterLoading(product, \"loading-description\");\n      });\n  }\n\n  loadDocuments(product: IProduct) {\n    const oldCategoryId = this.categoryId;\n\n    const fetch = this.categoryId\n      ? this.productService.fetchDocumentsWithCategory(product.id, this.categoryId)\n      : this.productService.fetchDocuments(product.id);\n\n    fetch\n      .then(result => {\n        // Check if categoryId has showed up while waiting for response - if yes, then abort\n        if (this.categoryId != oldCategoryId) return;\n\n        product.documents = Utils.isArrayEmpty(result) ? [] : result;\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) {\n          product.documents = [];\n          return Utils.handleRequestNoise(log, error, this.i18n);\n        }\n        product.documents = [];\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      })\n      .finally(() => {\n        this.afterLoading(product, \"loading-documents\");\n      });\n  }\n\n  loadOeNumbers(product: IProduct) {\n    this.productService\n      .fetchOeNumbers(product.id)\n      .then(result => {\n        if (Utils.isObjectEmpty(result)) result = {};\n\n        product.oeNumbers = Object.entries(result ?? {});\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) {\n          product.oeNumbers = [];\n          return Utils.handleRequestNoise(log, error, this.i18n);\n        }\n        product.oeNumbers = [];\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      })\n      .finally(() => {\n        this.afterLoading(product, \"loading-oe-numbers\");\n      });\n  }\n\n  loadCars(product: IProduct) {\n    this.productService\n      .fetchCars(product.id)\n      .then(result => {\n        if (Utils.isArrayEmpty(result)) result = [];\n\n        product.cars = result;\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) {\n          product.cars = [];\n          return Utils.handleRequestNoise(log, error, this.i18n);\n        }\n        product.cars = [];\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      })\n      .finally(() => {\n        this.afterLoading(product, \"loading-cars\");\n      });\n  }\n\n  /** SAL-165: partner stock for the whole page (one call for the uncached rows). */\n  loadExternalStockBatch(products: IProduct[]) {\n    const rows = this.tkItems(products);\n    if (rows.length === 0) return;\n    const byId = this.productService.fetchExternalStockBatch(rows.map(p => p.id));\n\n    rows.forEach(product => {\n      const existingExternalStock = product.externalStock ?? [];\n      byId\n        .get(Number(product.id))\n        ?.then(cached => {\n          if (this.products !== products) return;\n          // The cache is shared between pages; every row formats its own copy.\n          let result = (cached ?? []).map(item => ({ ...item }));\n          if (Utils.isArrayEmpty(result)) result = [];\n\n          ProductExtraHelper.preserveExternalStockRefundableDeposit(result, existingExternalStock);\n          product.externalStock = result;\n          PriceHelper.formatStockPrices(product.externalStock, this.appConfig.userSettings, this.i18n);\n\n          if (result.length > 0) this.fillDefaultSelectedStock(product);\n          const quantity = parseInt(product.toCartQuantity ?? \"\", 10);\n          if (!ProductExtraHelper.isValidMinimumQuantity(quantity, product.selectedStock)) {\n            product.toCartQuantity = String(ProductExtraHelper.getMinimumQuantity(product.selectedStock));\n          }\n        })\n        .catch(error => this.batchFailed(error));\n    });\n  }\n\n  fillDefaultSelectedStock(product: IProduct) {\n    let stockItem = product.stock.find(\n      x => x.warehouse.id == this.appConfig.userSettings.warehouseId,\n    );\n\n    if (!Utils.isInStock(stockItem)) {\n      var isNotInOurWarehouses = !product.stock.find(x => Utils.isInStock(x));\n      if (isNotInOurWarehouses && product.externalStock.length > 0) {\n        stockItem =\n          product.externalStock.find(s => Number(s.warehouse.groupId) === 2) ||\n          product.externalStock.find(s => Number(s.warehouse.groupId) === 1) ||\n          product.externalStock[0];\n      } else {\n        stockItem = this.getFallbackStock(product);\n      }\n      PriceHelper.formatStockPrices([stockItem], this.appConfig.userSettings, this.i18n);\n    }\n\n    product.selectedStock = stockItem;\n  }\n\n  getFallbackStock(product: IProduct) {\n    return {\n      warehouse:\n        (this.warehouses ?? []).find(x => x.id == this.appConfig.userSettings.warehouseId) ??\n        (this.warehouses ?? []).find(x => x.id == 0) ??\n        this.warehouses?.[0],\n      quantity: \"0\",\n      prices: product.prices ?? [],\n    };\n  }\n\n  extractEanFromInfo(product: IProduct) {\n    if (product.ean.length > 0) return;\n\n    const eanIndex = product.info?.findIndex(x => x[0] == \"EAN\") ?? -1;\n    if (eanIndex < 0) return;\n\n    const ean = product.info?.at(eanIndex)?.at(1);\n    if (!ean) return;\n\n    product.ean = ean;\n    product.info?.splice(eanIndex, 1);\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  hasTkItem(product: IProduct): boolean {\n    return ProductExtraHelper.hasTkItem(product);\n  }\n\n  getMinimumQuantity(product: IProduct): number {\n    return ProductExtraHelper.getMinimumQuantity(product.selectedStock);\n  }\n\n  changeOrder(clickedElement: Element) {\n    if (\n      !clickedElement.getAttribute(\"data-sort\") &&\n      !clickedElement.classList.contains(\"bi-filter\")\n    )\n      return;\n\n    // If clicked on sort icon, then use it's parent as base\n    if (clickedElement.classList.contains(\"bi-filter\"))\n      clickedElement = clickedElement.parentElement ?? clickedElement;\n\n    const orderBy = parseInt(clickedElement.getAttribute(\"data-sort\") ?? \"0\");\n    let orderReversed = !this.orderReversed;\n\n    // Reset orderReversed value to false if another column is being ordered\n    if (orderBy != this.orderBy) orderReversed = false;\n\n    this.orderReversed = orderReversed;\n    this.orderBy = orderBy;\n  }\n\n  toggleExtraRow(target: HTMLElement, product: IProduct) {\n    $(() => {\n      // Check if child element was clicked instead\n      if ($(target).prop(\"tagName\") != \"TD\" && $(target).prop(\"tagName\") != \"TR\") return;\n      // SAL-270: partner-only rows have no TK item, so no description/documents/OE/cars to load.\n      if (!ProductExtraHelper.hasTkItem(product)) return;\n\n      const productWrappers = $(`.clickable[data-product-id=\"${product.id}\"]`);\n\n      // Start loading them if they aren't already loaded\n      if (!this.areExtrasLoaded(product)) {\n        // If the element has any of these classes, we're still waiting for the results\n        if (productWrappers.is(\".loading-description, .loading-documents, .loading-oe-numbers\"))\n          return;\n\n        productWrappers.addClass(\n          \"loading-description loading-documents loading-oe-numbers loading-cars\",\n        );\n\n        this.loadDescription(product);\n        this.loadDocuments(product);\n        this.loadOeNumbers(product);\n        this.loadCars(product);\n\n        return;\n      }\n\n      this.tryOpenExtraRow(product, productWrappers, true);\n    });\n  }\n\n  shouldExtraRowOpen(product: IProduct): boolean {\n    const showDetails = this.appConfig.userSettings.detailsInProductPage;\n    const showImages = this.appConfig.userSettings.imagesInProductPage;\n\n    // extra row must be opened, because otherwise we can't print out the message that nothing can be displayed\n    if (!showDetails && !showImages) return true;\n\n    return this.anyDataInExtraRow(product);\n  }\n\n  anyDataInExtraRow(product: IProduct): boolean {\n    const showDetails = this.appConfig.userSettings.detailsInProductPage;\n    const showImages = this.appConfig.userSettings.imagesInProductPage;\n    const isDataInTable = $(\"#d-lg-none\").is(\":hidden\");\n\n    // Also check if EAN or package count is hidden or doesn't exist\n    const noHiddenData = isDataInTable || (!product.ean && !product.inPackage);\n    const noHiddenDetails = showDetails || product.info === null || product.info.length == 0;\n    const noDescriptions = product.description === null || product.description === \"\";\n    const noHiddenImages =\n      showImages || product.thumbnail === null || product.thumbnail.length == 0;\n    const noExtras = !this.isAnyExtras(product);\n\n    return !(noHiddenData && noHiddenDetails && noDescriptions && noHiddenImages && noExtras);\n  }\n\n  showGallery(product: IProduct) {\n    Utils.showGallery(product);\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  highlightSearchQuery(product: IProduct) {\n    // Highlight search query with <strong>\n    $(() => {\n      const target = $(\n        `[data-product-id=\"${product.id}\"] [data-highlight-query=\"${product.foundBy}\"]`,\n      );\n      if (target.length > 0) {\n        const regex = new RegExp(Utils.escapeRegex(this.query), \"gi\");\n        const code = target.html().replace(regex, \"<strong>$&</strong>\");\n        target.html(code);\n\n        if (!target.html().includes(\"<strong>\")) {\n          target.html(\"<strong>\" + target.html() + \"</strong>\");\n        }\n      }\n    });\n  }\n\n  isAnyExtras(product: IProduct) {\n    return (\n      product.cars?.length != 0 || product.documents?.length != 0 || product.oeNumbers?.length != 0\n    );\n  }\n\n  areExtrasLoaded(product: IProduct) {\n    // Don't wait for cars - they load separately and appear later\n    return product.documents !== undefined && product.oeNumbers !== undefined;\n  }\n\n  afterLoading(product: IProduct, classToRemove: string) {\n    const productWrappers = $(`.clickable[data-product-id=\"${product.id}\"]`);\n\n    productWrappers.removeClass(classToRemove);\n\n    // Don't wait for cars to load - open extra row when description, documents and oeNumbers are ready\n    // Cars will appear later when their request completes\n    if (productWrappers.is(\".loading-description, .loading-documents, .loading-oe-numbers\")) return;\n\n    this.tryOpenExtraRow(product, productWrappers);\n  }\n\n  tryOpenExtraRow(product: IProduct, productWrappers: JQuery<HTMLElement>, isUserToggle = false) {\n    $(() => {\n      if (!this.anyDataInExtraRow(product))\n        $(`[data-extra-not-found=\"${product.id}\"]`).html(\n          this.i18n.tr(\"components.products.errors.no-info-found\"),\n        );\n\n      if (this.shouldExtraRowOpen(product)) {\n        const extraRow = document.querySelector(`[data-extra=\"${product.id}\"]`);\n        // User click should always toggle, automatic open should not close an already open row\n        if (extraRow && (isUserToggle || !extraRow.classList.contains(\"show\"))) {\n          new Collapse(extraRow, { parent: \"#accordion\" }).toggle();\n        }\n      } else {\n        productWrappers.removeClass(\"clickable\");\n      }\n    });\n  }\n\n  // Move info and extra rows along with it's parent product row when sorted\n  moveRowsListener() {\n    $(() => {\n      $(\".sortable\").on(\"sorted\", function () {\n        $(this)\n          .find(\"[rowspan-value]\")\n          .each(function () {\n            $(this).attr(\"rowspan\", $(this).attr(\"rowspan-value\") || 2);\n          });\n\n        $(this)\n          .find(\"tr.info-row\")\n          .each(function () {\n            $(this).insertAfter(\n              `.product-row[data-product-id=\"${$(this).attr(\"data-product-id\")}\"]`,\n            );\n            $(this).children(\".product-image-wrapper\").remove();\n          });\n        $(this)\n          .find(\"tr.extra-row\")\n          .each(function () {\n            $(this).insertAfter(\n              $(`.info-row[data-product-id=\"${$(this).attr(\"data-product-id\")}\"]`),\n            );\n          });\n      });\n    });\n  }\n\n  formatPrice() {\n    if (!this.products || !this.appConfig.userSettings) return;\n\n    PriceHelper.formatProductsPrices(this.products, this.appConfig.userSettings, this.i18n);\n  }\n\n  pageHasEANChecker() {\n    for (const product of this.products) {\n      if (product.ean || !isEmpty(product.ean)) {\n        this.pageHasEan = true;\n        return;\n      }\n    }\n  }\n\n  pageHasBrandChecker() {\n    for (const product of this.products) {\n      if (product.brand || !isEmpty(product.brand)) {\n        this.pageHasBrand = true;\n        return;\n      }\n    }\n  }\n\n  pageHasInPackageChecker() {\n    for (const product of this.products) {\n      if (product.inPackage || product.inPackage > 0) {\n        this.pageHasInPackage = true;\n        return;\n      }\n    }\n  }\n\n  resetConditionalColumnRendering() {\n    this.pageHasEan = false;\n    this.pageHasBrand = false;\n    this.pageHasInPackage = false;\n  }\n\n  renderColumnsConditionally() {\n    this.resetConditionalColumnRendering();\n\n    if (!this.products || this.products.length == 0) return;\n\n    this.pageHasEANChecker();\n    this.pageHasBrandChecker();\n    this.pageHasInPackageChecker();\n  }\n\n  activateExtendedSearch() {\n    this.extendedSearch = true;\n  }\n\n  // #endregion\n  infoLabel(info: [string, string]): string {\n    const cat = this.categoryId != null ? this.categoryId : 10;\n    return TireFilterHelper.translateInfoPair(info, this.i18n, cat)[0];\n  }\n\n  infoValue(info: [string, string]): string {\n    const cat = this.categoryId != null ? this.categoryId : 10;\n    return TireFilterHelper.translateInfoPair(info, this.i18n, cat)[1];\n  }\n\n  infoHref(info: [string, string]): string | null {\n    return TireFilterHelper.infoHref(info);\n  }\n\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/mobile-cards\\\"></require>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n  <require from=\\\"components/product/product-list/add-to-cart\\\"></require>\\n  <require from=\\\"components/product/product-list/copy-to-clipboard\\\"></require>\\n  <require from=\\\"components/product/product-list/extra-row\\\"></require>\\n  <require from=\\\"components/product/product-list/gallery\\\"></require>\\n  <require from=\\\"components/product/product-list/stock\\\"></require>\\n  <require from=\\\"components/product/product-list/price\\\"></require>\\n  <require from=\\\"components/general/pager\\\"></require>\\n  <require from=\\\"components/product/product-list/report-button\\\"></require>\\n\\n  <!-- table-striped doesn't work, because every other row is hidden -->\\n  <!-- table-hover doesn't work, because we want to hover multiple rows at once (using .hover) -->\\n  <table mobile-cards\\n    id=\\\"accordion\\\"\\n    class=\\\"table table-borderless table-sm table-responsive-md w-100 accordion odd-row-darker-bg no-default-bg mc-products\\\">\\n    <thead>\\n      <tr id=\\\"product-list-header-row\\\" click.trigger=\\\"changeOrder($event.target)\\\">\\n        <th if.bind=\\\"appConfig.userSettings.imagesInProductPage\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.thumbnail' & t}\\n        </th>\\n        <th data-sort=\\\"1\\\">${'components.products.headers.code' & t}</th>\\n        <th data-sort=\\\"2\\\">${'components.products.headers.name' & t}</th>\\n        <th\\n          if.bind=\\\"pageHasEan || orderBy == SearchOrder.EAN\\\"\\n          data-sort=\\\"3\\\"\\n          class=\\\"text-center d-none d-lg-table-cell\\\">\\n          ${'components.products.headers.ean' & t}\\n        </th>\\n        <th if.bind=\\\"pageHasBrand || orderBy == SearchOrder.Brand\\\" data-sort=\\\"4\\\">\\n          ${'components.products.headers.brand' & t}\\n        </th>\\n        <th\\n          if.bind=\\\"pageHasInPackage || orderBy == SearchOrder.InPackage\\\"\\n          data-sort=\\\"5\\\"\\n          class=\\\"text-center d-none d-lg-table-cell\\\">\\n          ${'components.products.headers.in-package' & t}\\n        </th>\\n        <th class=\\\"text-center\\\">${'components.products.headers.stock' & t}</th>\\n        <th class=\\\"text-end\\\">${'components.products.headers.price' & t}</th>\\n        <th if.bind=\\\"options.showAmount\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.amount' & t}\\n        </th>\\n        <th if.bind=\\\"options.showSum\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.total' & t}\\n        </th>\\n        <th if.bind=\\\"options.showAddToCart\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.add-to-cart' & t}\\n        </th>\\n      </tr>\\n    </thead>\\n\\n    <tbody repeat.for=\\\"product of products\\\">\\n      <tr\\n        class=\\\"clickable product-row\\\"\\n        data-product-id.bind=\\\"product.id\\\"\\n        click.delegate=\\\"toggleExtraRow($event.target, product)\\\">\\n        <td\\n          rowspan.bind=\\\"imageRowspan\\\"\\n          if.bind=\\\"appConfig.userSettings.imagesInProductPage\\\"\\n          class=\\\"product-image-wrapper\\\"\\n          click.trigger=\\\"showGallery(product)\\\"\\n          data-image.bind=\\\"product.id\\\">\\n          <span class=\\\"product-image-state\\\">\\n            <span\\n              if.bind=\\\"product.imageLoadingCount && !product.thumbnail\\\"\\n              class=\\\"product-image-loading\\\">\\n              <span class=\\\"spinner-border spinner-border-sm text-secondary\\\" role=\\\"status\\\"></span>\\n            </span>\\n            <img\\n              class=\\\"mx-auto product-image\\\"\\n              if.bind=\\\"product.thumbnail\\\"\\n              src.bind=\\\"product.thumbnail\\\"\\n              loading=\\\"lazy\\\"\\n              load.trigger=\\\"thumbnailLoaded(product, $event.target)\\\"\\n              error.trigger=\\\"thumbnailFailed(product)\\\" />\\n          </span>\\n        </td>\\n\\n        <td\\n          if.bind=\\\"product.originalCode != product.code\\\"\\n          class=\\\"font-italic text-nowrap mc-code\\\"\\n          tooltip=\\\"${'components.products.fields.replacement' & t: {'originalCode': product.originalCode}}\\\">\\n          <span class=\\\"pe-none\\\" data-highlight-query=\\\"code\\\">${product.code}</span>\\n          <copy-to-clipboard text.bind=\\\"product.code\\\"></copy-to-clipboard>\\n          <report-button product.bind=\\\"product\\\"></report-button>\\n        </td>\\n\\n        <td else class=\\\"text-nowrap mc-code\\\">\\n          <span class=\\\"pe-none\\\" data-highlight-query=\\\"code\\\">${product.code}</span>\\n          <copy-to-clipboard text.bind=\\\"product.code\\\"></copy-to-clipboard>\\n          <report-button product.bind=\\\"product\\\"></report-button>\\n        </td>\\n\\n        <td class=\\\"mc-full\\\"><span data-highlight-query=\\\"name\\\">${product.name}</span></td>\\n\\n        <td\\n          if.bind=\\\"pageHasEan || orderBy == SearchOrder.EAN\\\"\\n          class=\\\"text-center text-nowrap d-none d-lg-table-cell\\\">\\n          <span data-highlight-query=\\\"ean\\\">${product.ean}</span>\\n        </td>\\n\\n        <td if.bind=\\\"pageHasBrand || orderBy == SearchOrder.Brand\\\" class=\\\"mc-brand\\\">\\n          <span>${product.brand}</span>\\n        </td>\\n\\n        <td\\n          if.bind=\\\"pageHasInPackage || orderBy == SearchOrder.InPackage\\\"\\n          class=\\\"text-center text-nowrap d-none d-lg-table-cell\\\">\\n          <span>${product.inPackage > 0 ? product.inPackage : ''}</span>\\n        </td>\\n\\n        <td\\n          class=\\\"text-center clickable mc-stock\\\"\\n          as-element=\\\"stock\\\"\\n          data-value.bind=\\\"product.selectedStock\\\"\\n          product.bind=\\\"product\\\"\\n          warehouses.bind=\\\"warehouses\\\"></td>\\n\\n        <td\\n          class=\\\"text-end text-nowrap mc-price\\\"\\n          as-element=\\\"price\\\"\\n          prices.bind=\\\"product.selectedStock ? product.selectedStock.prices : product.prices\\\"\\n          display-price.bind=\\\"product.selectedStock ? product.selectedStock.displayPrice : null\\\"\\n          product.bind=\\\"product\\\"\\n          stock-item.bind=\\\"product.selectedStock\\\"></td>\\n\\n        <td if.bind=\\\"options.showAmount\\\" class=\\\"text-center text-nowrap\\\">\\n          <input\\n            type=\\\"number\\\"\\n            class=\\\"form-control form-control-sm mx-auto cart-product-amount\\\"\\n            min.bind=\\\"getMinimumQuantity(product)\\\"\\n            step.bind=\\\"getMinimumQuantity(product)\\\"\\n            value.bind=\\\"product.quantity\\\" />\\n        </td>\\n\\n        <td if.bind=\\\"options.showSum\\\" class=\\\"text-end text-nowrap\\\">\\n          <span>${(product.selectedStock ? product.selectedStock.displayPrice * product.quantity : null) | currencyFormat}</span>\\n        </td>\\n\\n        <td if.bind=\\\"options.showAddToCart\\\" class=\\\"text-nowrap clickable mc-action\\\">\\n          <add-to-cart product.bind=\\\"product\\\"></add-to-cart>\\n        </td>\\n      </tr>\\n\\n      <tr\\n        if.bind=\\\"appConfig.userSettings.detailsInProductPage || appConfig.userSettings.imagesInProductPage\\\"\\n        class=\\\"clickable info-row\\\"\\n        data-disablesort=\\\"true\\\"\\n        data-product-id.bind=\\\"product.id\\\"\\n        click.delegate=\\\"toggleExtraRow($event.target, product)\\\">\\n        <td colspan.bind=\\\"colSpan\\\">\\n          <template if.bind=\\\"appConfig.userSettings.detailsInProductPage\\\">\\n            <span repeat.for=\\\"info of product.info\\\" class=\\\"text-muted small mx-1\\\">\\n              <a if.bind=\\\"infoHref(info)\\\" href.bind=\\\"infoHref(info)\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\" click.delegate=\\\"$event.stopPropagation() || true\\\">${infoLabel(info)}</a>\\n              <template else><b>${infoLabel(info)}:</b> ${infoValue(info)}</template>\\n            </span>\\n          </template>\\n          <span class=\\\"text-muted small mt-1\\\" data-extra-not-found.bind=\\\"product.id\\\"></span>\\n        </td>\\n      </tr>\\n\\n      <tr class=\\\"extra-row\\\" data-disablesort=\\\"true\\\" data-product-id.bind=\\\"product.id\\\">\\n        <td colspan.bind=\\\"colSpan\\\" class=\\\"p-0\\\">\\n          <extra-row product.bind=\\\"product\\\"></extra-row>\\n        </td>\\n      </tr>\\n    </tbody>\\n  </table>\\n\\n  <div if.bind=\\\"currentPage == lastPage && extendedSearch == false\\\" class=\\\"d-flex justify-content-center\\\">\\n    <button type=\\\"button\\\" class=\\\"btn btn-primary mb-3\\\" click.delegate=\\\"activateExtendedSearch()\\\">\\n      ${'components.products.buttons.load-more' & t}\\n    </button>\\n  </div>\\n\\n  <pager current-page.two-way=\\\"currentPage\\\" last-page.bind=\\\"lastPage\\\"></pager>\\n\\n  <gallery if.bind=\\\"appConfig.userSettings.imagesInProductPage\\\" products.bind=\\\"products\\\"></gallery>\\n\\n  <span id=\\\"d-lg-none\\\" class=\\\"d-lg-none\\\"></span>\\n</template>\\n\";","import { Utils } from \"utils/helpers/utils\";\nimport { LogManager, autoinject, bindable } from \"aurelia-framework\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { ProductService } from \"services/product/product-service\";\nimport { I18N } from \"aurelia-i18n\";\n\nexport const log = LogManager.getLogger(\"app.components.report-button\");\n\n@autoinject\nexport class ReportButtonCustomElement {\n  @bindable product: IProduct;\n\n  constructor(private i18n: I18N, private productService: ProductService) {}\n\n  sendProductReport(product: IProduct, reportText: string) {\n    this.productService\n      .postReportError(product.code, reportText, product.id)\n      .then(() => {\n        Utils.showSuccessToast(this.i18n.tr(\"components.products.messages.error-reported\"));\n      })\n      .catch(() => {\n        Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.report-error\"));\n      });\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n\\n  <a\\n    class=\\\"icon-link icon-link-hover text-reset\\\"\\n    data-bs-toggle=\\\"modal\\\"\\n    data-bs-target=\\\"#id${product.id}\\\">\\n    <i\\n      class=\\\"bi bi-exclamation-diamond clickable-important\\\"\\n      tooltip=\\\"${'components.products.tooltips.faulty-product' & t}\\\"></i>\\n  </a>\\n  <div class=\\\"modal fade\\\" id=\\\"id${product.id}\\\" tabindex=\\\"-1\\\" aria-hidden=\\\"true\\\">\\n    <div class=\\\"modal-dialog modal-dialog-centered\\\">\\n      <div class=\\\"modal-content\\\">\\n        <div class=\\\"modal-header\\\">\\n          <h1 class=\\\"modal-title fs-5\\\">\\n            ${product.code} ${'components.report-modal.report-faulty' & t}\\n          </h1>\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn-close clickable-important\\\"\\n            data-bs-dismiss=\\\"modal\\\"\\n            aria-label=\\\"Close\\\"></button>\\n        </div>\\n        <div class=\\\"modal-body\\\">\\n          <form>\\n            <div class=\\\"form-group\\\">\\n              <textarea\\n                class=\\\"form-control\\\"\\n                placeholder=\\\"${'components.report-modal.describe-fault' & t}\\\"\\n                value.bind=\\\"reportText\\\"></textarea>\\n            </div>\\n          </form>\\n        </div>\\n        <div class=\\\"modal-footer\\\">\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-secondary clickable-important\\\"\\n            data-bs-dismiss=\\\"modal\\\">\\n            ${'components.report-modal.close-button' & t}\\n          </button>\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-primary clickable-important\\\"\\n            click.trigger=\\\"sendProductReport(product, reportText)\\\">\\n            ${'components.report-modal.send-button' & t}\\n          </button>\\n        </div>\\n      </div>\\n    </div>\\n  </div>\\n</template>\\n\";","import { AppConfig } from \"app-config\";\nimport { ICartProduct } from \"domain/Cart/ICartProduct\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { ProductService } from \"services/product/product-service\";\nimport { autoinject, LogManager, bindable } from \"aurelia-framework\";\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { IStockItem } from \"domain/Product/IStockItem\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { PriceHelper } from \"utils/helpers/price-helper\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\n\nexport const log = LogManager.getLogger(\"app.components.stock\");\n\n@autoinject\nexport class StockCustomElement {\n  @bindable product: IProduct | ICartProduct;\n  @bindable warehouses: IWarehouse[];\n  isInStock = Utils.isInStock;\n\n  constructor(\n    private i18n: I18N,\n    private productService: ProductService,\n    private appConfig: AppConfig,\n    private eventAggregator: EventAggregator\n  ) {}\n\n  attached() {\n    if (this.product == null) {\n      Utils.showErrorToast(log, this.i18n.tr(\"components.stock.errors.load\"));\n      return;\n    }\n  }\n\n  getValue(stock: string): number {\n    switch (stock) {\n      case \"e\":\n        return 11;\n      case \"t\":\n        return -2;\n      case \"l\":\n        return -1;\n      default:\n        return Number(stock);\n    }\n  }\n\n  takeIntoStockUserWish(productCode: string, productId: number) {\n    const confirmation = confirm(\n      this.i18n.tr(\"components.products.messages.confirm-take-into-stock-wish\")\n    );\n\n    if (confirmation == false) return;\n\n    this.productService\n      .postProductStockRequest(productCode, productId)\n      .then(() => {\n        Utils.showSuccessToast(\n          this.i18n.tr(\"components.products.messages.take-into-stock-wish-received\")\n        );\n      })\n      .catch(() => {\n        Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.take-into-stock-wish\"));\n      });\n  }\n\n  getStockQuantity(warehouse: IWarehouse): string {\n    const stockItem = this.product.stock.find(x => x.warehouse.id === warehouse.id);\n    return stockItem?.quantity ?? \"0\";\n  }\n\n  updateStockFromWarehouse(warehouse: IWarehouse) {\n    let stockItem = this.product.stock.find(x => x.warehouse.id === warehouse.id);\n\n    if (!stockItem) {\n      stockItem = {\n        warehouse:\n          this.warehouses.find(x => x.id == warehouse.id) ??\n          this.warehouses.find(x => x.id == 0) ??\n          this.warehouses[0],\n        quantity: \"0\",\n        prices: this.product.prices ?? [],\n      };\n      PriceHelper.formatStockPrices([stockItem], this.appConfig.userSettings, this.i18n);\n    }\n\n    this.updateStock(stockItem);\n  }\n\n  updateStock(stockItem: IStockItem) {\n    if (!stockItem.warehouse.isAllowed) return;\n\n    this.product.selectedStock = stockItem;\n    this.snapToCartQuantityToMinimum(stockItem);\n\n    if (\"cartProductId\" in this.product) {\n      // SAL-283: an explicit choice replaces any automatic fallback row, so saving it moves the line.\n      (this.product as { fallbackStock?: unknown }).fallbackStock = undefined;\n      this.eventAggregator.publish(TKEvent.cartProductsWarehouseChanged, this.product); // TODO rethink this\n    }\n  }\n\n  allWarehousesNotAllowed() {\n    return this.product.stock.length > 0 && this.product.stock.every(x => !x.warehouse.isAllowed);\n  }\n\n  getNotAllowedStock() {\n    return this.product.stock.filter(x => !x.warehouse.isAllowed);\n  }\n\n  externalStockLabel(stockItem: IStockItem): string {\n    return (\n      ProductExtraHelper.getExternalWarehouseLabel(stockItem?.warehouse) ??\n      (Number(stockItem?.warehouse?.groupId) === 1\n        ? this.i18n.tr(\"components.products.headers.factory-warehouse\")\n        : this.i18n.tr(\"components.products.headers.partner-warehouse\"))\n    );\n  }\n\n  // External stock helpers: return external stock items grouped by warehouse.groupId\n  // (1 factory, 2 partner, 3 Dunlop, 4 Rehviladu). 2, 3 and 4 share the partner section.\n  getExternalStockByGroup(...groupIds: number[]): IStockItem[] {\n    if (!this.product || !this.product.externalStock) return [];\n    return this.product.externalStock.filter(s => s.warehouse && groupIds.includes(Number(s.warehouse.groupId)));\n  }\n\n  otherStockWarningNeeded(warehouse: IWarehouse) {\n    if (!warehouse) return false;\n    if (warehouse.isExternal) return true;\n\n    const warehouseId = warehouse.id;\n    const userWarehouseId = this.appConfig.userSettings.warehouseId;\n    const isCentral = warehouseId === 1;\n    const isKadaka = warehouseId === 3;\n    const isTartu = warehouseId === 21;\n\n    return !(warehouseId === userWarehouseId || isCentral || isKadaka || isTartu);\n  }\n  private snapToCartQuantityToMinimum(stockItem: IStockItem) {\n    const product = this.product as IProduct;\n    const quantity = parseInt(product.toCartQuantity ?? \"\", 10);\n    if (ProductExtraHelper.isValidMinimumQuantity(quantity, stockItem)) return;\n    product.toCartQuantity = String(ProductExtraHelper.getMinimumQuantity(stockItem));\n  }\n\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n\\n  <div class=\\\"d-flex justify-content-center align-items-center\\\">\\n    <div if.bind=\\\"product.selectedStock\\\" class=\\\"dropdown-center\\\">\\n      <button\\n        class=\\\"btn dropdown-toggle btn-outline-dark clickable-important jumping-icon-container\\\"\\n        type=\\\"button\\\"\\n        data-bs-toggle=\\\"dropdown\\\"\\n        aria-expanded=\\\"false\\\">\\n        <template if.bind=\\\"product.selectedStock.warehouse.isExternal\\\">${externalStockLabel(product.selectedStock)}:</template>\\n        <template else>${product.selectedStock.warehouse.name}:</template>\\n        ${ product.selectedStock.quantity | stockName:i18n}\\n\\n        <template if.bind=\\\"otherStockWarningNeeded(product.selectedStock.warehouse)\\\">\\n          <i\\n            if.bind=\\\"product.selectedStock.warehouse.isExternal == false\\\"\\n            class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n            tooltip=\\\"${'components.products.tooltips.other-stock-warning.warehouses.' + product.selectedStock.warehouse.id & t}\\\"></i>\\n          <i\\n            else\\n            class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n            tooltip=\\\"${'components.products.tooltips.other-stock-warning.external.' + product.selectedStock.warehouse.groupId & t}\\\"></i>\\n        </template>\\n      </button>\\n\\n      <ul class=\\\"dropdown-menu\\\">\\n        <li repeat.for=\\\"warehouse of warehouses\\\">\\n          <a\\n            class=\\\"dropdown-item jumping-icon-container\\\"\\n            click.delegate=\\\"updateStockFromWarehouse(warehouse)\\\">\\n            ${warehouse.name}: ${getStockQuantity(warehouse) | stockName:i18n }\\n            <i\\n              if.bind=\\\"otherStockWarningNeeded(warehouse)\\\"\\n              class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n              tooltip=\\\"${'components.products.tooltips.other-stock-warning.warehouses.' + warehouse.id & t}\\\"></i>\\n          </a>\\n        </li>\\n\\n        <li repeat.for=\\\"stockItem of getNotAllowedStock()\\\" class=\\\"non-clickable\\\">\\n          <a class=\\\"dropdown-item disabled\\\">\\n            ${stockItem.warehouse.name}: ${stockItem.quantity | stockName:i18n }\\n          </a>\\n        </li>\\n\\n        <template if.bind=\\\"product.externalStock.length > 0\\\">\\n          <template if.bind=\\\"getExternalStockByGroup(2, 3, 4).length > 0\\\">\\n            <li><hr class=\\\"dropdown-divider\\\" /></li>\\n            <li>\\n              <h6 class=\\\"dropdown-header\\\">${'components.products.headers.partner-warehouse' & t}</h6>\\n            </li>\\n            <li repeat.for=\\\"stockItem of getExternalStockByGroup(2, 3, 4)\\\">\\n              <a\\n                class=\\\"dropdown-item clickable-important jumping-icon-container\\\"\\n                click.delegate=\\\"updateStock(stockItem)\\\">\\n                ${stockItem.quantity | stockName:i18n } - ${ stockItem.displayPrice | currencyFormat\\n                }/${'components.stock.type.pcs' & t}\\n                <i\\n                  class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n                  tooltip=\\\"${'components.products.tooltips.other-stock-warning.external.' + stockItem.warehouse.groupId & t}\\\"></i>\\n              </a>\\n            </li>\\n          </template>\\n          <template if.bind=\\\"getExternalStockByGroup(1).length > 0\\\">\\n            <li><hr class=\\\"dropdown-divider\\\" /></li>\\n            <li>\\n              <h6 class=\\\"dropdown-header\\\">\\n                ${'components.products.headers.factory-warehouse' & t}\\n              </h6>\\n            </li>\\n            <li repeat.for=\\\"stockItem of getExternalStockByGroup(1)\\\">\\n              <a\\n                class=\\\"dropdown-item clickable-important jumping-icon-container\\\"\\n                click.delegate=\\\"updateStock(stockItem)\\\">\\n                ${stockItem.quantity | stockName:i18n } - ${ stockItem.displayPrice | currencyFormat\\n                }/${'components.stock.type.pcs' & t}\\n                <i\\n                  class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n                  tooltip=\\\"${'components.products.tooltips.other-stock-warning.external.' + stockItem.warehouse.groupId & t}\\\"></i>\\n              </a>\\n            </li>\\n          </template>\\n        </template>\\n      </ul>\\n    </div>\\n    <span else class=\\\"spinner-border spinner-border-sm text-secondary\\\" role=\\\"status\\\"></span>\\n\\n    <a\\n      if.bind=\\\"product.stock.length == 0 && product.externalStock.length == 0 || allWarehousesNotAllowed()\\\"\\n      class=\\\"icon-link icon-link-hover text-reset\\\"\\n      click.trigger=\\\"takeIntoStockUserWish(product.code, product.id)\\\">\\n      <i\\n        class=\\\"bi bi-bell clickable-important\\\"\\n        tooltip=\\\"${'components.products.tooltips.interested-take-into-stock' & t}\\\"></i>\\n    </a>\\n  </div>\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { isRequestNoise } from \"utils/helpers/request-errors\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { CategoryService } from \"services/product/category-service\";\nimport { AppConfig } from \"app-config\";\nimport { Router, NavigationInstruction, PipelineResult } from \"aurelia-router\";\nimport { IParentItem } from \"domain/Base/IParentItem\";\nimport { LogManager, autoinject } from \"aurelia-framework\";\nimport $ from \"jquery\";\nimport \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.search.categories\");\n\n@autoinject\nexport class Categories {\n  // Cache\n  categories: IParentItem[];\n\n  constructor(\n    private router: Router,\n    private eventAggregator: EventAggregator,\n    private appConfig: AppConfig, // used by HTML\n    private categoryService: CategoryService,\n    private i18n: I18N,\n  ) {}\n\n  // called only once: when the site is opened (and the user probably isn't logged in yet)\n  activate() {\n    // If user is already logged in, but refreshed the page\n    if (this.appConfig.isLoggedIn) this.loadCategoryMenu();\n\n    // attached() was too late, the \"router:navigation:success\" event had already been fired\n    this.eventAggregator.subscribe(\n      \"router:navigation:success\",\n      (event: { instruction: NavigationInstruction; result: PipelineResult }) => {\n        const currentRoute = event.instruction.config.name;\n        if (!currentRoute) return;\n\n        // Run only after successful login\n        if (this.appConfig.isLoggedIn && this.categories === undefined) this.loadCategoryMenu();\n      },\n    );\n  }\n\n  // #region LOAD\n\n  loadCategoryMenu() {\n    this.categoryService\n      .fetchCategories()\n      .then(result => {\n        this.categories = result;\n        this.positionSubmenu();\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) return Utils.handleRequestNoise(log, error, this.i18n);\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      });\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  openCategory(category: IParentItem) {\n    let id = category.id;\n\n    if (id == 6 || id == 7 || id == 8) {\n      // Car fitment categories (tyres/cat 10 use typed filters, not mark/model)\n      this.router.navigateToRoute(\"categoryManufacturers\", { categoryId: category.id });\n      return;\n    }\n\n    if (id == 54)\n      // 54 is alias for 10\n      id = 10;\n\n    this.router.navigateToRoute(\"categoryProducts\", {\n      categoryId: id,\n      page: 1,\n    });\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  positionSubmenu() {\n    $(() => {\n      // SAL-297: runs on every open, from viewport coordinates (getBoundingClientRect), so page\n      // scroll, resize and zoom since the last open are picked up without a reload.\n      function position(element: JQuery<HTMLElement>) {\n        const panel = element[0];\n        const level1 = document.getElementById(\"level-1-menu\");\n        const group = panel?.parentElement;\n        if (!panel || !level1 || !group) return;\n\n        const margin = 8;\n        const level1Rect = level1.getBoundingClientRect();\n        const groupRect = group.getBoundingClientRect();\n        const visibleTop = Math.max(level1Rect.top, 0);\n        // No bottom margin: same cap as before, so the columns match the Chrome reference.\n        const maxHeight = Math.max(window.innerHeight - visibleTop, 0);\n        const minHeight = Math.min(level1.clientHeight, maxHeight);\n\n        // Lay the columns out at their natural width first, then measure them.\n        element.removeClass(\"level-2-scroll\");\n        element.css({\n          position: \"absolute\",\n          top: visibleTop - groupRect.top + \"px\",\n          left: \"100%\",\n          width: \"10000px\",\n          \"max-width\": \"\",\n          \"min-height\": minHeight + \"px\",\n          \"max-height\": maxHeight + \"px\",\n          \"overflow-x\": \"hidden\",\n          \"overflow-y\": \"hidden\",\n        });\n\n        const panelRect = panel.getBoundingClientRect();\n        const style = getComputedStyle(panel);\n        let contentRight = panelRect.left;\n        for (const child of Array.from(panel.children))\n          contentRight = Math.max(contentRight, child.getBoundingClientRect().right);\n        const neededWidth =\n          contentRight -\n          panelRect.left +\n          parseFloat(style.paddingRight) +\n          parseFloat(style.borderRightWidth);\n\n        const viewportWidth = document.documentElement.clientWidth;\n        const availableWidth = Math.max(viewportWidth - panelRect.left - margin, 0);\n\n        if (neededWidth <= availableWidth) {\n          // Preferred: every column fully visible, no scrollbar.\n          element.css({ width: Math.ceil(neededWidth) + \"px\" });\n\n          // A single group taller than the height cap can't be split into columns: keep the\n          // columns, but let the panel scroll vertically so its last items stay reachable.\n          if (panel.scrollHeight > panel.clientHeight + 1) {\n            element.css({ \"overflow-y\": \"auto\" });\n            const scrollbar = panel.offsetWidth - panel.clientWidth;\n            if (scrollbar > 0) element.css({ width: Math.ceil(neededWidth) + scrollbar + \"px\" });\n          }\n          return;\n        }\n\n        // Fallback: no horizontal room. One column that scrolls inside the panel.\n        element.addClass(\"level-2-scroll\");\n        const width = Math.min(Math.max(availableWidth, 200), viewportWidth - 2 * margin);\n        element.css({\n          width: width + \"px\",\n          \"max-width\": \"\",\n          \"overflow-x\": \"auto\",\n          \"overflow-y\": \"auto\",\n        });\n\n        // Phones and narrow windows: no room right of level 1, so overlap it to stay on screen.\n        if (panelRect.left + width > viewportWidth - margin)\n          element.css({ left: viewportWidth - margin - width - groupRect.left + \"px\" });\n      }\n\n      // Submenu click support - (c) https://stackoverflow.com/a/45755948\n      $(\".dropdown-menu a.dropdown-toggle\").on(\"click\", function () {\n        if (!$(this).next().hasClass(\"show\"))\n          $(this).parents(\".dropdown-menu\").first().find(\".show\").removeClass(\"show\");\n\n        const subMenu = $(this).next(\".dropdown-menu\");\n        subMenu.toggleClass(\"show\");\n        if (subMenu.hasClass(\"show\")) position(subMenu);\n\n        return false;\n      });\n\n      $(\".level-2-menu .dropdown-item\").on(\"click\", function () {\n        $(this).parents().removeClass(\"hover-show show\");\n      });\n\n      $(\".dropdown-menu a.dropdown-toggle\").on(\"mouseenter\", function () {\n        if ($(\"#level-1-menu\").find(\".show\").length > 0) return;\n\n        const menu = $(this).next();\n        if (!menu.hasClass(\"hover-show\")) {\n          menu.addClass(\"hover-show\");\n          position(menu);\n        }\n      });\n      $(\".dropdown-menu a.dropdown-toggle\").on(\"mouseleave\", function () {\n        if ($(this).next(\".dropdown-menu:hover\").length == 0)\n          $(this).next().removeClass(\"hover-show\");\n      });\n      $(\".level-2-menu\").on(\"mouseleave\", function () {\n        if ($(this).prev(\".dropdown-toggle:hover\").length == 0) $(this).removeClass(\"hover-show\");\n      });\n    });\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n\\n  <div class=\\\"dropdown\\\">\\n    <button type=\\\"button\\\" class=\\\"btn btn-outline-primary dropdown-toggle\\\" data-bs-toggle=\\\"dropdown\\\">\\n      ${'pages.category.button'& t}\\n    </button>\\n\\n    <div id=\\\"level-1-menu\\\" class=\\\"dropdown-menu\\\">\\n      <div repeat.for=\\\"category of categories\\\" class=\\\"btn-group dropdown-submenu dropend w-100\\\">\\n        <a if.bind=\\\"category.children.length < 1\\\" class=\\\"dropdown-item\\\" href=\\\"#\\\"\\n           click.delegate=\\\"openCategory(category)\\\">\\n          ${('pages.category.categories.' + category.id) & t: { 'defaultValue': category.name }}\\n        </a>\\n        <template else>\\n          <a class=\\\"dropdown-item dropdown-toggle\\\" role=\\\"button\\\" href=\\\"#\\\">\\n            ${('pages.category.categories.' + category.id) & t: { 'defaultValue': category.name }}\\n          </a>\\n\\n          <div class=\\\"dropdown-menu level-2-menu col-sm\\\">\\n            <div repeat.for=\\\"subcategory of category.children\\\">\\n              <a if.bind=\\\"subcategory.children.length < 1\\\"\\n                 class=\\\"dropdown-item dropdown-header font-weight-bold text-primary\\\" href=\\\"#\\\"\\n                 click.delegate=\\\"openCategory(subcategory)\\\">\\n                ${('pages.category.categories.' + subcategory.id) & t: { 'defaultValue':\\n                subcategory.name }}\\n              </a>\\n              <template else>\\n                <h6 class=\\\"dropdown-header text-primary\\\">\\n                  ${('pages.category.categories.' + subcategory.id) & t: { 'defaultValue':\\n                  subcategory.name }}\\n                </h6>\\n\\n                <a repeat.for=\\\"subcategory2 of subcategory.children\\\" class=\\\"dropdown-item\\\"\\n                   click.delegate=\\\"openCategory(subcategory2)\\\" href=\\\"#\\\">\\n                  ${('pages.category.categories.' + subcategory2.id) & t: { 'defaultValue':\\n                  subcategory2.name }}\\n                </a>\\n              </template>\\n            </div>\\n          </div>\\n        </template>\\n      </div>\\n    </div>\\n  </div>\\n\\n</template>\\n\";","import { TKEvent } from \"utils/enums/TKEvent\";\nimport { SearchType } from \"utils/enums/SearchType\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { AppConfig } from \"app-config\";\nimport { Router, NavigationInstruction, PipelineResult } from \"aurelia-router\";\nimport { LogManager, autoinject, observable } from \"aurelia-framework\";\nimport { decodeSearchRouteQuery, encodeSearchRouteQuery, shouldNavigateForQuery } from \"utils/helpers/search-route\";\n\nexport const log = LogManager.getLogger(\"app.search.search-bar\");\n\n@autoinject\nexport class SearchBar {\n  // Main variables\n  @observable query: string;\n  @observable type: SearchType;\n  page = 1;\n  extendedSearch = false;\n\n  // Search delay variables\n  searchDelayMilliseconds = 500;\n  searchTimer: NodeJS.Timeout;\n  // SAL-341: a paste or Enter ends the input, so that search starts without the typing delay\n  private searchNow = false;\n  private pendingSearch?: () => void;\n\n  // Other variables\n  hasFocus = true;\n\n  constructor(\n    private router: Router,\n    private eventAggregator: EventAggregator,\n    private appConfig: AppConfig\n  ) {\n    this.eventAggregator.subscribeOnce(TKEvent.userSettingsLoaded, () => {\n      if (this.type === undefined)\n        this.type = this.appConfig.userSettings.defaultSearchLimitation;\n    });\n    this.eventAggregator.subscribe(\n      \"router:navigation:success\",\n      (event: {\n        instruction: NavigationInstruction;\n        result: PipelineResult;\n      }) => {\n        const currentRoute = event.instruction.config.name;\n        const currentParams = event.instruction.params;\n\n        this.updateFromRoute(currentRoute, currentParams);\n      }\n    );\n  }\n\n  activate() {\n    const instruction = this.router.currentInstruction.getAllInstructions()[0];\n    this.updateFromRoute(instruction.config.name, instruction.params);\n  }\n\n  // #region Observables\n\n  queryChanged(newQuery: string, oldQuery: string) {\n    // A paste only shortens the wait for the change it caused\n    const searchNow = this.searchNow;\n    this.searchNow = false;\n\n    // value is set from undefined to something for the first time\n    if (oldQuery === undefined)\n      return;\n\n    const query = newQuery.trim();\n    clearTimeout(this.searchTimer);\n    this.pendingSearch = undefined;\n\n    if (query.length == 0) {\n      if (this.router.currentInstruction.config.name == \"searchResult\")\n        this.router.navigateToRoute(\"home\");\n\n      return;\n    }\n\n    if (query.length < 3)\n      return;\n\n    this.page = 1; // if the query changes, we want to make sure the page is reset\n    this.delayedSearch(query, this.page, this.type, this.extendedSearch, searchNow);\n  }\n\n  typeChanged(newType: SearchType, oldType: SearchType) {\n    if (oldType === undefined)\n      return;\n\n    this.delayedSearch(this.query, this.page, newType,  this.extendedSearch);\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  delayedSearch(query: string, page: number, type: SearchType, extendedSearch: boolean, now = false) {\n    if (query.length < 3) return;\n\n    clearTimeout(this.searchTimer);\n    const run = () => {\n      this.pendingSearch = undefined;\n      this.search(query, page, type, extendedSearch);\n    };\n    this.pendingSearch = run;\n\n    if (now) {\n      run();\n      return;\n    }\n    this.searchTimer = setTimeout(run, this.searchDelayMilliseconds);\n  }\n\n  // Set before the input event that carries the pasted text. Returns true so the paste happens.\n  pasted() {\n    this.searchNow = true;\n    return true;\n  }\n\n  // Enter runs the waiting search now. Returns true so typing is not cancelled.\n  keyDown(event: KeyboardEvent) {\n    if (event.key === \"Enter\" && this.pendingSearch) {\n      clearTimeout(this.searchTimer);\n      this.pendingSearch();\n    }\n    return true;\n  }\n\n  search(query: string, page: number, type: SearchType, extendedSearch:  boolean) {\n    // SAL-343: checked when the timer fires, for query and type changes alike. The route already\n    // shows this search (e.g. an OE code clicked on a product page set both); navigating again\n    // would make the router deactivate the search page and abort its running request.\n    const instruction = this.router.currentInstruction;\n    if (!shouldNavigateForQuery(instruction?.config?.name, this.routeQuery(instruction?.params), query, instruction?.params?.type, type))\n      return;\n\n    this.router.navigateToRoute(\"searchResult\", {\n      query: encodeSearchRouteQuery(query),\n      page: page,\n      type: type,\n      extendedSearch: extendedSearch,\n    });\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  private routeQuery(params: any): string | undefined {\n    if (!params || params.query === undefined) return undefined;\n    return decodeSearchRouteQuery(params.query);\n  }\n\n  updateFromRoute(currentRoute: string | undefined, currentParams: any) {\n    if (!currentRoute)\n      return;\n\n    if (currentRoute == \"searchResult\" || currentRoute == \"carVehiclesQuery\") {\n      this.query = decodeSearchRouteQuery(currentParams.query);\n      // make sure these are numbers\n      this.page = parseInt(currentParams.page ?? \"1\");\n      this.type = parseInt(currentParams.type ?? SearchType.All);\n    } else {\n      this.query = \"\";\n\n      if (currentRoute == \"home\") this.hasFocus = true;\n    }\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n  <div class=\\\"input-group sticky-top search-box py-1\\\">\\n    <compose view-model=\\\"components/product/search/categories\\\"></compose>\\n\\n    <i class=\\\"bi-search input-group-text\\\"></i>\\n    <input\\n      id=\\\"search-bar\\\"\\n      focus.bind=\\\"hasFocus\\\"\\n      type=\\\"search\\\"\\n      minlength=\\\"3\\\"\\n      class=\\\"form-control w-50\\\"\\n      placeholder=\\\"${'components.search-bar.hint' & t}\\\"\\n      value.bind=\\\"query\\\"\\n      paste.trigger=\\\"pasted()\\\"\\n      keydown.trigger=\\\"keyDown($event)\\\" />\\n\\n    <select class=\\\"form-select\\\" value.bind=\\\"type\\\">\\n      <option model.bind=\\\"0\\\">${'components.search-bar.types.all' & t}</option>\\n      <option model.bind=\\\"1\\\">${'components.search-bar.types.code' & t}</option>\\n      <option model.bind=\\\"2\\\">${'components.search-bar.types.name' & t}</option>\\n      <option model.bind=\\\"3\\\">${'components.search-bar.types.tecdoc' & t}</option>\\n      <option model.bind=\\\"4\\\">${'components.search-bar.types.ean' & t}</option>\\n      <option model.bind=\\\"5\\\">${'components.search-bar.types.precise' & t}</option>\\n    </select>\\n\\n    <!--If this breaks, add width-inital to style.css (input.group.fix)-->\\n    <compose view-model=\\\"components/car/car-tree\\\"></compose>\\n  </div>\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { Router } from \"aurelia-router\";\nimport { IRvsOrder } from \"domain/Sale/IRvsOrder\";\nimport { LogManager, autoinject, bindable } from \"aurelia-framework\";\nimport $ from \"jquery\";\nimport \"bootstrap\";\nimport { OrderService } from \"services/sale/order-service\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { Collapse } from \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.components.order-list\");\n\n@autoinject\nexport class OrderListCustomElement {\n  @bindable orders: IRvsOrder[];\n\n  options = {\n    showInvoiceId: false,\n    showWarehouse: false,\n    showTransport: false,\n    showAddToCart: true,\n    showAddToReturn: true,\n    showConvertToCart: true,\n  };\n\n  constructor(\n    private orderService: OrderService,\n    private eventAggregator: EventAggregator,\n    private router: Router,\n    private i18n: I18N\n  ) {}\n\n  attached() {\n    this.orders.forEach((order) => {\n      order.originalId = order.originalId.replace(\"*INTERNET*\", \"\");\n    });\n  }\n\n  convertToCart(order: IRvsOrder) {\n    this.orderService\n      .convertRvsOrderToCart(order.id)\n      .then(() => {\n        this.eventAggregator.publish(TKEvent.cartProductsChanged);\n        Utils.showSuccessToast(\n          this.i18n.tr(\"pages.orders.messages.convert-to-cart\")\n        );\n      })\n      .catch((error) =>\n        Utils.showErrorToast(\n          log,\n          Utils.getErrorMessage(error, this.i18n)\n        )\n      );\n  }\n\n  toggleProductList(target: HTMLElement, order: IRvsOrder) {\n    $(() => {\n      // Check if child element was clicked instead\n      if (\n        $(target).prop(\"tagName\") != \"TD\" &&\n        $(target).prop(\"tagName\") != \"TR\"\n      )\n        return;\n\n      const productListElement = document.querySelector(\n        `[data-product-list=\"${order.id}\"]`\n      );\n      if (productListElement)\n        new Collapse(productListElement, {\n          parent: \"#accordion-order\",\n        }).toggle();\n    });\n  }\n\n  canConvertToCart(order: IRvsOrder): boolean {\n    return order.products.some((p) => Number(p.amount) > 0);\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/mobile-cards\\\"></require>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"components/cart/nested-cart-product-list\\\"></require>\\n\\n  <table mobile-cards id=\\\"accordion-order\\\" class=\\\"table w-100\\\">\\n    <thead>\\n      <tr>\\n        <th>${'pages.orders.headers.number' & t}</th>\\n        <th>${'pages.orders.headers.original-number' & t}</th>\\n        <th>${'pages.orders.headers.comments' & t}</th>\\n        <th class=\\\"text-end\\\">${'pages.orders.headers.total' & t}</th>\\n        <th class=\\\"text-end\\\" if.bind=\\\"options.showConvertToCart\\\">\\n          ${'components.products.headers.add-to-cart' & t}\\n        </th>\\n      </tr>\\n    </thead>\\n\\n    <tbody repeat.for=\\\"order of orders\\\" class=\\\"hover\\\">\\n      <tr class=\\\"clickable\\\" click.delegate=\\\"toggleProductList($event.target, order)\\\">\\n        <td><span>${order.id}</span></td>\\n        <td><span>${order.originalId}</span></td>\\n        <td><span>${order.comment}</span></td>\\n        <td class=\\\"text-end\\\" data-value.bind=\\\"order.total\\\">\\n          <span>${order.total | currencyFormat}</span>\\n        </td>\\n        <td class=\\\"text-end clickable mc-action\\\" if.bind=\\\"options.showConvertToCart\\\">\\n          <button\\n            if.bind=\\\"canConvertToCart(order)\\\"\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-success btn-sm\\\"\\n            click.delegate=\\\"convertToCart(order)\\\">\\n            ${'components.products.buttons.add-to-cart' & t}\\n          </button>\\n        </td>\\n      </tr>\\n\\n      <tr class=\\\"product-list-row hover\\\" data-disablesort=\\\"true\\\" data-order.bind=\\\"order.id\\\">\\n        <td colspan=\\\"7\\\" class=\\\"p-0\\\">\\n          <div\\n            class=\\\"collapse px-5\\\"\\n            data-product-list.bind=\\\"order.id\\\"\\n            data-bs-parent=\\\"#accordion-order\\\">\\n            <nested-cart-product-list\\n              products.bind=\\\"order.products\\\"\\n              rvs-order.bind=\\\"order\\\"\\n              options.bind=\\\"options\\\">\\n            </nested-cart-product-list>\\n          </div>\\n        </td>\\n      </tr>\\n    </tbody>\\n  </table>\\n</template>\\n\";","import { bindable } from 'aurelia-framework';\n\nexport class OrderSearchBarCustomElement {\n  @bindable searchIcon: string;\n  @bindable searchPlaceholder: string;\n\n  @bindable searchText: string;\n  @bindable searchDateFrom: string;\n  @bindable searchDateTo: string;\n\n  hasFocus = true;\n}\n","module.exports = \"<template>\\n  <div class=\\\"input-group mb-2 order-search-bar\\\">\\n    <i class='bi-search input-group-text'></i>\\n    <i class='bi-${searchIcon} input-group-text'></i>\\n\\n    <input focus.bind=\\\"hasFocus\\\" type=\\\"text\\\" class=\\\"form-control\\\"\\n           placeholder.bind=\\\"searchPlaceholder\\\" value.two-way=\\\"searchText\\\">\\n\\n    <i class='bi-calendar-range input-group-text'></i>\\n    <input type=\\\"date\\\" class=\\\"form-control\\\" value.two-way=\\\"searchDateFrom\\\" placeholder=\\\"yyyy-mm-dd\\\"\\n           pattern=\\\"^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9])$\\\">\\n\\n    <i class='bi-three-dots input-group-text'></i>\\n    <input type=\\\"date\\\" class=\\\"form-control\\\" value.two-way=\\\"searchDateTo\\\" placeholder=\\\"yyyy-mm-dd\\\"\\n           pattern=\\\"^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9])$\\\">\\n  </div>\\n</template>\\n\";"],"sourceRoot":""}