{"version":3,"sources":["webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/develop/src/components/product/brand-filter.ts","webpack:///./src/components/product/brand-filter.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/develop/src/components/product/filter-value-order.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/develop/src/components/product/product-filter.ts","webpack:///./src/components/product/product-filter.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/develop/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/develop/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/develop/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/develop/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/develop/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/develop/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/develop/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/develop/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/develop/src/components/product/search/categories.ts","webpack:///./src/components/product/search/categories.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/develop/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/develop/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/develop/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","error","warn","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","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","off","each","attr","insertAfter","formatProductsPrices","pageHasEANChecker","pageHasBrandChecker","pageHasInPackageChecker","resetConditionalColumnRendering","activateExtendedSearch","extendedSearch","cat","ProductListCustomElement","reportText","sending","sendProductReport","postReportError","modalEl","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.9dffd8b5d86da4601b72.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 { LogManager, autoinject, bindable } from 'aurelia-framework';\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\n\nconst log = LogManager.getLogger('app.components.copy-to-clipboard');\n\n@autoinject\nexport class CopyToClipboardCustomElement {\n  @bindable text: string;\n\n  constructor(\n    private i18n: I18N\n  ) {}\n  \n  copyToClipboard() {\n    // Only confirm a copy that happened; the clipboard is refused outside a secure context.\n    navigator.clipboard?.writeText(this.text)\n      .then(() => Utils.showSuccessToast(this.i18n.tr('components.products.messages.code-copied-to-clipboard')))\n      .catch(error => log.warn('Copy to clipboard failed', error));\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=\\\"d-block text-muted small mx-1 d-lg-none\\\">\\n            ${'components.products.headers.ean' & t}:\\n            <b>${product.ean}</b>\\n          </span>\\n          <span if.bind=\\\"product.inPackage\\\" class=\\\"d-block 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\").off(\"sorted.products\").on(\"sorted.products\", 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=\\\"fst-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=\\\"text-nowrap 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\";\nimport { Modal } from \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.components.report-button\");\n\n@autoinject\nexport class ReportButtonCustomElement {\n  @bindable product: IProduct;\n  reportText = \"\";\n  sending = false;\n  private modalEl!: HTMLElement;\n\n  constructor(private i18n: I18N, private productService: ProductService) {}\n\n  sendProductReport(product: IProduct, reportText: string) {\n    if (this.sending || !reportText?.trim()) return;\n\n    this.sending = true;\n    this.productService\n      .postReportError(product.code, reportText, product.id)\n      .then(() => {\n        Modal.getOrCreateInstance(this.modalEl).hide();\n        this.reportText = \"\";\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      .finally(() => (this.sending = false));\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\\\" ref=\\\"modalEl\\\">\\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            disabled.bind=\\\"sending || !reportText || !reportText.trim()\\\"\\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 fw-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 align-middle\\\">\\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":""}