{"version":3,"sources":["webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Sale/OrderTotal.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Cart/CartLinePayload.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Cart/CartExternalStock.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Cart/TransportSelection.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Cart/CartProductUpdate.ts","webpack:///./src/locales/en_GB.json?78d9","webpack:///./src/locales/et_EE.json?1dfc","webpack:///./src/locales/fi_FI.json?5092","webpack:///./src/locales/ru_RU.json?b7c1","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/brand-filter.ts","webpack:///./src/components/product/brand-filter.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/filter-value-order.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-filter.ts","webpack:///./src/components/product/product-filter.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/add-to-cart.ts","webpack:///./src/components/product/product-list/add-to-cart.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/copy-to-clipboard.ts","webpack:///./src/components/product/product-list/copy-to-clipboard.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/extra-row.ts","webpack:///./src/components/product/product-list/extra-row.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/gallery.ts","webpack:///./src/components/product/product-list/gallery.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/price.ts","webpack:///./src/components/product/product-list/price.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/product-list.ts","webpack:///./src/components/product/product-list/product-list.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/report-button.ts","webpack:///./src/components/product/product-list/report-button.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/product-list/stock.ts","webpack:///./src/components/product/product-list/stock.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/search/categories.ts","webpack:///./src/components/product/search/categories.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/product/search/search-bar.ts","webpack:///./src/components/product/search/search-bar.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/sale/order/order-list.ts","webpack:///./src/components/sale/order/order-list.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/sale/order/order-search-bar.ts","webpack:///./src/components/sale/order/order-search-bar.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/sale/return/index.ts","webpack:///./src/components/sale/return/index.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/components/sale/return/list.ts","webpack:///./src/components/sale/return/list.html","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Cart/Origin.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Product/PriceDisplay.ts","webpack:///src/var/www/virtualhost/client.tk.salome.ee/www/master/src/domain/Cart/CartBadge.ts"],"names":["activeOrderLines","products","Array","isArray","filter","p","removedDateTime","orderTotal","reduce","sum","Number","finalPrice","quantity","buildCartLinePayload","product","payload","externalWarehouseId","warehouseId","hasValidWarehouse","retainCartLineOffer","hasTkItem","externalStock","stored","stock","find","x","warehouse","id","groupId","findStoredExternalOffer","selectedStock","contractTransportAddresses","contractSettings","addresses","otherTransportAddresses","linesToPreselect","transportId","isExternalStock","flag","isExternal","buildCartProductUpdate","cartProductId","foundBy","code","parseInt","toString","comment","fallbackStock","pickExternalStock","fallback","undefined","isStoredSupplierMissing","usesStoredPrice","lineUnitPrice","displayPrice","lineTotalWithoutVat","wholesaleType","wholesale","prices","price","type","withoutVat","ORDER_REFUSAL_CODES","orderRefusalText","body","tr","parsed","JSON","parse","trim","errors","parts","map","e","includes","productCode","message","t","length","join","errorValueText","parseErrorBody","text","test","startsWith","value","v","o","detail","errs","Object","values","title","submitErrorMessage","headline","reason","escaped","replace","module","exports","cb","require","log","getLogger","chosenBrands","uid","instanceCount","brandSearch","BrandFilterCustomElement","resetView","this","toggleButton","getOrCreateInstance","hide","possibleBrands","term","toLowerCase","brand","openDropdown","load","isChosen","indexOf","toggleBrand","chosen","notifyChanged","resetChosenBrands","changed","brands","defaultBindingMode","twoWay","compareNumericSize","a","b","left","String","right","leftNumber","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","sorted","has","slice","sort","areAllNumbers","some","index","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","target","noUiSlider","chosenMin","chosenMax","options","set","isFilterValueChosen","chosenValue","areFilterValuesEqual","isFilterValueDisabled","isOptionDisabled","isFilterValueLocked","pending","isOptionLocked","firstValue","secondValue","filterBadge","getElementByKey","keyName","translateKey","displayText","translateBadgeValues","innerText","style","display","split","part","translateValue","filterValueLabel","filterEntries","seasonEntries","nested","element","getElementById","i","children","child","nodeName","clearElement","clearFilterBadge","innerHTML","HTMLInputElement","applySeasonFamily","classList","contains","getSliderFilterValues","getCheckboxFilterValues","updateChosenFilters","chosenValues","get","push","clicked","boxes","from","available","box","selected","checked","next","seasonChoice","checkedBoxes","publishChosenFiltersChanged","removeSliders","getElementsByClassName","destroy","publish","TKEvent","chosenFiltersChanged","ProductFilterCustomElement","rowSequence","cartProductService","appConfig","rowUid","currencyFormat","gate","getUniqueProductId","source","tryAddToCart","ensureValidMinimumQuantity","busy","cartWarningNeeded","confirmModalEl","requestConfirm","show","addToCart","confirmAddToCart","takeConfirm","cancelConfirm","toCartQuantity","buttons","addToCartButtonEl","addToCartWarnButtonEl","begin","disabled","post","getRequestData","then","showSuccessToast","cartProductsChanged","catch","showErrorToast","finally","end","getMinimumQuantity","showsMinimumQuantityHint","isValidMinimumQuantity","data","isExternalWarehouse","otherWarehouseWarningNeeded","otherWarehouseIdWarningNeeded","userWarehouseId","userSettings","externalWarehouseGroupId","hasStockWarning","hasRefundableDeposit","hasExternalStockWarning","getSelectedRefundableDepositSource","getRefundableDeposit","getRefundableDepositLabel","refundableDeposit","toView","getRefundableDepositWarningText","lines","getStockWarningText","getExternalWarningGroupId","stockWarehouseId","getWarehouseWarningId","AddToCartCustomElement","Element","copyToClipboard","navigator","clipboard","writeText","CopyToClipboardCustomElement","router","bindingEngine","oeNumberTree","oeNumbersSubscription","subscribeToOeNumbers","buildOeNumberTree","detached","disposeOeNumbersSubscription","productChanged","propertyObserver","subscribe","dispose","oeNumbers","manufacturerIndex","manufacturer","name","oeNumber","oeNumberIndex","query","infoLabel","info","translateInfoPair","infoValue","infoHref","openDocument","productId","win","window","open","apiUrl","focus","showGallery","loadVehicle","navigateToRoute","vehicleId","searchOeNumber","page","TecDoc","searchOeTreeItem","ExtraRowCustomElement","priceTooltip","pricesToTooltip","bind","updateRefundableDepositInfo","pricesChanged","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","vehicleIdChanged","loadInfo","loadImagesWithCategory","loadSortables","moveRowsListener","detailsInProductPage","imagesInProductPage","renderColumnsConditionally","getWarehouses","formatStockPrices","fillDefaultSelectedStock","loadExternalStock","isPositive","highlightSearchQuery","loadThumbnail","loadImages","remove","append","addClass","Promise","resolve","result","debug","imageLoadingCount","fetchThumbnail","thumbnailVersion","thumbnail","error","handleRequestNoise","getErrorMessage","thumbnailFailed","thumbnailLoaded","trigger","closest","getInstance","content","html","fetchImages","images","concat","fetchImagesWithCategory","oldVehicleId","fetchInfoWithCategory","fetchInfoWithCar","fetchInfo","isArrayEmpty","extractEanFromInfo","loadDescription","oldCategoryId","fetchDescriptionWithCategory","fetchDescription","description","afterLoading","loadDocuments","fetchDocumentsWithCategory","fetchDocuments","documents","loadOeNumbers","fetchOeNumbers","isObjectEmpty","loadCars","fetchCars","cars","existingExternalStock","fetchExternalStock","preserveExternalStockRefundableDeposit","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","classToRemove","removeClass","isUserToggle","extraRow","querySelector","parent","toggle","each","attr","insertAfter","formatProductsPrices","pageHasEANChecker","pageHasBrandChecker","pageHasInPackageChecker","resetConditionalColumnRendering","activateExtendedSearch","extendedSearch","cat","ProductListCustomElement","sendProductReport","reportText","postReportError","ReportButtonCustomElement","getValue","takeIntoStockUserWish","confirm","postProductStockRequest","getStockQuantity","updateStockFromWarehouse","updateStock","isAllowed","snapToCartQuantityToMinimum","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","hasFocus","subscribeOnce","defaultSearchLimitation","currentRoute","currentParams","params","updateFromRoute","currentInstruction","getAllInstructions","queryChanged","newQuery","oldQuery","clearTimeout","searchTimer","delayedSearch","typeChanged","newType","oldType","that","setTimeout","search","routeQuery","All","SearchBar","orderService","showInvoiceId","showWarehouse","showTransport","showAddToReturn","showConvertToCart","orders","order","originalId","convertToCart","convertRvsOrderToCart","toggleProductList","productListElement","canConvertToCart","amount","OrderListCustomElement","returnService","searchText","searchDateFrom","searchDateTo","totalWithoutVat","totalVat","totalWithVat","showEan","showStock","showReason","showDisplayPrice","isReturnCart","updateTotal","returnCartChanged","cart","returnCart","loadReturn","round","vatRate","dateRegex","match","encode","dateFrom","dateTo","fetchCurrent","sendReturn","cancel","updatedCart","returnId","returnSent","printMessage","clearReturn","clearReturnCart","fetchReturnText","printable","changeHandler","ReturnIndexCustomElement","loadReturns","returns","fetchReturns","items","closedDateTime","Date","total","sortedListener","loadSortable","searchProduct","Precise","collapseElement","loading","ReturnListCustomElement","Origin","isExternalProduct","origin","hasStoredOrigin","Factory","Partner","getExternalGroupId","AmountDiscount","AmountDiscountList","cartLinePrices","cartTotalWithoutVat","num","count","version","beginFetch","acceptFetch","token","mergeCartLines","current","old","byId","Map","merged","line","assign"],"mappings":"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","file":"app~21833f8f.1589aa8f62f1c2aa13c7.chunk.js","sourcesContent":["// SAL-283 r7: the order list must render even if an order comes back with odd lines (no products list,\n// a removed line, a line without price, quantity or transport). The total counts active lines only.\ntype OrderLine =\n  | {\n      finalPrice?: number | null;\n      quantity?: number | null;\n      removedDateTime?: string | null;\n    }\n  | null\n  | undefined;\n\nexport function activeOrderLines<T extends OrderLine>(\n  products: T[] | null | undefined,\n): NonNullable<T>[] {\n  if (!Array.isArray(products)) return [];\n  return products.filter(p => p != null && !p.removedDateTime) as NonNullable<T>[];\n}\n\nexport function orderTotal(products: OrderLine[] | null | undefined): number {\n  return activeOrderLines(products).reduce(\n    (sum, p) => sum + (Number(p.finalPrice) || 0) * (Number(p.quantity) || 0),\n    0,\n  );\n}\n","// SAL-315: one place that turns a cart line into the PUT /CartProduct payload.\n// A line must be either a local warehouse (warehouseId > 0) or an external offer\n// (warehouseId 0 + externalWarehouseId). The UI-only -1 \"external\" group id must never be sent.\nimport { buildCartProductUpdate, CartLineForUpdate } from \"./CartProductUpdate\";\nimport { isExternalProduct } from \"./Origin\";\n\n// The cart line as SAL-283 reads it (stored origin, selected and fallback stock rows).\nexport type CartLinePayloadSource = CartLineForUpdate;\n\n/**\n * Returns the payload, or null when the line has no valid warehouse and must not be saved.\n * SAL-283 decides the move (stored origin, fallback rows); this only refuses what fits no destination.\n */\nexport function buildCartLinePayload(product: CartLinePayloadSource): any | null {\n  const payload: any = buildCartProductUpdate(product);\n  if (payload.externalWarehouseId || payload.warehouseId > 0) return payload;\n\n  if (isExternalProduct(product) && product.externalWarehouseId) {\n    // External line whose offer was not (re)loaded: keep the saved offer; the server\n    // rejects it if that offer is gone, so nothing invalid is persisted.\n    payload.warehouseId = 0;\n    payload.externalWarehouseId = product.externalWarehouseId;\n    return payload;\n  }\n  return null;\n}\n\n/** True when the line can be ordered: a local warehouse or a saved external offer. */\nexport function hasValidWarehouse(product: CartLinePayloadSource): boolean {\n  if (product.externalWarehouseId) return true;\n  return (product.warehouseId ?? 0) > 0;\n}\n","import { ICartProduct } from \"domain/Cart/ICartProduct\";\nimport { IStockItem } from \"domain/Product/IStockItem\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\n\n/**\n * The offer saved on the cart line. Same order as the cart page has always used\n * for a line that does have a TK item: the stored warehouse, then a partner row,\n * then a factory row, then whatever is left.\n */\nexport function findStoredExternalOffer(product: {\n  externalWarehouseId?: number | null;\n  externalStock?: IStockItem[] | null;\n}): IStockItem | undefined {\n  if (!product.externalWarehouseId) return undefined;\n\n  const stock = product.externalStock ?? [];\n  return (\n    stock.find(x => x.warehouse.id === product.externalWarehouseId) ||\n    stock.find(x => Number(x.warehouse.groupId) === 2) ||\n    stock.find(x => Number(x.warehouse.groupId) === 1) ||\n    stock[0]\n  );\n}\n\n/**\n * A partner line with no TK item. There is no item id to ask ExternalStock for;\n * the cart response already carries the offer. Returns true when that request\n * must be skipped. Preselects the stored offer when one is present.\n */\nexport function retainCartLineOffer(product: ICartProduct): boolean {\n  if (ProductExtraHelper.hasTkItem(product)) return false;\n\n  product.externalStock = product.externalStock ?? [];\n  const stored = findStoredExternalOffer(product);\n  if (stored) product.selectedStock = stored;\n  return true;\n}\n","// SAL-283 r9: transport selection helpers (no framework imports, unit-tested).\n\n/** The contract's extra delivery addresses; empty until the user's settings are loaded. */\nexport function contractTransportAddresses(\n  contractSettings: { otherTransportAddresses?: string[] | null } | null | undefined,\n): string[] {\n  const addresses = contractSettings?.otherTransportAddresses;\n  return Array.isArray(addresses) ? addresses : [];\n}\n\n/** Lines whose transport differs from the only allowed option: these must be set AND saved. */\nexport function linesToPreselect<T extends { transportId?: string | number | null }>(\n  products: T[] | null | undefined,\n  transportId: string,\n): T[] {\n  return (products ?? []).filter(p => p != null && `${p.transportId ?? \"0\"}` !== `${transportId}`);\n}\n","import { isExternalProduct, getExternalGroupId } from \"./Origin\";\n\n// SAL-283: the cart line payload is built in one place. Whether a line is external comes from the\n// stored origin; the selected stock row only says where the user wants the line moved.\n\ntype StockChoice = {\n  warehouse?: { id?: number; isExternal?: unknown; groupId?: unknown } | null;\n} | null | undefined;\n\nexport type CartLineForUpdate = {\n  cartProductId?: number;\n  foundBy?: string;\n  code: string;\n  quantity: number | string;\n  comment?: string;\n  warehouseId?: number;\n  externalWarehouseId?: number;\n  externalWarehouseGroupId?: number;\n  origin?: number | null;\n  transportId?: string;\n  selectedStock?: StockChoice;\n  // Stock row picked automatically because the stored supplier is not in the list (e.g. a\n  // cheaper supplier now heads its group). Keeping it selected must not move the line.\n  fallbackStock?: StockChoice;\n};\n\nexport function isExternalStock(stock: StockChoice): boolean {\n  const flag = stock?.warehouse?.isExternal as unknown;\n  return flag === true || flag === \"true\" || flag === 1 || flag === \"1\";\n}\n\nexport function buildCartProductUpdate(product: CartLineForUpdate) {\n  const payload: {\n    cartProductId: number;\n    foundBy?: string;\n    code: string;\n    quantity: number;\n    comment?: string;\n    warehouseId: number;\n    externalWarehouseId?: number;\n    transportId: number;\n  } = {\n    cartProductId: product.cartProductId ?? 0,\n    foundBy: product.foundBy,\n    code: product.code,\n    quantity: parseInt(product.quantity.toString()),\n    comment: product.comment,\n    warehouseId: product.selectedStock?.warehouse?.id ?? product.warehouseId ?? 0,\n    transportId: parseInt(product.transportId ?? \"0\"),\n  };\n\n  // A fallback row, or (SAL-283 QA r6) no row at all, keeps the stored supplier: never a move.\n  const keepsStoredSupplier =\n    isExternalProduct(product) &&\n    (!product.selectedStock || (!!product.fallbackStock && product.selectedStock === product.fallbackStock));\n\n  if (keepsStoredSupplier) {\n    payload.warehouseId = 0;\n    payload.externalWarehouseId = product.externalWarehouseId;\n  } else if (isExternalStock(product.selectedStock)) {\n    payload.warehouseId = 0;\n    payload.externalWarehouseId = product.selectedStock?.warehouse?.id;\n  }\n\n  return payload;\n}\n\n/**\n * Picks the stock row shown for an external cart line: the stored supplier when listed, otherwise\n * a row of the same group, then partner, factory, first. Returns the row and whether it is a fallback.\n */\nexport function pickExternalStock<T extends { warehouse: { id?: number; groupId?: unknown } }>(\n  product: { externalWarehouseId?: number; externalWarehouseGroupId?: number; origin?: number | null },\n  externalStock: T[],\n): { stock: T | undefined; fallback: boolean } {\n  const stored = externalStock.find(x => x.warehouse.id === product.externalWarehouseId);\n  if (stored) return { stock: stored, fallback: false };\n\n  const groupId = getExternalGroupId(product);\n  const stock =\n    (groupId !== undefined ? externalStock.find(x => Number(x.warehouse.groupId) === groupId) : undefined) ||\n    externalStock.find(x => Number(x.warehouse.groupId) === 2) ||\n    externalStock.find(x => Number(x.warehouse.groupId) === 1) ||\n    externalStock[0];\n  return { stock, fallback: stock !== undefined };\n}\n\ntype PricedLine = CartLineForUpdate & {\n  finalPrice?: number | null;\n  selectedStock?: (StockChoice & { displayPrice?: number | null; prices?: { type?: unknown; withoutVat?: number | null }[] }) | null;\n};\n\n/**\n * QA 5b: the stored supplier is no longer listed (e.g. its amount went to 0) and the row shown is\n * only an automatic fallback. The line still holds the stored offer until the user picks another\n * warehouse, so it keeps the stored snapshot price (finalPrice), the same price the header shows.\n */\nexport function isStoredSupplierMissing(product: PricedLine): boolean {\n  return !!product.fallbackStock && product.selectedStock === product.fallbackStock && isExternalProduct(product);\n}\n\n/**\n * SAL-283 review: an external line is charged its stored line price (finalPrice). The server keeps it on\n * the cheapest supplier of its group and re-prices it at least daily, so the shown row's live price can\n * differ for up to 24h; the line, the page total, the header badge and the order use finalPrice.\n */\nfunction usesStoredPrice(product: PricedLine): boolean {\n  return (\n    isExternalProduct(product) &&\n    product.finalPrice !== undefined &&\n    product.finalPrice !== null &&\n    product.selectedStock?.warehouse?.id === product.externalWarehouseId\n  );\n}\n\n/** Unit price shown on the cart line. */\nexport function lineUnitPrice(product: PricedLine): number | null {\n  if (usesStoredPrice(product) || isStoredSupplierMissing(product)) return product.finalPrice ?? null;\n  // SAL-283 QA r5: while a reloaded line has no stock row picked yet, keep its stored price on screen.\n  if (!product.selectedStock) return product.finalPrice ?? null;\n  return product.selectedStock.displayPrice ?? product.finalPrice ?? null;\n}\n\n/** Line total without VAT for the cart page total; matches the header badge for an external line. */\nexport function lineTotalWithoutVat(product: PricedLine, wholesaleType: unknown): number {\n  const quantity = Number(product.quantity) || 0;\n  if (usesStoredPrice(product) || isStoredSupplierMissing(product)) return (product.finalPrice ?? 0) * quantity;\n  const wholesale = product.selectedStock?.prices?.find(price => price.type == wholesaleType);\n  if (wholesale) return (wholesale.withoutVat ?? 0) * quantity;\n  // No stock row loaded (e.g. the plain cart behind the header badge): the stored line price.\n  return (product.finalPrice ?? 0) * quantity;\n}\n\nexport type Translate = (key: string, params?: Record<string, unknown>) => string;\n\n/** Refusal reason codes PlaceOrder sends (TKCore OrderRefusedException), translated under this key. */\nexport const ORDER_REFUSAL_CODES = [\"PriceChanged\", \"ExternalStockUnavailable\"] as const;\nexport const ORDER_REFUSAL_I18N_PREFIX = \"pages.cart.errors.order.\";\n\n/**\n * SAL-283: the PlaceOrder refusal body {code: \"OrderRefused\", message, errors: [{code, productCode,\n * message}]} in the user's language (same mechanism as the login error codes). A reason without a\n * known code keeps the server text. Returns null when the body is not such a refusal.\n */\nexport function orderRefusalText(body: string | null | undefined, tr: Translate): string | null {\n  let parsed: any;\n  try {\n    parsed = JSON.parse((body ?? \"\").trim());\n  } catch {\n    return null;\n  }\n  if (!parsed || typeof parsed !== \"object\" || parsed.code !== \"OrderRefused\" || !Array.isArray(parsed.errors))\n    return null;\n  const parts = parsed.errors\n    .map((e: any) => {\n      if (e && (ORDER_REFUSAL_CODES as readonly string[]).includes(e.code) && e.productCode)\n        return tr(ORDER_REFUSAL_I18N_PREFIX + e.code, { code: e.productCode });\n      return typeof e?.message === \"string\" ? e.message.trim() : \"\";\n    })\n    .filter((t: string) => !!t);\n  return parts.length ? parts.join(\" \") : errorValueText(parsed.message);\n}\n\n/** Body text of a failed response: ASP.NET BadRequest(string) sends a plain or JSON-quoted string. */\nexport function parseErrorBody(body: string | null | undefined): string | null {\n  const text = (body ?? \"\").trim();\n  if (!text) return null;\n  if (!/^[\"{\\[]/.test(text)) return text;\n  try {\n    return errorValueText(JSON.parse(text));\n  } catch {\n    return text.startsWith('\"') ? text : null;\n  }\n}\n\n/** Text of a parsed error body: a string, an array of strings, or ProblemDetails (detail/title/errors). */\nfunction errorValueText(value: unknown): string | null {\n  if (typeof value === \"string\") return value.trim() || null;\n  if (Array.isArray(value)) {\n    const parts = value.map(errorValueText).filter((v): v is string => !!v);\n    return parts.length ? parts.join(\" \") : null;\n  }\n  if (value && typeof value === \"object\") {\n    const o = value as Record<string, unknown>;\n    const detail = errorValueText(o.detail) ?? errorValueText(o.message);\n    if (detail) return detail;\n    if (o.errors && typeof o.errors === \"object\") {\n      const errs = errorValueText(Array.isArray(o.errors) ? o.errors : Object.values(o.errors));\n      if (errs) return errs;\n    }\n    return errorValueText(o.title);\n  }\n  return null;\n}\n\n/** Order submit error: the translated headline plus the server's reason when there is one. */\nexport function submitErrorMessage(headline: string, reason: string | null | undefined): string {\n  const escaped = (reason ?? \"\").replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n  return escaped ? `${headline}<br>${escaped}` : headline;\n}\n","module.exports = function(cb) {\n\trequire.ensure([], function(require) {\n\t\tcb(require(\"!!../../node_modules/json-loader/index.js!./en_GB.json\"));\n\t}, \"lang-en_GB\");\n}","module.exports = function(cb) {\n\trequire.ensure([], function(require) {\n\t\tcb(require(\"!!../../node_modules/json-loader/index.js!./et_EE.json\"));\n\t}, \"lang-et_EE\");\n}","module.exports = function(cb) {\n\trequire.ensure([], function(require) {\n\t\tcb(require(\"!!../../node_modules/json-loader/index.js!./fi_FI.json\"));\n\t}, \"lang-fi_FI\");\n}","module.exports = function(cb) {\n\trequire.ensure([], function(require) {\n\t\tcb(require(\"!!../../node_modules/json-loader/index.js!./ru_RU.json\"));\n\t}, \"lang-ru_RU\");\n}","import { LogManager, autoinject, bindable, bindingMode, computedFrom } from \"aurelia-framework\";\nimport { Dropdown } from \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.components.brand-filter\");\n\n@autoinject\nexport class BrandFilterCustomElement {\n  // undefined = not loaded yet (spinner shown while the dropdown is open)\n  @bindable possibleBrands?: string[];\n  @bindable({ defaultBindingMode: bindingMode.twoWay }) chosenBrands: string[] = [];\n  @bindable load: () => void;\n  // The two-way chosenBrands binding only propagates to the parent as a microtask,\n  // so the fresh selection is also passed directly as a call argument.\n  @bindable changed: (args: { brands: string[] }) => void;\n\n  // Unique per instance so checkbox label \"for\" ids can't collide if the\n  // element is ever instantiated twice on one page\n  private static instanceCount = 0;\n  uid = ++BrandFilterCustomElement.instanceCount;\n\n  brandSearch = \"\";\n  toggleButton: HTMLButtonElement;\n\n  // Called by the page when the search scope changes: the loaded brand list no\n  // longer applies, so collapse the dropdown (a dropdown left open here would\n  // keep showing the old list and reappear mispositioned) and clear the filter\n  // text. The next open fetches the new scope's list.\n  resetView() {\n    this.brandSearch = \"\";\n    if (this.toggleButton) Dropdown.getOrCreateInstance(this.toggleButton).hide();\n  }\n\n  @computedFrom(\"possibleBrands\", \"brandSearch\")\n  get filteredBrands(): string[] {\n    if (this.possibleBrands === undefined) return [];\n\n    const term = this.brandSearch.trim().toLowerCase();\n    if (term.length == 0) return this.possibleBrands;\n\n    return this.possibleBrands.filter(brand => brand.toLowerCase().includes(term));\n  }\n\n  openDropdown(): boolean {\n    if (this.load) this.load();\n\n    // Let the bootstrap dropdown toggle proceed\n    return true;\n  }\n\n  // The template passes chosenBrands as an argument so the binding re-evaluates\n  // when the array is replaced - Aurelia only observes a call's arguments.\n  isChosen(brand: string, chosenBrands: string[] = this.chosenBrands): boolean {\n    return chosenBrands.indexOf(brand) !== -1;\n  }\n\n  toggleBrand(brand: string): boolean {\n    if (this.isChosen(brand)) {\n      this.chosenBrands = this.chosenBrands.filter(chosen => chosen !== brand);\n    } else {\n      this.chosenBrands = [...this.chosenBrands, brand];\n    }\n\n    this.notifyChanged();\n\n    // Let the checkbox update itself\n    return true;\n  }\n\n  resetChosenBrands() {\n    if (this.chosenBrands.length == 0) return;\n\n    this.chosenBrands = [];\n    this.notifyChanged();\n  }\n\n  private notifyChanged() {\n    if (this.changed) this.changed({ brands: this.chosenBrands });\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"/node_modules/bootstrap-icons/font/bootstrap-icons.css\\\"></require>\\n\\n  <!-- Laid out as a full-width filter bar to match the tyre category filters\\n       (see product-filter.html): the shared \\\"Filtrid:\\\" header, a growing\\n       spacer cell that stretches the bar to full width, then the Bränd\\n       dropdown on the right. Its menu opens leftward (see the button and the\\n       #brand-filter rule in style.css) so it doesn't run off the right edge.\\n       Distance to the search bar above is 1.5rem: search-box pb (0.25rem)\\n       + main mt-3 (1rem) + pt-1 here (0.25rem). -->\\n  <div class=\\\"pt-1 pb-3 w-100\\\">\\n    <div class=\\\"input-group mx-auto\\\" id=\\\"brand-filter\\\">\\n      <span class=\\\"input-group-text\\\">${'pages.category.filters.header' & t}</span>\\n\\n      <span class=\\\"input-group-text form-control\\\"></span>\\n\\n      <div class=\\\"dropdown\\\">\\n        <!-- data-bs-display=\\\"static\\\" turns off Popper positioning for this\\n             menu; Popper aligned it to the left here (running off the right\\n             edge), so the menu is right-aligned deterministically via CSS\\n             instead (#brand-filter .dropdown-menu in style.css). -->\\n        <button class=\\\"btn btn-outline-primary dropdown-toggle\\\" type=\\\"button\\\" ref=\\\"toggleButton\\\"\\n                data-bs-toggle=\\\"dropdown\\\" data-bs-auto-close=\\\"outside\\\" data-bs-display=\\\"static\\\"\\n                click.delegate=\\\"openDropdown()\\\">\\n          ${'components.brand-filter.title' & t}\\n          <span if.bind=\\\"chosenBrands.length > 0\\\" class=\\\"badge rounded-pill badge-outline-primary ms-1\\\">${chosenBrands.length}</span>\\n        </button>\\n\\n        <div class=\\\"dropdown-menu dropdown-menu-end p-2\\\" style=\\\"min-width: 16rem;\\\">\\n          <input class=\\\"form-control form-control-sm mb-2\\\" type=\\\"text\\\"\\n                 placeholder=\\\"${'components.brand-filter.search' & t}\\\"\\n                 value.bind=\\\"brandSearch & debounce:200\\\">\\n\\n          <div if.bind=\\\"possibleBrands === undefined\\\" class=\\\"text-center text-muted py-2\\\">\\n            <span class=\\\"spinner-border spinner-border-sm\\\"></span>\\n          </div>\\n\\n          <div else style=\\\"max-height: 18rem; overflow-y: auto;\\\">\\n            <div if.bind=\\\"filteredBrands.length == 0\\\" class=\\\"text-muted small px-1\\\">\\n              ${'components.brand-filter.empty' & t}\\n            </div>\\n\\n            <div repeat.for=\\\"brand of filteredBrands\\\" class=\\\"form-check\\\">\\n              <input class=\\\"form-check-input\\\" type=\\\"checkbox\\\" id=\\\"brand-check-${uid}-${$index}\\\"\\n                     checked.one-way=\\\"isChosen(brand, chosenBrands)\\\"\\n                     change.delegate=\\\"toggleBrand(brand)\\\">\\n              <label class=\\\"form-check-label\\\" for=\\\"brand-check-${uid}-${$index}\\\">${brand}</label>\\n            </div>\\n          </div>\\n        </div>\\n      </div>\\n    </div>\\n\\n    <!-- Chosen brands are already visible as checked checkboxes in the\\n         dropdown, so only a reset-all control remains here, shown once it\\n         saves work (from two selections up). -->\\n    <div class=\\\"input-group pt-2\\\" id=\\\"chosen-brands\\\">\\n      <a if.bind=\\\"chosenBrands.length > 1\\\" href=\\\"#\\\" class=\\\"link-danger align-middle\\\" click.delegate=\\\"resetChosenBrands()\\\">\\n        <i class=\\\"bi bi-x-lg\\\"></i>\\n      </a>\\n    </div>\\n  </div>\\n</template>\\n\";","// Tyre size facets are stored as text (\"015\", \"02\") so a plain string sort\n// puts 385 before 70. Compare the numeric value and keep the original text.\n\nexport function compareNumericSize(a: unknown, b: unknown): number {\n  const left = String(a);\n  const right = String(b);\n  const leftNumber = Number(left);\n  const rightNumber = Number(right);\n  const leftIsNumber = left.trim() !== \"\" && Number.isFinite(leftNumber);\n  const rightIsNumber = right.trim() !== \"\" && Number.isFinite(rightNumber);\n\n  if (leftIsNumber && rightIsNumber) {\n    if (leftNumber !== rightNumber) {\n      return leftNumber - rightNumber;\n    }\n    return left < right ? -1 : left > right ? 1 : 0;\n  }\n  if (leftIsNumber) {\n    return -1;\n  }\n  if (rightIsNumber) {\n    return 1;\n  }\n  return left < right ? -1 : left > right ? 1 : 0;\n}\n","import { I18N } from 'aurelia-i18n';\nimport { observable } from 'aurelia-framework';\nimport { TKEvent } from 'utils/enums/TKEvent';\nimport { EventAggregator } from 'aurelia-event-aggregator';\nimport { autoinject, bindable } from 'aurelia-framework';\nimport noUiSlider, { PipsMode } from \"nouislider\";\nimport wNumb from 'wnumb';\nimport { TireFilterHelper } from 'utils/helpers/tire-filter-helper';\nimport { compareNumericSize } from './filter-value-order';\n\nconst NUMERIC_SIZE_FILTERS = new Set(['width', 'height', 'diameter']);\n\n@autoinject\nexport class ProductFilterCustomElement {\n  @bindable @observable categoryId: number;\n  @bindable possibleFilters: any;\n  @bindable chosenFilters: any;\n  /** SAL-313: group -> values that would return no in-stock tyre with the other chosen filters. */\n  @bindable disabledFilters: Record<string, string[]> | null = null;\n  /** SAL-313 r2: a Filters request for the newest selection is in flight. */\n  @bindable filtersPending = false;\n  /** SAL-313 r2: the group the user just changed; it stays clickable while pending. */\n  @bindable pendingGroup: string | null = null;\n\n  chosenFiltersCount: number = 0;\n  private sortingFilters = false;\n\n  constructor(\n    private eventAggregator: EventAggregator,\n    private i18n: I18N\n  ) { }\n\n  attached() {\n    this.updateChosenFiltersCount();\n    this.sortPossibleFilters();\n    this.createSliders();\n    this.prefillFilters();\n  }\n\n  categoryIdChanged(newValue: number, oldValue: number) {\n    if (oldValue === undefined)\n      return;\n\n    this.resetChosenFilters();\n  }\n\n  // Runs while the filter property is bound, before the dropdown repeat paints.\n  // attached() is too late: the list has already rendered in arrival order.\n  possibleFiltersChanged() {\n    this.sortPossibleFilters();\n  }\n\n  sortPossibleFilters() {\n    if (!this.possibleFilters || this.sortingFilters) {\n      return;\n    }\n\n    const sortedPossibleFilters: any = {};\n    let changed = false;\n\n    for (const key of Object.keys(this.possibleFilters)) {\n      const values = this.possibleFilters[key];\n      if (!Array.isArray(values)) {\n        sortedPossibleFilters[key] = values;\n        continue;\n      }\n\n      const sorted = NUMERIC_SIZE_FILTERS.has(key)\n        ? values.slice().sort(compareNumericSize)\n        : this.areAllNumbers(values)\n          ? values.slice().sort((a: number, b: number) => Number(a) - Number(b))\n          : values.slice().sort();\n      sortedPossibleFilters[key] = sorted;\n      if (sorted.length !== values.length || sorted.some((value, index) => value !== values[index])) {\n        changed = true;\n      }\n    }\n\n    if (!changed) {\n      return;\n    }\n\n    this.sortingFilters = true;\n    this.possibleFilters = sortedPossibleFilters;\n    this.sortingFilters = false;\n  }\n\n  areAllNumbers(array: []) {\n    return array.every((value: any) => !isNaN(value));\n  }\n\n  /**\n   * SAL-270 reopen / SAL-313: category 10 sizes are always checkboxes, never the range slider.\n   */\n  shouldUseSlider(key: string): boolean {\n    // SAL-313: tyres never use the slider, so every size value can be greyed out.\n    if (Number(this.categoryId) === 10) {\n      return false;\n    }\n    const values = this.possibleFilters?.[key];\n    return Array.isArray(values) && values.length > 25 && this.areAllNumbers(values);\n  }\n\n\n  createSliders() {\n    const containers = document.querySelectorAll('.slider');\n    containers.forEach(container => {\n      const key = container.getAttribute('data-key')!;\n      const filterValues = this.possibleFilters[key];\n\n      const min = Math.min(...filterValues);\n      const max = Math.max(...filterValues);\n\n      this.createSlider(container, min, max);\n    });\n  }\n\n  createSlider(slider: any, min: number, max: number) {\n    noUiSlider.create(slider, {\n      start: [min, max],\n      range: { min, max },\n      connect: true,\n      tooltips: true,\n      direction: 'rtl',\n      orientation: 'vertical',\n      format: wNumb({ decimals: 0 }),\n      step: 1,\n      pips: {\n        mode: PipsMode.Positions as any,\n        values: [0, 25, 50, 75, 100],\n        stepped: true,\n        density: 5\n      }\n    }).on('change', () => {\n      this.chooseFilter(slider);\n    });\n  }\n\n  prefillFilters() {\n    if (this.possibleFilters === undefined || this.chosenFilters === undefined)\n      return;\n\n    this.clearFilterBadges();\n\n    Object.entries(this.chosenFilters).forEach(([key, values]: [string, string[]]) => this.prefillFilter(key, values));\n  }\n\n  prefillFilter(key: string, values: string[]) {\n    let temporaryPossibleFilters = this.possibleFilters;\n    this.possibleFilters = {}; // Clear previous filters\n    this.possibleFilters = temporaryPossibleFilters;\n\n    const sliders = document.querySelectorAll(`.slider[data-key=\"${key}\"]`);\n\n    if (sliders.length > 0)\n      this.prefillSliders(sliders.item(0), key, values);\n    else\n      this.addFilterBadge(key, (values as []).join(\", \"));\n  }\n\n  prefillSliders(target: Element, key: string, values: string[]) {\n    const slider = (target as any).noUiSlider;\n\n    const chosenMin = Math.min(...values as []);\n    const chosenMax = Math.max(...values as []);\n\n    const range = slider.options.range;\n    if (chosenMin != range.min || chosenMax != range.max)\n      this.addFilterBadge(key, `${chosenMin}...${chosenMax}`);\n\n    slider.set([chosenMin, chosenMax]);\n  }\n\n  isFilterValueChosen(key: string, value: any) {\n    if (!this.chosenFilters || !this.chosenFilters[key])\n      return false;\n\n    return (this.chosenFilters[key] as []).some((chosenValue) => this.areFilterValuesEqual(chosenValue, value));\n  }\n\n  /** SAL-313: disabledFilters is passed in so the binding re-runs when it is replaced. */\n  isFilterValueDisabled(key: string, value: any, disabledFilters: Record<string, string[]> | null): boolean {\n    return TireFilterHelper.isOptionDisabled(disabledFilters, this.chosenFilters, key, value);\n  }\n\n  /** SAL-313 r2: dimmed and not clickable while the newest Filters request is in flight. */\n  isFilterValueLocked(key: string, value: any, pending: boolean, pendingGroup: string | null): boolean {\n    return TireFilterHelper.isOptionLocked(pending, pendingGroup, this.chosenFilters, key, value);\n  }\n\n  areFilterValuesEqual(firstValue: any, secondValue: any) {\n    return `${firstValue}` === `${secondValue}`;\n  }\n\n  addFilterBadge(key: string, text: string) {\n    const filterBadge = this.getElementByKey(key);\n    const keyName = TireFilterHelper.translateKey(this.categoryId, key, this.i18n);\n    const displayText = this.translateBadgeValues(key, text);\n\n    filterBadge.innerText = `${keyName}: ${displayText}`;\n    filterBadge.style.display = \"block\";\n  }\n\n  translateBadgeValues(key: string, text: string): string {\n    if (Number(this.categoryId) !== 10) return text;\n    if (text.includes('...')) return text;\n    return text\n      .split(',')\n      .map(part => TireFilterHelper.translateValue(this.categoryId, key, part.trim(), this.i18n))\n      .join(', ');\n  }\n\n  filterValueLabel(key: string, value: string): string {\n    if (Number(this.categoryId) !== 10) return value;\n    return TireFilterHelper.translateValue(this.categoryId, key, String(value), this.i18n);\n  }\n\n  filterEntries(key: string): { value: string; nested: boolean }[] {\n    const values = this.possibleFilters?.[key] ?? [];\n    if (Number(this.categoryId) === 10 && key === 'season') {\n      return TireFilterHelper.seasonEntries(values);\n    }\n    return values.map((value: string) => ({ value: String(value), nested: false }));\n  }\n\n  clearFilterBadges() {\n    const element = document.getElementById(\"chosen-filters\");\n    if (!element) return;\n\n    for (let i = 0; i < element.children.length; i++) {\n      let child = element.children[i];\n      if (child.nodeName == \"SPAN\")\n        this.clearElement(child as HTMLSpanElement);\n    }\n  }\n\n  clearFilterBadge(key: string) {\n    const element = this.getElementByKey(key);\n    this.clearElement(element);\n  }\n\n  clearElement(element: HTMLElement) {\n    if (!element) return;\n    element.style.display = \"none\";\n    element.innerHTML = \"\";\n  }\n\n  chooseFilter(target: HTMLElement) {\n    let values: string[] = [];\n    let key = target.getAttribute('data-key')!;\n\n    if (target instanceof HTMLInputElement && Number(this.categoryId) === 10 && key === 'season') {\n      this.applySeasonFamily(target);\n    }\n\n    this.clearFilterBadge(key);\n\n    if (target.classList.contains(\"slider\")) {\n      values = this.getSliderFilterValues(target, key);\n    } else {\n      values = this.getCheckboxFilterValues(key);\n    }\n\n    this.updateChosenFilters(values, key);\n  }\n\n  getSliderFilterValues(target: HTMLElement, key: string): string[] {\n    const values: string[] = [];\n\n    const chosenValues = (target as any).noUiSlider.get(true);\n    const chosenMin = parseInt(chosenValues[0]);\n    const chosenMax = parseInt(chosenValues[1]);\n\n    const range = (target as any).noUiSlider.options.range;\n    if (chosenMin == range.min && chosenMax == range.max)\n      return values;\n\n    this.addFilterBadge(key, `${chosenMin}...${chosenMax}`);\n\n    for (let value of this.possibleFilters[key]) {\n      value = Number(value);\n\n      if (value >= chosenMin && value <= chosenMax)\n        values.push(value);\n    }\n\n    return values;\n  }\n\n  /** Keep the Talv checkbox and its children in step before the checked boxes are read. */\n  applySeasonFamily(target: HTMLInputElement) {\n    const clicked = target.getAttribute('data-value') || '';\n    const boxes = Array.from(document.querySelectorAll<HTMLInputElement>('input[data-key=\"season\"]'));\n    const available = boxes.map(box => box.getAttribute('data-value') || '');\n    const selected = boxes.filter(box => box.checked).map(box => box.getAttribute('data-value') || '');\n    const next = new Set(TireFilterHelper.seasonChoice(selected, clicked, target.checked, available));\n    boxes.forEach(box => {\n      box.checked = next.has(box.getAttribute('data-value') || '');\n    });\n  }\n\n  getCheckboxFilterValues(key: string): string[] {\n    let values: string[] = [];\n    let checkedBoxes: NodeListOf<Element> = document.querySelectorAll(`input[data-key=\"${key}\"]:checked`);\n\n    if (checkedBoxes.length == 0)\n      return [];\n\n    checkedBoxes.forEach((element: HTMLInputElement) => values.push(element.getAttribute(\"data-value\")!));\n    this.addFilterBadge(key, (values as []).join(\", \"));\n\n    return values;\n  }\n\n  updateChosenFilters(values: string[], key: string) {\n    if (this.chosenFilters == undefined)\n      this.chosenFilters = {};\n\n    if (values.length == 0)\n      delete this.chosenFilters[key];\n    else\n      this.chosenFilters[key] = values;\n\n    this.updateChosenFiltersCount();\n    this.publishChosenFiltersChanged();\n  }\n\n  getElementByKey(key: string) {\n    return document.querySelectorAll(`#chosen-filters span[data-key=\"${key}\"]`)[0] as HTMLSpanElement;\n  }\n\n  resetChosenFilters() {\n    this.chosenFilters = {};\n    this.clearFilterBadges();\n    // SAL-296: Clear must uncheck the boxes, not only hide the chip. The one-way\n    // checked binding does not re-sync from chosenFilters on this click.\n    document.querySelectorAll('#product-filter input[type=\"checkbox\"]').forEach(box => {\n      (box as HTMLInputElement).checked = false;\n    });\n    this.removeSliders();\n    this.publishChosenFiltersChanged();\n    this.attached();\n  }\n\n  removeSliders() {\n    const sliders = document.getElementsByClassName(\"slider\");\n    for (var i = 0; i < sliders.length; i++)\n      (sliders.item(i) as any).noUiSlider.destroy();\n  }\n\n  publishChosenFiltersChanged() {\n    this.eventAggregator.publish(TKEvent.chosenFiltersChanged, {\n      categoryId: this.categoryId,\n      chosenFilters: this.chosenFilters\n    });\n  }\n\n  updateChosenFiltersCount() {\n    this.chosenFiltersCount = Object.values(this.chosenFilters ?? {})\n      .reduce((sum: number, values: any) => sum + (values as []).length, 0);\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"nouislider/dist/nouislider.css\\\"></require>\\n  <require from=\\\"/node_modules/bootstrap-icons/font/bootstrap-icons.css\\\"></require>\\n\\n  <div class=\\\"pt-1 pb-3 w-100\\\">\\n    <div class=\\\"input-group mx-auto\\\" id=\\\"product-filter\\\">\\n      <span class=\\\"input-group-text\\\">${'pages.category.filters.header' & t}</span>\\n\\n      <span class=\\\"input-group-text form-control\\\"></span>\\n\\n      <div repeat.for=\\\"key of possibleFilters | objectKeys\\\" class=\\\"dropdown\\\">\\n        <button class=\\\"btn btn-outline-primary dropdown-toggle\\\" type=\\\"button\\\" data-bs-toggle=\\\"dropdown\\\">\\n          ${('pages.category.filters.' + categoryId + '.' + key) & t}\\n        </button>\\n\\n        <ul class=\\\"dropdown-menu\\\">\\n          <let outer-index=\\\"${$index}\\\"></let>\\n          <li if.bind=\\\"shouldUseSlider(key)\\\">\\n            <div type=\\\"input\\\" class=\\\"slider mx-auto mx-1 my-4\\\" change.delegate=\\\"chooseFilter($event.target)\\\"\\n              data-key=\\\"${key}\\\"></div>\\n          </li>\\n          <!-- The chosen value rides on data-value, not value. A bound \\\"value\\\" gives\\n               Aurelia's CheckedObserver a value observer to subscribe to, and that\\n               subscription re-synchronises \\\"checked\\\" from the (still unchanged) model\\n               on the element's own change event - before the delegated chooseFilter\\n               handler runs, so it would always read zero checked boxes. -->\\n          <!-- SAL-313: while the newest Filters request is in flight (r2), unchosen values of the\\n               other groups are dimmed and disabled until the response or an error lands.\\n               SAL-313: a value that would return no in-stock tyre with the other chosen\\n               filters is greyed out and disabled, not hidden. Chosen values stay enabled. -->\\n          <li else repeat.for=\\\"entry of filterEntries(key)\\\"\\n            class=\\\"${entry.nested ? 'dropdown-item ps-4' : 'dropdown-item'} ${isFilterValueDisabled(key, entry.value, disabledFilters) ? 'disabled text-muted' : ''} ${isFilterValueLocked(key, entry.value, filtersPending, pendingGroup) ? 'disabled opacity-50' : ''}\\\"\\n            aria-disabled.bind=\\\"isFilterValueDisabled(key, entry.value, disabledFilters) || isFilterValueLocked(key, entry.value, filtersPending, pendingGroup)\\\"\\n            aria-busy.bind=\\\"filtersPending\\\">\\n            <input class=\\\"form-check-input\\\" change.delegate=\\\"chooseFilter($event.target)\\\" type=\\\"checkbox\\\"\\n              id=\\\"value-${outerIndex}-${$index}\\\" data-key=\\\"${key}\\\" data-value=\\\"${entry.value}\\\"\\n              disabled.bind=\\\"isFilterValueDisabled(key, entry.value, disabledFilters) || isFilterValueLocked(key, entry.value, filtersPending, pendingGroup)\\\"\\n              checked.one-way=\\\"isFilterValueChosen(key, entry.value)\\\">${filterValueLabel(key, entry.value)}\\n          </li>\\n        </ul>\\n      </div>\\n    </div>\\n\\n    <div class=\\\"input-group pt-2\\\" id=\\\"chosen-filters\\\">\\n      <a if.bind=\\\"chosenFiltersCount > 0\\\" href=\\\"#\\\" class=\\\"link-danger\\\" click.delegate=\\\"resetChosenFilters()\\\">\\n        <i class=\\\"bi bi-x-lg\\\"></i>\\n      </a>\\n      <span repeat.for=\\\"key of possibleFilters | objectKeys\\\" class=\\\"badge rounded-pill badge-outline-primary ms-1\\\"\\n        style=\\\"display: none\\\" data-key.bind=\\\"key\\\"></span>\\n    </div>\\n  </div>\\n\\n</template>\";","import { autoinject, LogManager, bindable } from \"aurelia-framework\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { CartProductService } from \"services/cart/cart-product-service\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { AppConfig } from \"app-config\";\nimport { ICartProduct } from \"domain/Cart/ICartProduct\";\nimport { IStockItem } from \"domain/Product/IStockItem\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\nimport { CurrencyFormatValueConverter } from \"utils/classes/value-converters\";\nimport { Modal } from \"bootstrap\";\nimport { AddToCartGate } from \"utils/helpers/toast-helper\";\n\nexport const log = LogManager.getLogger(\"app.components.add-to-cart\");\n\ntype CartProductCandidate = IProduct & Partial<ICartProduct>;\n\n// SAL-319: every rendered row gets its own sequence number, so two rows with the same code\n// (e.g. an RVS product and a partner row) never share a button or modal id.\nlet rowSequence = 0;\n\n@autoinject\nexport class AddToCartCustomElement {\n  @bindable product: CartProductCandidate;\n  productCode: string;\n  readonly rowUid = ++rowSequence;\n  // SAL-319: component-scoped refs; never look the modal up by a (possibly shared) DOM id.\n  confirmModalEl?: HTMLElement;\n  addToCartButtonEl?: HTMLButtonElement;\n  addToCartWarnButtonEl?: HTMLButtonElement;\n  private currencyFormat = new CurrencyFormatValueConverter();\n\n  /** SAL-283 QA: Lisa opened the confirm modal and only its OK may add; one add at a time. */\n  private gate = new AddToCartGate();\n\n  constructor(\n    private element: Element,\n    private cartProductService: CartProductService,\n    private eventAggregator: EventAggregator,\n    private appConfig: AppConfig,\n    private i18n: I18N,\n  ) {}\n\n  getUniqueProductId(product: CartProductCandidate) {\n    const source = product.id ?? product.foundBy ?? \"x\";\n    return `${product.code}-${source}-${this.rowUid}`;\n  }\n\n  tryAddToCart(product: CartProductCandidate) {\n    if (!this.ensureValidMinimumQuantity(product)) return;\n\n    if (this.gate.busy) return;\n\n    if (this.cartWarningNeeded(product)) {\n      // SAL-319: this component's own modal (ref), never one looked up by a shared id.\n      // SAL-283 QA: only the OK of the modal opened by this Lisa click may add.\n      if (this.confirmModalEl && this.gate.requestConfirm()) Modal.getOrCreateInstance(this.confirmModalEl).show();\n      return;\n    }\n\n    this.addToCart(product);\n  }\n\n  /** OK in this component's confirm modal: adds once for the Lisa click that opened it. */\n  confirmAddToCart(product: CartProductCandidate) {\n    if (!this.gate.takeConfirm()) return;\n    this.addToCart(product);\n  }\n\n  /** Modal closed without OK: the pending Lisa click is dropped. */\n  cancelConfirm() {\n    this.gate.cancelConfirm();\n  }\n\n  addToCart(product: CartProductCandidate) {\n    if (this.gate.busy) return;\n    if (!this.ensureValidMinimumQuantity(product)) return;\n    const quantity = parseInt(product.toCartQuantity ?? \"1\", 10);\n\n    const buttons = [this.addToCartButtonEl, this.addToCartWarnButtonEl].filter(\n      (b): b is HTMLButtonElement => !!b,\n    );\n    if (!this.gate.begin()) return;\n    buttons.forEach(b => (b.disabled = true));\n\n    this.cartProductService\n      .post(this.getRequestData(product, quantity))\n      .then(() => {\n        Utils.showSuccessToast(this.i18n.tr(\"components.products.messages.added-to-cart\"));\n\n        this.eventAggregator.publish(TKEvent.cartProductsChanged);\n      })\n      .catch(() => {\n        Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.add-to-cart\"));\n      })\n      .finally(() => {\n        this.gate.end();\n        buttons.forEach(b => (b.disabled = false));\n      });\n  }\n\n  getMinimumQuantity(product: CartProductCandidate): number {\n    return ProductExtraHelper.getMinimumQuantity(product.selectedStock);\n  }\n\n  showsMinimumQuantityHint(product: CartProductCandidate): boolean {\n    return this.getMinimumQuantity(product) > 1;\n  }\n\n  private ensureValidMinimumQuantity(product: CartProductCandidate): boolean {\n    const quantity = parseInt(product.toCartQuantity ?? \"\", 10);\n    if (ProductExtraHelper.isValidMinimumQuantity(quantity, product.selectedStock)) return true;\n\n    product.toCartQuantity = this.getMinimumQuantity(product).toString();\n    Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.minimum-quantity\"));\n    return false;\n  }\n\n  getRequestData(product: CartProductCandidate, quantity: number): any {\n    const data = {\n      id: product.id,\n      foundBy: product.foundBy,\n      code: product.code,\n      quantity,\n      warehouseId: product.selectedStock?.warehouse?.id ?? product.warehouseId ?? 0,\n    } as any;\n\n    if (this.isExternalWarehouse(product.selectedStock?.warehouse) || product.externalWarehouseId) {\n      data.warehouseId = 0;\n      data.externalWarehouseId = product.selectedStock?.warehouse?.id ?? product.externalWarehouseId;\n    }\n\n    return data;\n  }\n\n  private otherWarehouseWarningNeeded(warehouse: IWarehouse | undefined) {\n    if (!warehouse) return false;\n    if (this.isExternalWarehouse(warehouse)) return true;\n\n    return this.otherWarehouseIdWarningNeeded(warehouse.id);\n  }\n\n  private isExternalWarehouse(warehouse: IWarehouse | undefined) {\n    const isExternal = warehouse?.isExternal as unknown;\n    return (\n      isExternal === true ||\n      isExternal === \"true\" ||\n      isExternal === 1 ||\n      isExternal === \"1\"\n    );\n  }\n\n  private otherWarehouseIdWarningNeeded(warehouseId: number) {\n    const userWarehouseId = this.appConfig.userSettings.warehouseId;\n    const isCentralWarehouse = warehouseId === 1;\n    const isMustamaeWarehouse = warehouseId === 3;\n    const isTartuWarehouse = warehouseId === 21;\n    // SAL-296: Rehviladu always shows the +2 / 16:30 note.\n    if (warehouseId === 40) return true;\n\n    return (\n      warehouseId !== userWarehouseId &&\n      !isCentralWarehouse &&\n      !isMustamaeWarehouse &&\n      !isTartuWarehouse\n    );\n  }\n\n  cartWarningNeeded(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    return (\n      this.hasStockWarning(\n        product,\n        selectedStock,\n        warehouseId,\n        externalWarehouseId,\n        externalWarehouseGroupId,\n      ) || this.hasRefundableDeposit(product, selectedStock)\n    );\n  }\n\n  hasStockWarning(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    if (selectedStock?.warehouse) {\n      return this.otherWarehouseWarningNeeded(selectedStock.warehouse);\n    }\n\n    if (externalWarehouseId != null || externalWarehouseGroupId != null) {\n      return true;\n    }\n\n    return warehouseId == null ? false : this.otherWarehouseIdWarningNeeded(warehouseId);\n  }\n\n  hasExternalStockWarning(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    if (\n      !this.hasStockWarning(\n        product,\n        selectedStock,\n        product.warehouseId,\n        externalWarehouseId,\n        externalWarehouseGroupId,\n      )\n    ) {\n      return false;\n    }\n\n    if (selectedStock?.warehouse) return this.isExternalWarehouse(selectedStock.warehouse);\n\n    return externalWarehouseId != null || externalWarehouseGroupId != null;\n  }\n\n  hasRefundableDeposit(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    return ProductExtraHelper.hasRefundableDeposit(\n      ProductExtraHelper.getSelectedRefundableDepositSource(product, selectedStock),\n    );\n  }\n\n  getRefundableDeposit(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    return ProductExtraHelper.getRefundableDeposit(\n      ProductExtraHelper.getSelectedRefundableDepositSource(product, selectedStock),\n    );\n  }\n\n  getRefundableDepositLabel(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    const refundableDeposit = this.getRefundableDeposit(product, selectedStock);\n    return refundableDeposit == null ? \"\" : this.currencyFormat.toView(refundableDeposit);\n  }\n\n  getRefundableDepositWarningText(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n  ) {\n    const refundableDeposit = this.getRefundableDeposit(product, selectedStock);\n    const lines = [this.i18n.tr(\"components.products.tooltips.casing.order-delay\")];\n\n    if (refundableDeposit != null) {\n      lines.push(\n        this.i18n.tr(\"components.products.tooltips.casing.price-line\", {\n          price: this.getRefundableDepositLabel(product, selectedStock),\n        }),\n      );\n    } else {\n      lines.push(this.i18n.tr(\"components.products.tooltips.casing.included-without-price\"));\n    }\n\n    return lines.join(\"<br>\");\n  }\n\n  getStockWarningText(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n    externalWarehouseId = product.externalWarehouseId,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    if (\n      this.hasExternalStockWarning(\n        product,\n        selectedStock,\n        externalWarehouseId,\n        externalWarehouseGroupId,\n      )\n    ) {\n      const groupId = this.getExternalWarningGroupId(\n        product,\n        selectedStock,\n        externalWarehouseGroupId,\n      );\n\n      return this.i18n.tr(`components.products.tooltips.other-stock-warning.external.${groupId}`);\n    }\n\n    const stockWarehouseId = this.getWarehouseWarningId(product, selectedStock, warehouseId);\n    return this.i18n.tr(\n      `components.products.tooltips.other-stock-warning.warehouses.${stockWarehouseId}`,\n    );\n  }\n\n  getExternalWarningGroupId(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    externalWarehouseGroupId = product.externalWarehouseGroupId,\n  ) {\n    return selectedStock?.warehouse?.groupId || externalWarehouseGroupId || 2;\n  }\n\n  getWarehouseWarningId(\n    product: CartProductCandidate,\n    selectedStock: IStockItem | null | undefined = product.selectedStock,\n    warehouseId = product.warehouseId,\n  ) {\n    return selectedStock?.warehouse?.id || warehouseId;\n  }\n}\n","module.exports = \"<template>\\n  <div>\\n    <div class=\\\"input-group mx-auto add-to-cart-form\\\">\\n    <input\\n      type=\\\"number\\\"\\n      class=\\\"form-control form-control-sm\\\"\\n      min.bind=\\\"getMinimumQuantity(product)\\\"\\n      step.bind=\\\"getMinimumQuantity(product)\\\"\\n      value.bind=\\\"product.toCartQuantity\\\" />\\n    <div class=\\\"input-group-append\\\">\\n      <button\\n        id=\\\"addToCart-${getUniqueProductId(product)}-warn\\\"\\n        ref=\\\"addToCartWarnButtonEl\\\"\\n        type=\\\"button\\\"\\n        class=\\\"btn btn-success btn-sm clickable-important\\\"\\n        if.bind=\\\"cartWarningNeeded(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"\\n        click.trigger=\\\"tryAddToCart(product)\\\">\\n        ${'components.products.buttons.add-to-cart' & t}\\n      </button>\\n      <button\\n        id=\\\"addToCart-${getUniqueProductId(product)}\\\"\\n        ref=\\\"addToCartButtonEl\\\"\\n        type=\\\"button\\\"\\n        class=\\\"btn btn-success btn-sm clickable-important\\\"\\n        click.trigger=\\\"tryAddToCart(product)\\\"\\n        else>\\n        ${'components.products.buttons.add-to-cart' & t}\\n      </button>\\n    </div>\\n    </div>\\n    <div\\n      if.bind=\\\"showsMinimumQuantityHint(product)\\\"\\n      class=\\\"text-muted small text-center mt-1 minimum-quantity-hint\\\">\\n      ${'components.products.fields.minimum-quantity-hint' & t: {'quantity': getMinimumQuantity(product)}}\\n    </div>\\n  </div>\\n\\n  <div\\n    class=\\\"modal fade text-wrap\\\"\\n    id=\\\"confirmModal-${getUniqueProductId(product)}\\\"\\n    ref=\\\"confirmModalEl\\\"\\n    hidden.bs.modal.trigger=\\\"cancelConfirm()\\\"\\n    tabindex=\\\"-1\\\"\\n    aria-hidden=\\\"true\\\">\\n    <div class=\\\"modal-dialog modal-dialog-centered\\\">\\n      <div class=\\\"modal-content\\\">\\n        <div class=\\\"modal-header d-flex text-center\\\">\\n          <h5\\n            if.bind=\\\"hasStockWarning(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"\\n            class=\\\"modal-title inline\\\"\\n            innerhtml.bind=\\\"i18n.tr('components.products.tooltips.other-stock-warning.general')\\\"></h5>\\n          <h5\\n            else\\n            class=\\\"modal-title inline\\\">\\n            ${'components.products.tooltips.info-modal.product-info' & t}\\n          </h5>\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn-close clickable-important mt-0 mb-auto\\\"\\n            data-bs-dismiss=\\\"modal\\\"\\n            aria-label=\\\"Close\\\"></button>\\n        </div>\\n        <div class=\\\"modal-body text-center\\\">\\n          <div\\n            if.bind=\\\"hasStockWarning(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"\\n            class=\\\"product-info-modal-section\\\">\\n            <h6 class=\\\"product-info-modal-heading\\\">\\n              ${'components.products.tooltips.info-modal.stock-selection' & t}\\n            </h6>\\n            <p\\n              class=\\\"product-info-modal-warning-text\\\"\\n              innerhtml.bind=\\\"getStockWarningText(product, product.selectedStock, product.warehouseId, product.externalWarehouseId, product.externalWarehouseGroupId)\\\"></p>\\n          </div>\\n          <div if.bind=\\\"hasRefundableDeposit(product, product.selectedStock)\\\" class=\\\"product-info-modal-section\\\">\\n            <h6 class=\\\"product-info-modal-heading\\\">\\n              ${'components.products.tooltips.info-modal.additional-component' & t}\\n            </h6>\\n            <p\\n              class=\\\"product-info-modal-warning-text\\\"\\n              innerhtml.bind=\\\"getRefundableDepositWarningText(product, product.selectedStock)\\\"></p>\\n          </div>\\n        </div>\\n        <div class=\\\"modal-footer d-flex align-items-center\\\">\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-secondary clickable-important\\\"\\n            data-bs-dismiss=\\\"modal\\\">\\n            ${'components.report-modal.close-button' & t}\\n          </button>\\n          <button\\n            id=\\\"addToCartConfirm-${getUniqueProductId(product)}\\\"\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-primary clickable-important\\\"\\n            click.trigger=\\\"confirmAddToCart(product)\\\"\\n            data-bs-dismiss=\\\"modal\\\">\\n            OK\\n          </button>\\n        </div>\\n      </div>\\n    </div>\\n  </div>\\n</template>\\n\";","import { autoinject, bindable } from 'aurelia-framework';\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\n\n@autoinject\nexport class CopyToClipboardCustomElement {\n  @bindable text: string;\n\n  constructor(\n    private i18n: I18N\n  ) {}\n  \n  copyToClipboard() {\n    navigator.clipboard.writeText(this.text)\n    Utils.showSuccessToast(this.i18n.tr('components.products.messages.code-copied-to-clipboard'));\n  }\n}\n","module.exports = \"<template>\\n\\n  <a class=\\\"icon-link icon-link-hover text-reset\\\" click.trigger=\\\"copyToClipboard()\\\">\\n    <i class=\\\"bi bi-copy clickable-important\\\"></i>\\n  </a>\\n\\n</template>\\n\";","import { encodeSearchRouteQuery } from \"utils/helpers/search-route\";\nimport { SearchType } from 'utils/enums/SearchType';\nimport { IParentItem } from 'domain/Base/IParentItem';\nimport { Router } from 'aurelia-router';\nimport { AppConfig } from 'app-config';\nimport { autoinject, observable, LogManager, bindable, BindingEngine } from 'aurelia-framework';\nimport { IProduct } from 'domain/Product/IProduct';\nimport { Utils } from 'utils/helpers/utils';\nimport { TireFilterHelper } from 'utils/helpers/tire-filter-helper';\nimport { I18N } from 'aurelia-i18n';\n\nexport const log = LogManager.getLogger('app.components.extra-row');\n\ninterface IOeTreeItem extends IParentItem {\n  query?: string;\n}\n\n@autoinject\nexport class ExtraRowCustomElement {\n  @bindable @observable product: IProduct;\n  oeNumberTree: IOeTreeItem[] = [];\n  private oeNumbersSubscription: { dispose(): void } | null = null;\n\n  attached() {\n    this.subscribeToOeNumbers();\n    this.buildOeNumberTree();\n  }\n\n  detached() {\n    this.disposeOeNumbersSubscription();\n  }\n\n  productChanged() {\n    this.subscribeToOeNumbers();\n    this.buildOeNumberTree();\n  }\n\n  private subscribeToOeNumbers() {\n    this.disposeOeNumbersSubscription();\n\n    if (!this.product) {\n      return;\n    }\n\n    this.oeNumbersSubscription = this.bindingEngine\n      .propertyObserver(this.product, 'oeNumbers')\n      .subscribe(() => this.buildOeNumberTree());\n  }\n\n  private disposeOeNumbersSubscription() {\n    this.oeNumbersSubscription?.dispose();\n    this.oeNumbersSubscription = null;\n  }\n\n  private buildOeNumberTree() {\n    this.oeNumberTree = (this.product?.oeNumbers ?? []).map(([manufacturer, oeNumbers], manufacturerIndex) => ({\n      id: manufacturerIndex,\n      name: manufacturer,\n      children: oeNumbers.map((oeNumber, oeNumberIndex) => ({\n        id: manufacturerIndex * 1000 + oeNumberIndex,\n        name: oeNumber,\n        query: oeNumber,\n        children: []\n      }))\n    }));\n  }\n\n  constructor(\n    private appConfig: AppConfig,\n    private router: Router,\n    private bindingEngine: BindingEngine,\n    private i18n: I18N,\n  ) { }\n\n  infoLabel(info: [string, string]): string {\n    return TireFilterHelper.translateInfoPair(info, this.i18n)[0];\n  }\n\n  infoValue(info: [string, string]): string {\n    return TireFilterHelper.translateInfoPair(info, this.i18n)[1];\n  }\n\n  infoHref(info: [string, string]): string | null {\n    return TireFilterHelper.infoHref(info);\n  }\n\n  openDocument(productId: number, document: [string, string], index: number) {\n    const data = document[1];\n    let win: Window | null;\n\n    if (data && data.toLowerCase().startsWith(\"http\")) {\n      win = window.open(data, \"_blank\");\n    } else {\n      win = window.open(`${this.appConfig.apiUrl}/Product/${productId}/Document/${index}`, \"_blank\");\n    }\n\n    if (win != null)\n      win.focus();\n  }\n\n  showGallery(product: IProduct) {\n    Utils.showGallery(product);\n  }\n\n  loadVehicle(item: IParentItem) {\n    this.router.navigateToRoute('catalogueList', { vehicleId: item.id });\n  }\n\n  searchOeNumber(query: string) {\n    this.router.navigateToRoute('searchResult', {\n      query: encodeSearchRouteQuery(query),\n      page: 1,\n      type: SearchType.TecDoc\n    });\n  }\n\n  searchOeTreeItem(item: IOeTreeItem) {\n    if (item.query) {\n      this.searchOeNumber(item.query);\n    }\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"components/general/simple-tree\\\"></require>\\n  <require from=\\\"components/product/product-list/stock\\\"></require>\\n  <require from=\\\"components/product/product-list/price\\\"></require>\\n  <require from=\\\"resources/style.css\\\"></require>\\n\\n  <div class=\\\"collapse\\\" data-bs-parent=\\\"#accordion\\\" data-extra.bind=\\\"product.id\\\">\\n    <p if.bind=\\\"!!product.description\\\" class=\\\"row p-2\\\" innerhtml.bind=\\\"product.description\\\"></p>\\n    <div class=\\\"row p-2\\\">\\n      <div class=\\\"col\\\">\\n        <div\\n          if.bind=\\\"!appConfig.userSettings.imagesInProductPage && product.thumbnail\\\"\\n          class=\\\"col product-image-wrapper\\\"\\n          click.trigger=\\\"showGallery(product)\\\"\\n          data-image.bind=\\\"product.id\\\">\\n          <span>\\n            <img class=\\\"mx-auto product-image\\\" src.bind=\\\"product.thumbnail\\\" loading=\\\"lazy\\\" />\\n          </span>\\n        </div>\\n\\n        <div>\\n          <span\\n            if.bind=\\\"!appConfig.userSettings.detailsInProductPage\\\"\\n            repeat.for=\\\"info of product.info\\\"\\n            class=\\\"text-muted small mx-1\\\">\\n            <a if.bind=\\\"infoHref(info)\\\" href.bind=\\\"infoHref(info)\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">${infoLabel(info)}</a>\\n            <template else><b>${infoLabel(info)}</b>: ${infoValue(info)}</template><br />\\n          </span>\\n          <span if.bind=\\\"product.ean\\\" class=\\\"text-muted small mx-1 d-lg-none\\\">\\n            ${'components.products.headers.ean' & t}:\\n            <b>${product.ean}</b> </span\\n          ><br />\\n          <span if.bind=\\\"product.inPackage\\\" class=\\\"text-muted small mx-1 d-lg-none\\\">\\n            ${'components.products.headers.in-package' & t}:\\n            <b>${product.inPackage}</b>\\n          </span>\\n        </div>\\n        <span\\n          if.bind=\\\"!appConfig.userSettings.detailsInProductPage && !appConfig.userSettings.imagesInProductPage\\\"\\n          class=\\\"text-muted small\\\"\\n          data-extra-not-found.bind=\\\"product.id\\\"></span>\\n\\n        <dl if.bind=\\\"product.documents !== undefined && product.documents.length != 0\\\" class=\\\"row\\\">\\n          <dt repeat.for=\\\"document of product.documents\\\" class=\\\"col-12\\\">\\n            <a click.delegate=\\\"openDocument(product.id, document, $index)\\\" href=\\\"\\\">\\n              ${document[0]}\\n            </a>\\n          </dt>\\n        </dl>\\n      </div>\\n\\n      <div class=\\\"col\\\" if.bind=\\\"product.oeNumbers !== undefined && product.oeNumbers.length != 0\\\">\\n        <strong class=\\\"d-block mb-2\\\">${'components.products.headers.oe-numbers' & t}</strong>\\n        <simple-tree\\n          list.bind=\\\"oeNumberTree\\\"\\n          depth.bind=\\\"0\\\"\\n          click-function.call=\\\"searchOeTreeItem(item)\\\">\\n        </simple-tree>\\n      </div>\\n\\n      <div class=\\\"col\\\">\\n        <!-- Loading state -->\\n        <template if.bind=\\\"product.cars === undefined\\\">\\n          <strong class=\\\"d-block mb-2\\\">${'components.products.headers.fits-cars' & t}</strong>\\n          <div class=\\\"text-muted\\\">\\n            <span class=\\\"spinner-border spinner-border-sm me-2\\\" role=\\\"status\\\"></span>\\n          </div>\\n        </template>\\n        <!-- Loaded state with cars -->\\n        <template if.bind=\\\"product.cars !== undefined && product.cars.length != 0\\\">\\n          <strong class=\\\"d-block mb-2\\\">${'components.products.headers.fits-cars' & t}</strong>\\n          <simple-tree\\n            list.bind=\\\"product.cars\\\"\\n            depth.bind=\\\"0\\\"\\n            click-function.call=\\\"loadVehicle(item)\\\">\\n          </simple-tree>\\n        </template>\\n      </div>\\n    </div>\\n  </div>\\n</template>\\n\";","import { IProduct } from 'domain/Product/IProduct';\nimport { observable } from 'aurelia-framework';\nimport { LogManager } from 'aurelia-framework';\nimport { bindable } from 'aurelia-framework';\n\nexport var log = LogManager.getLogger('app.components.gallery');\n\nexport class GalleryCustomElement {\n  @bindable @observable products: IProduct[];\n}\n","module.exports = \"<template>\\n\\n  <div repeat.for=\\\"product of products\\\" class=\\\"modal fade\\\" data-gallery-wrapper.bind=\\\"product.id\\\"\\n       tabindex=\\\"-1\\\">\\n    <div class=\\\"modal-dialog modal-lg\\\">\\n      <div class=\\\"modal-content\\\">\\n        <div data-gallery=\\\"${product.id}\\\" class=\\\"carousel slide\\\" data-bs-interval=\\\"false\\\">\\n          <ol class=\\\"carousel-indicators\\\">\\n            <li repeat.for=\\\"image of product.images\\\" class=\\\"${$index == 0 ? 'active' : ''}\\\"\\n                data-bs-target=\\\"[data-gallery='${product.id}']\\\" data-bs-slide-to=\\\"${$index}\\\"></li>\\n          </ol>\\n          <div class=\\\"carousel-inner\\\">\\n            <div repeat.for=\\\"image of product.images\\\"\\n                 class=\\\"carousel-item ${$index == 0 ? 'active' : ''}\\\">\\n              <img class=\\\"d-block mx-auto mw-100\\\" src=\\\"${image}\\\">\\n            </div>\\n          </div>\\n          <a class=\\\"carousel-control-prev\\\" href=\\\"#\\\" data-bs-target=\\\"[data-gallery='${product.id}']\\\"\\n             role=\\\"button\\\" data-bs-slide=\\\"prev\\\">\\n            <span class=\\\"carousel-control-prev-icon\\\"></span>\\n          </a>\\n          <a class=\\\"carousel-control-next\\\" href=\\\"#\\\" data-bs-target=\\\"[data-gallery='${product.id}']\\\"\\n             role=\\\"button\\\" data-bs-slide=\\\"next\\\">\\n            <span class=\\\"carousel-control-next-icon\\\"></span>\\n          </a>\\n        </div>\\n      </div>\\n    </div>\\n  </div>\\n\\n</template>\\n\";","import { autoinject, observable, bindable, LogManager } from 'aurelia-framework';\nimport { I18N } from 'aurelia-i18n';\nimport { Utils } from 'utils/helpers/utils';\nimport { IPrice } from 'domain/Product/IPrice';\nimport { hasAmountDependentPrice } from 'domain/Product/PriceDisplay';\nimport { IProduct } from 'domain/Product/IProduct';\nimport { IStockItem } from 'domain/Product/IStockItem';\nimport { ProductExtraHelper } from 'utils/helpers/product-extra-helper';\nimport { CurrencyFormatValueConverter, PricesToTooltipValueConverter } from 'utils/classes/value-converters';\n\nexport const log = LogManager.getLogger('app.components.price');\n\n@autoinject\nexport class PriceCustomElement {\n  @bindable @observable prices: IPrice[];\n  @bindable displayPrice: number | null;\n  @bindable product: IProduct | null;\n  @bindable stockItem: IStockItem | null;\n  hasRefundableDeposit = false;\n  refundableDeposit: number | null = null;\n  priceTooltip = '';\n  private currencyFormat = new CurrencyFormatValueConverter();\n  private pricesToTooltip = new PricesToTooltipValueConverter();\n\n  constructor(\n    private i18n: I18N\n  ) {}\n\n  // #region MAIN\n\n  bind() {\n    this.updateRefundableDepositInfo();\n  }\n\n  pricesChanged() {\n    // SAL-283 QA r6: a cart line without a stock row has no prices but a stored price; not an error.\n    if (this.prices == null && this.displayPrice == null)\n      Utils.showErrorToast(log, this.i18n.tr('components.price.errors.load'));\n\n    this.updateRefundableDepositInfo();\n  }\n\n  productChanged() {\n    this.updateRefundableDepositInfo();\n  }\n\n  stockItemChanged() {\n    this.updateRefundableDepositInfo();\n  }\n  \n  hasAmountDependentPrice(prices: IPrice[] | null | undefined) {\n    return hasAmountDependentPrice(prices);\n  }\n\n  updateRefundableDepositInfo() {\n    const refundableDepositSource = this.getRefundableDepositSource();\n\n    this.hasRefundableDeposit = ProductExtraHelper.hasRefundableDeposit(refundableDepositSource);\n    this.refundableDeposit = ProductExtraHelper.getRefundableDeposit(refundableDepositSource);\n    this.priceTooltip = this.getPriceTooltip();\n  }\n\n  /** Prices plus the refundable deposit, so the whole price field has one tooltip. */\n  getPriceTooltip() {\n    const priceLines = this.pricesToTooltip.toView(this.prices, this.i18n);\n    if (!this.hasRefundableDeposit) return priceLines;\n\n    return priceLines + this.getRefundableDepositLine();\n  }\n\n  private getRefundableDepositLine() {\n    if (this.refundableDeposit == null)\n      return this.i18n.tr('components.products.tooltips.casing.included-without-price');\n\n    return this.i18n.tr('components.products.tooltips.casing.price-line', {\n      price: this.currencyFormat.toView(this.refundableDeposit),\n    });\n  }\n\n  private getRefundableDepositSource() {\n    return ProductExtraHelper.getSelectedRefundableDepositSource(this.product, this.stockItem);\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n\\n  <span if.bind=\\\"displayPrice == null\\\">\\n    ${displayPrice | currencyFormat}\\n  </span>\\n  <span else tooltip.bind=\\\"priceTooltip\\\">\\n    <span>\\n      <i if.bind=\\\"hasAmountDependentPrice(prices)\\\" class=\\\"bi bi-bar-chart\\\"></i>\\n      ${displayPrice | currencyFormat}\\n    </span>\\n    <span if.bind=\\\"hasRefundableDeposit\\\" class=\\\"product-extra-price\\\">\\n      + ${refundableDeposit | currencyFormat}\\n    </span>\\n  </span>\\n\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { TireFilterHelper } from \"utils/helpers/tire-filter-helper\";\nimport { AppConfig } from \"app-config\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { isRequestNoise } from \"utils/helpers/request-errors\";\nimport { EventAggregator, Subscription } from \"aurelia-event-aggregator\";\nimport { LogManager, autoinject, observable, bindable } from \"aurelia-framework\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { ProductService } from \"services/product/product-service\";\nimport { PriceHelper } from \"utils/helpers/price-helper\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport $ from \"jquery\";\nimport { Collapse, Popover } from \"bootstrap\";\nimport { SearchOrder } from \"utils/enums/SearchOrder\";\nimport { isEmpty } from \"lodash\";\nimport { WarehouseService } from \"services/client/warehouse-service\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\n\nexport const log = LogManager.getLogger(\"app.components.product-list\");\n\n@autoinject\nexport class ProductListCustomElement {\n  @bindable @observable products: IProduct[];\n  @bindable currentPage = 1;\n  @bindable lastPage = 1;\n  @bindable query = \"\";\n  @bindable @observable vehicleId: number | undefined;\n  @bindable @observable categoryId: number | undefined;\n  @bindable orderBy = SearchOrder.Default;\n  @bindable orderReversed = false;\n  pageHasEan = false;\n  pageHasBrand = false;\n  pageHasInPackage = false;\n  @bindable extendedSearch: boolean;\n\n  colSpan = 9;\n  imageRowspan = 2;\n\n  @bindable options = {\n    showAmount: false,\n    showSum: false,\n    showAddToCart: false,\n  };\n\n  warehouses: IWarehouse[] = [];\n\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    this.products.forEach(product => {\n      if (ProductExtraHelper.hasTkItem(product)) this.loadInfo(product);\n    });\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    this.products.forEach(product => {\n      if (!ProductExtraHelper.hasTkItem(product)) return;\n      this.loadImagesWithCategory(product);\n      this.loadInfo(product);\n    });\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          if (hasTkItem) this.loadExternalStock(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          this.loadImages(product);\n          this.loadInfo(product);\n        });\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    return this.warehouseService\n      .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  loadImages(product: IProduct) {\n    product.imageLoadingCount = (product.imageLoadingCount ?? 0) + 1;\n\n    this.productService\n      .fetchImages(product.id)\n      .then(result => {\n        product.images = result.concat(product.images ?? []);\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  loadImagesWithCategory(product: IProduct) {\n    if (!this.categoryId) return;\n\n    product.imageLoadingCount = (product.imageLoadingCount ?? 0) + 1;\n\n    this.productService\n      .fetchImagesWithCategory(product.id, this.categoryId)\n      .then(result => {\n        product.images = result.concat(product.images ?? []);\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  loadInfo(product: IProduct) {\n    const oldVehicleId = this.vehicleId;\n    const oldCategoryId = this.categoryId;\n\n    let fetch;\n    if (this.vehicleId) {\n      if (this.categoryId) {\n        fetch = this.productService.fetchInfoWithCategory(\n          product.id,\n          this.vehicleId,\n          this.categoryId,\n        );\n      } else {\n        fetch = this.productService.fetchInfoWithCar(product.id, this.vehicleId);\n      }\n    } else {\n      fetch = this.productService.fetchInfo(product.id);\n    }\n\n    fetch\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 => {\n        if (isRequestNoise(error)) return Utils.handleRequestNoise(log, error, this.i18n);\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      });\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  loadExternalStock(product: IProduct) {\n    if (!ProductExtraHelper.hasTkItem(product)) return;\n    const existingExternalStock = product.externalStock ?? [];\n\n    this.productService.fetchExternalStock(product.id).then(result => {\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  }\n\n  fillDefaultSelectedStock(product: IProduct) {\n    let stockItem = product.stock.find(\n      x => x.warehouse.id == this.appConfig.userSettings.warehouseId,\n    );\n\n    if (!Utils.isInStock(stockItem)) {\n      var isNotInOurWarehouses = !product.stock.find(x => Utils.isInStock(x));\n      if (isNotInOurWarehouses && product.externalStock.length > 0) {\n        stockItem =\n          product.externalStock.find(s => Number(s.warehouse.groupId) === 2) ||\n          product.externalStock.find(s => Number(s.warehouse.groupId) === 1) ||\n          product.externalStock[0];\n      } else {\n        stockItem = this.getFallbackStock(product);\n      }\n      PriceHelper.formatStockPrices([stockItem], this.appConfig.userSettings, this.i18n);\n    }\n\n    product.selectedStock = stockItem;\n  }\n\n  getFallbackStock(product: IProduct) {\n    return {\n      warehouse:\n        (this.warehouses ?? []).find(x => x.id == this.appConfig.userSettings.warehouseId) ??\n        (this.warehouses ?? []).find(x => x.id == 0) ??\n        this.warehouses?.[0],\n      quantity: \"0\",\n      prices: product.prices ?? [],\n    };\n  }\n\n  extractEanFromInfo(product: IProduct) {\n    if (product.ean.length > 0) return;\n\n    const eanIndex = product.info?.findIndex(x => x[0] == \"EAN\") ?? -1;\n    if (eanIndex < 0) return;\n\n    const ean = product.info?.at(eanIndex)?.at(1);\n    if (!ean) return;\n\n    product.ean = ean;\n    product.info?.splice(eanIndex, 1);\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  hasTkItem(product: IProduct): boolean {\n    return ProductExtraHelper.hasTkItem(product);\n  }\n\n  getMinimumQuantity(product: IProduct): number {\n    return ProductExtraHelper.getMinimumQuantity(product.selectedStock);\n  }\n\n  changeOrder(clickedElement: Element) {\n    if (\n      !clickedElement.getAttribute(\"data-sort\") &&\n      !clickedElement.classList.contains(\"bi-filter\")\n    )\n      return;\n\n    // If clicked on sort icon, then use it's parent as base\n    if (clickedElement.classList.contains(\"bi-filter\"))\n      clickedElement = clickedElement.parentElement ?? clickedElement;\n\n    const orderBy = parseInt(clickedElement.getAttribute(\"data-sort\") ?? \"0\");\n    let orderReversed = !this.orderReversed;\n\n    // Reset orderReversed value to false if another column is being ordered\n    if (orderBy != this.orderBy) orderReversed = false;\n\n    this.orderReversed = orderReversed;\n    this.orderBy = orderBy;\n  }\n\n  toggleExtraRow(target: HTMLElement, product: IProduct) {\n    $(() => {\n      // Check if child element was clicked instead\n      if ($(target).prop(\"tagName\") != \"TD\" && $(target).prop(\"tagName\") != \"TR\") return;\n      // SAL-270: partner-only rows have no TK item, so no description/documents/OE/cars to load.\n      if (!ProductExtraHelper.hasTkItem(product)) return;\n\n      const productWrappers = $(`.clickable[data-product-id=\"${product.id}\"]`);\n\n      // Start loading them if they aren't already loaded\n      if (!this.areExtrasLoaded(product)) {\n        // If the element has any of these classes, we're still waiting for the results\n        if (productWrappers.is(\".loading-description, .loading-documents, .loading-oe-numbers\"))\n          return;\n\n        productWrappers.addClass(\n          \"loading-description loading-documents loading-oe-numbers loading-cars\",\n        );\n\n        this.loadDescription(product);\n        this.loadDocuments(product);\n        this.loadOeNumbers(product);\n        this.loadCars(product);\n\n        return;\n      }\n\n      this.tryOpenExtraRow(product, productWrappers, true);\n    });\n  }\n\n  shouldExtraRowOpen(product: IProduct): boolean {\n    const showDetails = this.appConfig.userSettings.detailsInProductPage;\n    const showImages = this.appConfig.userSettings.imagesInProductPage;\n\n    // extra row must be opened, because otherwise we can't print out the message that nothing can be displayed\n    if (!showDetails && !showImages) return true;\n\n    return this.anyDataInExtraRow(product);\n  }\n\n  anyDataInExtraRow(product: IProduct): boolean {\n    const showDetails = this.appConfig.userSettings.detailsInProductPage;\n    const showImages = this.appConfig.userSettings.imagesInProductPage;\n    const isDataInTable = $(\"#d-lg-none\").is(\":hidden\");\n\n    // Also check if EAN or package count is hidden or doesn't exist\n    const noHiddenData = isDataInTable || (!product.ean && !product.inPackage);\n    const noHiddenDetails = showDetails || product.info === null || product.info.length == 0;\n    const noDescriptions = product.description === null || product.description === \"\";\n    const noHiddenImages =\n      showImages || product.thumbnail === null || product.thumbnail.length == 0;\n    const noExtras = !this.isAnyExtras(product);\n\n    return !(noHiddenData && noHiddenDetails && noDescriptions && noHiddenImages && noExtras);\n  }\n\n  showGallery(product: IProduct) {\n    Utils.showGallery(product);\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  highlightSearchQuery(product: IProduct) {\n    // Highlight search query with <strong>\n    $(() => {\n      const target = $(\n        `[data-product-id=\"${product.id}\"] [data-highlight-query=\"${product.foundBy}\"]`,\n      );\n      if (target.length > 0) {\n        const regex = new RegExp(Utils.escapeRegex(this.query), \"gi\");\n        const code = target.html().replace(regex, \"<strong>$&</strong>\");\n        target.html(code);\n\n        if (!target.html().includes(\"<strong>\")) {\n          target.html(\"<strong>\" + target.html() + \"</strong>\");\n        }\n      }\n    });\n  }\n\n  isAnyExtras(product: IProduct) {\n    return (\n      product.cars?.length != 0 || product.documents?.length != 0 || product.oeNumbers?.length != 0\n    );\n  }\n\n  areExtrasLoaded(product: IProduct) {\n    // Don't wait for cars - they load separately and appear later\n    return product.documents !== undefined && product.oeNumbers !== undefined;\n  }\n\n  afterLoading(product: IProduct, classToRemove: string) {\n    const productWrappers = $(`.clickable[data-product-id=\"${product.id}\"]`);\n\n    productWrappers.removeClass(classToRemove);\n\n    // Don't wait for cars to load - open extra row when description, documents and oeNumbers are ready\n    // Cars will appear later when their request completes\n    if (productWrappers.is(\".loading-description, .loading-documents, .loading-oe-numbers\")) return;\n\n    this.tryOpenExtraRow(product, productWrappers);\n  }\n\n  tryOpenExtraRow(product: IProduct, productWrappers: JQuery<HTMLElement>, isUserToggle = false) {\n    $(() => {\n      if (!this.anyDataInExtraRow(product))\n        $(`[data-extra-not-found=\"${product.id}\"]`).html(\n          this.i18n.tr(\"components.products.errors.no-info-found\"),\n        );\n\n      if (this.shouldExtraRowOpen(product)) {\n        const extraRow = document.querySelector(`[data-extra=\"${product.id}\"]`);\n        // User click should always toggle, automatic open should not close an already open row\n        if (extraRow && (isUserToggle || !extraRow.classList.contains(\"show\"))) {\n          new Collapse(extraRow, { parent: \"#accordion\" }).toggle();\n        }\n      } else {\n        productWrappers.removeClass(\"clickable\");\n      }\n    });\n  }\n\n  // Move info and extra rows along with it's parent product row when sorted\n  moveRowsListener() {\n    $(() => {\n      $(\".sortable\").on(\"sorted\", function () {\n        $(this)\n          .find(\"[rowspan-value]\")\n          .each(function () {\n            $(this).attr(\"rowspan\", $(this).attr(\"rowspan-value\") || 2);\n          });\n\n        $(this)\n          .find(\"tr.info-row\")\n          .each(function () {\n            $(this).insertAfter(\n              `.product-row[data-product-id=\"${$(this).attr(\"data-product-id\")}\"]`,\n            );\n            $(this).children(\".product-image-wrapper\").remove();\n          });\n        $(this)\n          .find(\"tr.extra-row\")\n          .each(function () {\n            $(this).insertAfter(\n              $(`.info-row[data-product-id=\"${$(this).attr(\"data-product-id\")}\"]`),\n            );\n          });\n      });\n    });\n  }\n\n  formatPrice() {\n    if (!this.products || !this.appConfig.userSettings) return;\n\n    PriceHelper.formatProductsPrices(this.products, this.appConfig.userSettings, this.i18n);\n  }\n\n  pageHasEANChecker() {\n    for (const product of this.products) {\n      if (product.ean || !isEmpty(product.ean)) {\n        this.pageHasEan = true;\n        return;\n      }\n    }\n  }\n\n  pageHasBrandChecker() {\n    for (const product of this.products) {\n      if (product.brand || !isEmpty(product.brand)) {\n        this.pageHasBrand = true;\n        return;\n      }\n    }\n  }\n\n  pageHasInPackageChecker() {\n    for (const product of this.products) {\n      if (product.inPackage || product.inPackage > 0) {\n        this.pageHasInPackage = true;\n        return;\n      }\n    }\n  }\n\n  resetConditionalColumnRendering() {\n    this.pageHasEan = false;\n    this.pageHasBrand = false;\n    this.pageHasInPackage = false;\n  }\n\n  renderColumnsConditionally() {\n    this.resetConditionalColumnRendering();\n\n    if (!this.products || this.products.length == 0) return;\n\n    this.pageHasEANChecker();\n    this.pageHasBrandChecker();\n    this.pageHasInPackageChecker();\n  }\n\n  activateExtendedSearch() {\n    this.extendedSearch = true;\n  }\n\n  // #endregion\n  infoLabel(info: [string, string]): string {\n    const cat = this.categoryId != null ? this.categoryId : 10;\n    return TireFilterHelper.translateInfoPair(info, this.i18n, cat)[0];\n  }\n\n  infoValue(info: [string, string]): string {\n    const cat = this.categoryId != null ? this.categoryId : 10;\n    return TireFilterHelper.translateInfoPair(info, this.i18n, cat)[1];\n  }\n\n  infoHref(info: [string, string]): string | null {\n    return TireFilterHelper.infoHref(info);\n  }\n\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/mobile-cards\\\"></require>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n  <require from=\\\"components/product/product-list/add-to-cart\\\"></require>\\n  <require from=\\\"components/product/product-list/copy-to-clipboard\\\"></require>\\n  <require from=\\\"components/product/product-list/extra-row\\\"></require>\\n  <require from=\\\"components/product/product-list/gallery\\\"></require>\\n  <require from=\\\"components/product/product-list/stock\\\"></require>\\n  <require from=\\\"components/product/product-list/price\\\"></require>\\n  <require from=\\\"components/general/pager\\\"></require>\\n  <require from=\\\"components/product/product-list/report-button\\\"></require>\\n\\n  <!-- table-striped doesn't work, because every other row is hidden -->\\n  <!-- table-hover doesn't work, because we want to hover multiple rows at once (using .hover) -->\\n  <table mobile-cards\\n    id=\\\"accordion\\\"\\n    class=\\\"table table-borderless table-sm table-responsive-md w-100 accordion odd-row-darker-bg no-default-bg mc-products\\\">\\n    <thead>\\n      <tr id=\\\"product-list-header-row\\\" click.trigger=\\\"changeOrder($event.target)\\\">\\n        <th if.bind=\\\"appConfig.userSettings.imagesInProductPage\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.thumbnail' & t}\\n        </th>\\n        <th data-sort=\\\"1\\\">${'components.products.headers.code' & t}</th>\\n        <th data-sort=\\\"2\\\">${'components.products.headers.name' & t}</th>\\n        <th\\n          if.bind=\\\"pageHasEan || orderBy == SearchOrder.EAN\\\"\\n          data-sort=\\\"3\\\"\\n          class=\\\"text-center d-none d-lg-table-cell\\\">\\n          ${'components.products.headers.ean' & t}\\n        </th>\\n        <th if.bind=\\\"pageHasBrand || orderBy == SearchOrder.Brand\\\" data-sort=\\\"4\\\">\\n          ${'components.products.headers.brand' & t}\\n        </th>\\n        <th\\n          if.bind=\\\"pageHasInPackage || orderBy == SearchOrder.InPackage\\\"\\n          data-sort=\\\"5\\\"\\n          class=\\\"text-center d-none d-lg-table-cell\\\">\\n          ${'components.products.headers.in-package' & t}\\n        </th>\\n        <th class=\\\"text-center\\\">${'components.products.headers.stock' & t}</th>\\n        <th class=\\\"text-end\\\">${'components.products.headers.price' & t}</th>\\n        <th if.bind=\\\"options.showAmount\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.amount' & t}\\n        </th>\\n        <th if.bind=\\\"options.showSum\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.total' & t}\\n        </th>\\n        <th if.bind=\\\"options.showAddToCart\\\" class=\\\"text-center\\\">\\n          ${'components.products.headers.add-to-cart' & t}\\n        </th>\\n      </tr>\\n    </thead>\\n\\n    <tbody repeat.for=\\\"product of products\\\">\\n      <tr\\n        class=\\\"clickable product-row\\\"\\n        data-product-id.bind=\\\"product.id\\\"\\n        click.delegate=\\\"toggleExtraRow($event.target, product)\\\">\\n        <td\\n          rowspan.bind=\\\"imageRowspan\\\"\\n          if.bind=\\\"appConfig.userSettings.imagesInProductPage\\\"\\n          class=\\\"product-image-wrapper\\\"\\n          click.trigger=\\\"showGallery(product)\\\"\\n          data-image.bind=\\\"product.id\\\">\\n          <span class=\\\"product-image-state\\\">\\n            <span\\n              if.bind=\\\"product.imageLoadingCount && !product.thumbnail\\\"\\n              class=\\\"product-image-loading\\\">\\n              <span class=\\\"spinner-border spinner-border-sm text-secondary\\\" role=\\\"status\\\"></span>\\n            </span>\\n            <img\\n              class=\\\"mx-auto product-image\\\"\\n              if.bind=\\\"product.thumbnail\\\"\\n              src.bind=\\\"product.thumbnail\\\"\\n              loading=\\\"lazy\\\"\\n              load.trigger=\\\"thumbnailLoaded(product, $event.target)\\\"\\n              error.trigger=\\\"thumbnailFailed(product)\\\" />\\n          </span>\\n        </td>\\n\\n        <td\\n          if.bind=\\\"product.originalCode != product.code\\\"\\n          class=\\\"font-italic text-nowrap mc-code\\\"\\n          tooltip=\\\"${'components.products.fields.replacement' & t: {'originalCode': product.originalCode}}\\\">\\n          <span class=\\\"pe-none\\\" data-highlight-query=\\\"code\\\">${product.code}</span>\\n          <copy-to-clipboard text.bind=\\\"product.code\\\"></copy-to-clipboard>\\n          <report-button product.bind=\\\"product\\\"></report-button>\\n        </td>\\n\\n        <td else class=\\\"text-nowrap mc-code\\\">\\n          <span class=\\\"pe-none\\\" data-highlight-query=\\\"code\\\">${product.code}</span>\\n          <copy-to-clipboard text.bind=\\\"product.code\\\"></copy-to-clipboard>\\n          <report-button product.bind=\\\"product\\\"></report-button>\\n        </td>\\n\\n        <td class=\\\"mc-full\\\"><span data-highlight-query=\\\"name\\\">${product.name}</span></td>\\n\\n        <td\\n          if.bind=\\\"pageHasEan || orderBy == SearchOrder.EAN\\\"\\n          class=\\\"text-center text-nowrap d-none d-lg-table-cell\\\">\\n          <span data-highlight-query=\\\"ean\\\">${product.ean}</span>\\n        </td>\\n\\n        <td if.bind=\\\"pageHasBrand || orderBy == SearchOrder.Brand\\\" class=\\\"mc-brand\\\">\\n          <span>${product.brand}</span>\\n        </td>\\n\\n        <td\\n          if.bind=\\\"pageHasInPackage || orderBy == SearchOrder.InPackage\\\"\\n          class=\\\"text-center text-nowrap d-none d-lg-table-cell\\\">\\n          <span>${product.inPackage > 0 ? product.inPackage : ''}</span>\\n        </td>\\n\\n        <td\\n          class=\\\"text-center clickable mc-stock\\\"\\n          as-element=\\\"stock\\\"\\n          data-value.bind=\\\"product.selectedStock\\\"\\n          product.bind=\\\"product\\\"\\n          warehouses.bind=\\\"warehouses\\\"></td>\\n\\n        <td\\n          class=\\\"text-end text-nowrap mc-price\\\"\\n          as-element=\\\"price\\\"\\n          prices.bind=\\\"product.selectedStock ? product.selectedStock.prices : product.prices\\\"\\n          display-price.bind=\\\"product.selectedStock ? product.selectedStock.displayPrice : null\\\"\\n          product.bind=\\\"product\\\"\\n          stock-item.bind=\\\"product.selectedStock\\\"></td>\\n\\n        <td if.bind=\\\"options.showAmount\\\" class=\\\"text-center text-nowrap\\\">\\n          <input\\n            type=\\\"number\\\"\\n            class=\\\"form-control form-control-sm mx-auto cart-product-amount\\\"\\n            min.bind=\\\"getMinimumQuantity(product)\\\"\\n            step.bind=\\\"getMinimumQuantity(product)\\\"\\n            value.bind=\\\"product.quantity\\\" />\\n        </td>\\n\\n        <td if.bind=\\\"options.showSum\\\" class=\\\"text-end text-nowrap\\\">\\n          <span>${(product.selectedStock ? product.selectedStock.displayPrice * product.quantity : null) | currencyFormat}</span>\\n        </td>\\n\\n        <td if.bind=\\\"options.showAddToCart\\\" class=\\\"text-nowrap clickable mc-action\\\">\\n          <add-to-cart product.bind=\\\"product\\\"></add-to-cart>\\n        </td>\\n      </tr>\\n\\n      <tr\\n        if.bind=\\\"appConfig.userSettings.detailsInProductPage || appConfig.userSettings.imagesInProductPage\\\"\\n        class=\\\"clickable info-row\\\"\\n        data-disablesort=\\\"true\\\"\\n        data-product-id.bind=\\\"product.id\\\"\\n        click.delegate=\\\"toggleExtraRow($event.target, product)\\\">\\n        <td colspan.bind=\\\"colSpan\\\">\\n          <template if.bind=\\\"appConfig.userSettings.detailsInProductPage\\\">\\n            <span repeat.for=\\\"info of product.info\\\" class=\\\"text-muted small mx-1\\\">\\n              <a if.bind=\\\"infoHref(info)\\\" href.bind=\\\"infoHref(info)\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\" click.delegate=\\\"$event.stopPropagation() || true\\\">${infoLabel(info)}</a>\\n              <template else><b>${infoLabel(info)}:</b> ${infoValue(info)}</template>\\n            </span>\\n          </template>\\n          <span class=\\\"text-muted small mt-1\\\" data-extra-not-found.bind=\\\"product.id\\\"></span>\\n        </td>\\n      </tr>\\n\\n      <tr class=\\\"extra-row\\\" data-disablesort=\\\"true\\\" data-product-id.bind=\\\"product.id\\\">\\n        <td colspan.bind=\\\"colSpan\\\" class=\\\"p-0\\\">\\n          <extra-row product.bind=\\\"product\\\"></extra-row>\\n        </td>\\n      </tr>\\n    </tbody>\\n  </table>\\n\\n  <div if.bind=\\\"currentPage == lastPage && extendedSearch == false\\\" class=\\\"d-flex justify-content-center\\\">\\n    <button type=\\\"button\\\" class=\\\"btn btn-primary mb-3\\\" click.delegate=\\\"activateExtendedSearch()\\\">\\n      ${'components.products.buttons.load-more' & t}\\n    </button>\\n  </div>\\n\\n  <pager current-page.two-way=\\\"currentPage\\\" last-page.bind=\\\"lastPage\\\"></pager>\\n\\n  <gallery if.bind=\\\"appConfig.userSettings.imagesInProductPage\\\" products.bind=\\\"products\\\"></gallery>\\n\\n  <span id=\\\"d-lg-none\\\" class=\\\"d-lg-none\\\"></span>\\n</template>\\n\";","import { Utils } from \"utils/helpers/utils\";\nimport { LogManager, autoinject, bindable } from \"aurelia-framework\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { ProductService } from \"services/product/product-service\";\nimport { I18N } from \"aurelia-i18n\";\n\nexport const log = LogManager.getLogger(\"app.components.report-button\");\n\n@autoinject\nexport class ReportButtonCustomElement {\n  @bindable product: IProduct;\n\n  constructor(private i18n: I18N, private productService: ProductService) {}\n\n  sendProductReport(product: IProduct, reportText: string) {\n    this.productService\n      .postReportError(product.code, reportText, product.id)\n      .then(() => {\n        Utils.showSuccessToast(this.i18n.tr(\"components.products.messages.error-reported\"));\n      })\n      .catch(() => {\n        Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.report-error\"));\n      });\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n\\n  <a\\n    class=\\\"icon-link icon-link-hover text-reset\\\"\\n    data-bs-toggle=\\\"modal\\\"\\n    data-bs-target=\\\"#id${product.id}\\\">\\n    <i\\n      class=\\\"bi bi-exclamation-diamond clickable-important\\\"\\n      tooltip=\\\"${'components.products.tooltips.faulty-product' & t}\\\"></i>\\n  </a>\\n  <div class=\\\"modal fade\\\" id=\\\"id${product.id}\\\" tabindex=\\\"-1\\\" aria-hidden=\\\"true\\\">\\n    <div class=\\\"modal-dialog modal-dialog-centered\\\">\\n      <div class=\\\"modal-content\\\">\\n        <div class=\\\"modal-header\\\">\\n          <h1 class=\\\"modal-title fs-5\\\">\\n            ${product.code} ${'components.report-modal.report-faulty' & t}\\n          </h1>\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn-close clickable-important\\\"\\n            data-bs-dismiss=\\\"modal\\\"\\n            aria-label=\\\"Close\\\"></button>\\n        </div>\\n        <div class=\\\"modal-body\\\">\\n          <form>\\n            <div class=\\\"form-group\\\">\\n              <textarea\\n                class=\\\"form-control\\\"\\n                placeholder=\\\"${'components.report-modal.describe-fault' & t}\\\"\\n                value.bind=\\\"reportText\\\"></textarea>\\n            </div>\\n          </form>\\n        </div>\\n        <div class=\\\"modal-footer\\\">\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-secondary clickable-important\\\"\\n            data-bs-dismiss=\\\"modal\\\">\\n            ${'components.report-modal.close-button' & t}\\n          </button>\\n          <button\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-primary clickable-important\\\"\\n            click.trigger=\\\"sendProductReport(product, reportText)\\\">\\n            ${'components.report-modal.send-button' & t}\\n          </button>\\n        </div>\\n      </div>\\n    </div>\\n  </div>\\n</template>\\n\";","import { AppConfig } from \"app-config\";\nimport { ICartProduct } from \"domain/Cart/ICartProduct\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { ProductService } from \"services/product/product-service\";\nimport { autoinject, LogManager, bindable } from \"aurelia-framework\";\nimport { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { IProduct } from \"domain/Product/IProduct\";\nimport { IStockItem } from \"domain/Product/IStockItem\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { PriceHelper } from \"utils/helpers/price-helper\";\nimport { ProductExtraHelper } from \"utils/helpers/product-extra-helper\";\n\nexport const log = LogManager.getLogger(\"app.components.stock\");\n\n@autoinject\nexport class StockCustomElement {\n  @bindable product: IProduct | ICartProduct;\n  @bindable warehouses: IWarehouse[];\n  isInStock = Utils.isInStock;\n\n  constructor(\n    private i18n: I18N,\n    private productService: ProductService,\n    private appConfig: AppConfig,\n    private eventAggregator: EventAggregator\n  ) {}\n\n  attached() {\n    if (this.product == null) {\n      Utils.showErrorToast(log, this.i18n.tr(\"components.stock.errors.load\"));\n      return;\n    }\n  }\n\n  getValue(stock: string): number {\n    switch (stock) {\n      case \"e\":\n        return 11;\n      case \"t\":\n        return -2;\n      case \"l\":\n        return -1;\n      default:\n        return Number(stock);\n    }\n  }\n\n  takeIntoStockUserWish(productCode: string, productId: number) {\n    const confirmation = confirm(\n      this.i18n.tr(\"components.products.messages.confirm-take-into-stock-wish\")\n    );\n\n    if (confirmation == false) return;\n\n    this.productService\n      .postProductStockRequest(productCode, productId)\n      .then(() => {\n        Utils.showSuccessToast(\n          this.i18n.tr(\"components.products.messages.take-into-stock-wish-received\")\n        );\n      })\n      .catch(() => {\n        Utils.showErrorToast(log, this.i18n.tr(\"components.products.errors.take-into-stock-wish\"));\n      });\n  }\n\n  getStockQuantity(warehouse: IWarehouse): string {\n    const stockItem = this.product.stock.find(x => x.warehouse.id === warehouse.id);\n    return stockItem?.quantity ?? \"0\";\n  }\n\n  updateStockFromWarehouse(warehouse: IWarehouse) {\n    let stockItem = this.product.stock.find(x => x.warehouse.id === warehouse.id);\n\n    if (!stockItem) {\n      stockItem = {\n        warehouse:\n          this.warehouses.find(x => x.id == warehouse.id) ??\n          this.warehouses.find(x => x.id == 0) ??\n          this.warehouses[0],\n        quantity: \"0\",\n        prices: this.product.prices ?? [],\n      };\n      PriceHelper.formatStockPrices([stockItem], this.appConfig.userSettings, this.i18n);\n    }\n\n    this.updateStock(stockItem);\n  }\n\n  updateStock(stockItem: IStockItem) {\n    if (!stockItem.warehouse.isAllowed) return;\n\n    this.product.selectedStock = stockItem;\n    this.snapToCartQuantityToMinimum(stockItem);\n\n    if (\"cartProductId\" in this.product) {\n      // SAL-283: an explicit choice replaces any automatic fallback row, so saving it moves the line.\n      (this.product as { fallbackStock?: unknown }).fallbackStock = undefined;\n      this.eventAggregator.publish(TKEvent.cartProductsWarehouseChanged, this.product); // TODO rethink this\n    }\n  }\n\n  allWarehousesNotAllowed() {\n    return this.product.stock.length > 0 && this.product.stock.every(x => !x.warehouse.isAllowed);\n  }\n\n  getNotAllowedStock() {\n    return this.product.stock.filter(x => !x.warehouse.isAllowed);\n  }\n\n  externalStockLabel(stockItem: IStockItem): string {\n    return (\n      ProductExtraHelper.getExternalWarehouseLabel(stockItem?.warehouse) ??\n      (Number(stockItem?.warehouse?.groupId) === 1\n        ? this.i18n.tr(\"components.products.headers.factory-warehouse\")\n        : this.i18n.tr(\"components.products.headers.partner-warehouse\"))\n    );\n  }\n\n  // External stock helpers: return external stock items grouped by warehouse.groupId\n  // (1 factory, 2 partner, 3 Dunlop, 4 Rehviladu). 2, 3 and 4 share the partner section.\n  getExternalStockByGroup(...groupIds: number[]): IStockItem[] {\n    if (!this.product || !this.product.externalStock) return [];\n    return this.product.externalStock.filter(s => s.warehouse && groupIds.includes(Number(s.warehouse.groupId)));\n  }\n\n  otherStockWarningNeeded(warehouse: IWarehouse) {\n    if (!warehouse) return false;\n    if (warehouse.isExternal) return true;\n\n    const warehouseId = warehouse.id;\n    const userWarehouseId = this.appConfig.userSettings.warehouseId;\n    const isCentral = warehouseId === 1;\n    const isKadaka = warehouseId === 3;\n    const isTartu = warehouseId === 21;\n\n    return !(warehouseId === userWarehouseId || isCentral || isKadaka || isTartu);\n  }\n  private snapToCartQuantityToMinimum(stockItem: IStockItem) {\n    const product = this.product as IProduct;\n    const quantity = parseInt(product.toCartQuantity ?? \"\", 10);\n    if (ProductExtraHelper.isValidMinimumQuantity(quantity, stockItem)) return;\n    product.toCartQuantity = String(ProductExtraHelper.getMinimumQuantity(stockItem));\n  }\n\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"utils/classes/tooltip\\\"></require>\\n\\n  <div class=\\\"d-flex justify-content-center align-items-center\\\">\\n    <div if.bind=\\\"product.selectedStock\\\" class=\\\"dropdown-center\\\">\\n      <button\\n        class=\\\"btn dropdown-toggle btn-outline-dark clickable-important jumping-icon-container\\\"\\n        type=\\\"button\\\"\\n        data-bs-toggle=\\\"dropdown\\\"\\n        aria-expanded=\\\"false\\\">\\n        <template if.bind=\\\"product.selectedStock.warehouse.isExternal\\\">${externalStockLabel(product.selectedStock)}:</template>\\n        <template else>${product.selectedStock.warehouse.name}:</template>\\n        ${ product.selectedStock.quantity | stockName:i18n}\\n\\n        <template if.bind=\\\"otherStockWarningNeeded(product.selectedStock.warehouse)\\\">\\n          <i\\n            if.bind=\\\"product.selectedStock.warehouse.isExternal == false\\\"\\n            class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n            tooltip=\\\"${'components.products.tooltips.other-stock-warning.warehouses.' + product.selectedStock.warehouse.id & t}\\\"></i>\\n          <i\\n            else\\n            class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n            tooltip=\\\"${'components.products.tooltips.other-stock-warning.external.' + product.selectedStock.warehouse.groupId & t}\\\"></i>\\n        </template>\\n      </button>\\n\\n      <ul class=\\\"dropdown-menu\\\">\\n        <li repeat.for=\\\"warehouse of warehouses\\\">\\n          <a\\n            class=\\\"dropdown-item jumping-icon-container\\\"\\n            click.delegate=\\\"updateStockFromWarehouse(warehouse)\\\">\\n            ${warehouse.name}: ${getStockQuantity(warehouse) | stockName:i18n }\\n            <i\\n              if.bind=\\\"otherStockWarningNeeded(warehouse)\\\"\\n              class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n              tooltip=\\\"${'components.products.tooltips.other-stock-warning.warehouses.' + warehouse.id & t}\\\"></i>\\n          </a>\\n        </li>\\n\\n        <li repeat.for=\\\"stockItem of getNotAllowedStock()\\\" class=\\\"non-clickable\\\">\\n          <a class=\\\"dropdown-item disabled\\\">\\n            ${stockItem.warehouse.name}: ${stockItem.quantity | stockName:i18n }\\n          </a>\\n        </li>\\n\\n        <template if.bind=\\\"product.externalStock.length > 0\\\">\\n          <template if.bind=\\\"getExternalStockByGroup(2, 3, 4).length > 0\\\">\\n            <li><hr class=\\\"dropdown-divider\\\" /></li>\\n            <li>\\n              <h6 class=\\\"dropdown-header\\\">${'components.products.headers.partner-warehouse' & t}</h6>\\n            </li>\\n            <li repeat.for=\\\"stockItem of getExternalStockByGroup(2, 3, 4)\\\">\\n              <a\\n                class=\\\"dropdown-item clickable-important jumping-icon-container\\\"\\n                click.delegate=\\\"updateStock(stockItem)\\\">\\n                ${stockItem.quantity | stockName:i18n } - ${ stockItem.displayPrice | currencyFormat\\n                }/${'components.stock.type.pcs' & t}\\n                <i\\n                  class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n                  tooltip=\\\"${'components.products.tooltips.other-stock-warning.external.' + stockItem.warehouse.groupId & t}\\\"></i>\\n              </a>\\n            </li>\\n          </template>\\n          <template if.bind=\\\"getExternalStockByGroup(1).length > 0\\\">\\n            <li><hr class=\\\"dropdown-divider\\\" /></li>\\n            <li>\\n              <h6 class=\\\"dropdown-header\\\">\\n                ${'components.products.headers.factory-warehouse' & t}\\n              </h6>\\n            </li>\\n            <li repeat.for=\\\"stockItem of getExternalStockByGroup(1)\\\">\\n              <a\\n                class=\\\"dropdown-item clickable-important jumping-icon-container\\\"\\n                click.delegate=\\\"updateStock(stockItem)\\\">\\n                ${stockItem.quantity | stockName:i18n } - ${ stockItem.displayPrice | currencyFormat\\n                }/${'components.stock.type.pcs' & t}\\n                <i\\n                  class=\\\"jumping-icon bi bi-exclamation-triangle text-warning\\\"\\n                  tooltip=\\\"${'components.products.tooltips.other-stock-warning.external.' + stockItem.warehouse.groupId & t}\\\"></i>\\n              </a>\\n            </li>\\n          </template>\\n        </template>\\n      </ul>\\n    </div>\\n    <span else class=\\\"spinner-border spinner-border-sm text-secondary\\\" role=\\\"status\\\"></span>\\n\\n    <a\\n      if.bind=\\\"product.stock.length == 0 && product.externalStock.length == 0 || allWarehousesNotAllowed()\\\"\\n      class=\\\"icon-link icon-link-hover text-reset\\\"\\n      click.trigger=\\\"takeIntoStockUserWish(product.code, product.id)\\\">\\n      <i\\n        class=\\\"bi bi-bell clickable-important\\\"\\n        tooltip=\\\"${'components.products.tooltips.interested-take-into-stock' & t}\\\"></i>\\n    </a>\\n  </div>\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { isRequestNoise } from \"utils/helpers/request-errors\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { CategoryService } from \"services/product/category-service\";\nimport { AppConfig } from \"app-config\";\nimport { Router, NavigationInstruction, PipelineResult } from \"aurelia-router\";\nimport { IParentItem } from \"domain/Base/IParentItem\";\nimport { LogManager, autoinject } from \"aurelia-framework\";\nimport $ from \"jquery\";\nimport \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.search.categories\");\n\n@autoinject\nexport class Categories {\n  // Cache\n  categories: IParentItem[];\n\n  constructor(\n    private router: Router,\n    private eventAggregator: EventAggregator,\n    private appConfig: AppConfig, // used by HTML\n    private categoryService: CategoryService,\n    private i18n: I18N,\n  ) {}\n\n  // called only once: when the site is opened (and the user probably isn't logged in yet)\n  activate() {\n    // If user is already logged in, but refreshed the page\n    if (this.appConfig.isLoggedIn) this.loadCategoryMenu();\n\n    // attached() was too late, the \"router:navigation:success\" event had already been fired\n    this.eventAggregator.subscribe(\n      \"router:navigation:success\",\n      (event: { instruction: NavigationInstruction; result: PipelineResult }) => {\n        const currentRoute = event.instruction.config.name;\n        if (!currentRoute) return;\n\n        // Run only after successful login\n        if (this.appConfig.isLoggedIn && this.categories === undefined) this.loadCategoryMenu();\n      },\n    );\n  }\n\n  // #region LOAD\n\n  loadCategoryMenu() {\n    this.categoryService\n      .fetchCategories()\n      .then(result => {\n        this.categories = result;\n        this.positionSubmenu();\n      })\n      .catch(error => {\n        if (isRequestNoise(error)) return Utils.handleRequestNoise(log, error, this.i18n);\n        Utils.showErrorToast(log, Utils.getErrorMessage(error, this.i18n));\n      });\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  openCategory(category: IParentItem) {\n    let id = category.id;\n\n    if (id == 6 || id == 7 || id == 8) {\n      // Car fitment categories (tyres/cat 10 use typed filters, not mark/model)\n      this.router.navigateToRoute(\"categoryManufacturers\", { categoryId: category.id });\n      return;\n    }\n\n    if (id == 54)\n      // 54 is alias for 10\n      id = 10;\n\n    this.router.navigateToRoute(\"categoryProducts\", {\n      categoryId: id,\n      page: 1,\n    });\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  positionSubmenu() {\n    $(() => {\n      // SAL-297: runs on every open, from viewport coordinates (getBoundingClientRect), so page\n      // scroll, resize and zoom since the last open are picked up without a reload.\n      function position(element: JQuery<HTMLElement>) {\n        const panel = element[0];\n        const level1 = document.getElementById(\"level-1-menu\");\n        const group = panel?.parentElement;\n        if (!panel || !level1 || !group) return;\n\n        const margin = 8;\n        const level1Rect = level1.getBoundingClientRect();\n        const groupRect = group.getBoundingClientRect();\n        const visibleTop = Math.max(level1Rect.top, 0);\n        // No bottom margin: same cap as before, so the columns match the Chrome reference.\n        const maxHeight = Math.max(window.innerHeight - visibleTop, 0);\n        const minHeight = Math.min(level1.clientHeight, maxHeight);\n\n        // Lay the columns out at their natural width first, then measure them.\n        element.removeClass(\"level-2-scroll\");\n        element.css({\n          position: \"absolute\",\n          top: visibleTop - groupRect.top + \"px\",\n          left: \"100%\",\n          width: \"10000px\",\n          \"max-width\": \"\",\n          \"min-height\": minHeight + \"px\",\n          \"max-height\": maxHeight + \"px\",\n          \"overflow-x\": \"hidden\",\n          \"overflow-y\": \"hidden\",\n        });\n\n        const panelRect = panel.getBoundingClientRect();\n        const style = getComputedStyle(panel);\n        let contentRight = panelRect.left;\n        for (const child of Array.from(panel.children))\n          contentRight = Math.max(contentRight, child.getBoundingClientRect().right);\n        const neededWidth =\n          contentRight -\n          panelRect.left +\n          parseFloat(style.paddingRight) +\n          parseFloat(style.borderRightWidth);\n\n        const viewportWidth = document.documentElement.clientWidth;\n        const availableWidth = Math.max(viewportWidth - panelRect.left - margin, 0);\n\n        if (neededWidth <= availableWidth) {\n          // Preferred: every column fully visible, no scrollbar.\n          element.css({ width: Math.ceil(neededWidth) + \"px\" });\n\n          // A single group taller than the height cap can't be split into columns: keep the\n          // columns, but let the panel scroll vertically so its last items stay reachable.\n          if (panel.scrollHeight > panel.clientHeight + 1) {\n            element.css({ \"overflow-y\": \"auto\" });\n            const scrollbar = panel.offsetWidth - panel.clientWidth;\n            if (scrollbar > 0) element.css({ width: Math.ceil(neededWidth) + scrollbar + \"px\" });\n          }\n          return;\n        }\n\n        // Fallback: no horizontal room. One column that scrolls inside the panel.\n        element.addClass(\"level-2-scroll\");\n        const width = Math.min(Math.max(availableWidth, 200), viewportWidth - 2 * margin);\n        element.css({\n          width: width + \"px\",\n          \"max-width\": \"\",\n          \"overflow-x\": \"auto\",\n          \"overflow-y\": \"auto\",\n        });\n\n        // Phones and narrow windows: no room right of level 1, so overlap it to stay on screen.\n        if (panelRect.left + width > viewportWidth - margin)\n          element.css({ left: viewportWidth - margin - width - groupRect.left + \"px\" });\n      }\n\n      // Submenu click support - (c) https://stackoverflow.com/a/45755948\n      $(\".dropdown-menu a.dropdown-toggle\").on(\"click\", function () {\n        if (!$(this).next().hasClass(\"show\"))\n          $(this).parents(\".dropdown-menu\").first().find(\".show\").removeClass(\"show\");\n\n        const subMenu = $(this).next(\".dropdown-menu\");\n        subMenu.toggleClass(\"show\");\n        if (subMenu.hasClass(\"show\")) position(subMenu);\n\n        return false;\n      });\n\n      $(\".level-2-menu .dropdown-item\").on(\"click\", function () {\n        $(this).parents().removeClass(\"hover-show show\");\n      });\n\n      $(\".dropdown-menu a.dropdown-toggle\").on(\"mouseenter\", function () {\n        if ($(\"#level-1-menu\").find(\".show\").length > 0) return;\n\n        const menu = $(this).next();\n        if (!menu.hasClass(\"hover-show\")) {\n          menu.addClass(\"hover-show\");\n          position(menu);\n        }\n      });\n      $(\".dropdown-menu a.dropdown-toggle\").on(\"mouseleave\", function () {\n        if ($(this).next(\".dropdown-menu:hover\").length == 0)\n          $(this).next().removeClass(\"hover-show\");\n      });\n      $(\".level-2-menu\").on(\"mouseleave\", function () {\n        if ($(this).prev(\".dropdown-toggle:hover\").length == 0) $(this).removeClass(\"hover-show\");\n      });\n    });\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n\\n  <div class=\\\"dropdown\\\">\\n    <button type=\\\"button\\\" class=\\\"btn btn-outline-primary dropdown-toggle\\\" data-bs-toggle=\\\"dropdown\\\">\\n      ${'pages.category.button'& t}\\n    </button>\\n\\n    <div id=\\\"level-1-menu\\\" class=\\\"dropdown-menu\\\">\\n      <div repeat.for=\\\"category of categories\\\" class=\\\"btn-group dropdown-submenu dropend w-100\\\">\\n        <a if.bind=\\\"category.children.length < 1\\\" class=\\\"dropdown-item\\\" href=\\\"#\\\"\\n           click.delegate=\\\"openCategory(category)\\\">\\n          ${('pages.category.categories.' + category.id) & t: { 'defaultValue': category.name }}\\n        </a>\\n        <template else>\\n          <a class=\\\"dropdown-item dropdown-toggle\\\" role=\\\"button\\\" href=\\\"#\\\">\\n            ${('pages.category.categories.' + category.id) & t: { 'defaultValue': category.name }}\\n          </a>\\n\\n          <div class=\\\"dropdown-menu level-2-menu col-sm\\\">\\n            <div repeat.for=\\\"subcategory of category.children\\\">\\n              <a if.bind=\\\"subcategory.children.length < 1\\\"\\n                 class=\\\"dropdown-item dropdown-header font-weight-bold text-primary\\\" href=\\\"#\\\"\\n                 click.delegate=\\\"openCategory(subcategory)\\\">\\n                ${('pages.category.categories.' + subcategory.id) & t: { 'defaultValue':\\n                subcategory.name }}\\n              </a>\\n              <template else>\\n                <h6 class=\\\"dropdown-header text-primary\\\">\\n                  ${('pages.category.categories.' + subcategory.id) & t: { 'defaultValue':\\n                  subcategory.name }}\\n                </h6>\\n\\n                <a repeat.for=\\\"subcategory2 of subcategory.children\\\" class=\\\"dropdown-item\\\"\\n                   click.delegate=\\\"openCategory(subcategory2)\\\" href=\\\"#\\\">\\n                  ${('pages.category.categories.' + subcategory2.id) & t: { 'defaultValue':\\n                  subcategory2.name }}\\n                </a>\\n              </template>\\n            </div>\\n          </div>\\n        </template>\\n      </div>\\n    </div>\\n  </div>\\n\\n</template>\\n\";","import { TKEvent } from \"utils/enums/TKEvent\";\nimport { SearchType } from \"utils/enums/SearchType\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { AppConfig } from \"app-config\";\nimport { Router, NavigationInstruction, PipelineResult } from \"aurelia-router\";\nimport { LogManager, autoinject, observable } from \"aurelia-framework\";\nimport { decodeSearchRouteQuery, encodeSearchRouteQuery, shouldNavigateForQuery } from \"utils/helpers/search-route\";\n\nexport const log = LogManager.getLogger(\"app.search.search-bar\");\n\n@autoinject\nexport class SearchBar {\n  // Main variables\n  @observable query: string;\n  @observable type: SearchType;\n  page = 1;\n  extendedSearch = false;\n\n  // Search delay variables\n  searchDelayMilliseconds = 500;\n  searchTimer: NodeJS.Timeout;\n\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    // 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\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);\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) {\n    if (query.length < 3) return;\n\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    const that = this;\n    clearTimeout(this.searchTimer);\n    this.searchTimer = setTimeout(function () {\n      that.search(query, page, type, extendedSearch);\n    }, this.searchDelayMilliseconds);\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\\n    <select class=\\\"form-select\\\" value.bind=\\\"type\\\">\\n      <option model.bind=\\\"0\\\">${'components.search-bar.types.all' & t}</option>\\n      <option model.bind=\\\"1\\\">${'components.search-bar.types.code' & t}</option>\\n      <option model.bind=\\\"2\\\">${'components.search-bar.types.name' & t}</option>\\n      <option model.bind=\\\"3\\\">${'components.search-bar.types.tecdoc' & t}</option>\\n      <option model.bind=\\\"4\\\">${'components.search-bar.types.ean' & t}</option>\\n      <option model.bind=\\\"5\\\">${'components.search-bar.types.precise' & t}</option>\\n    </select>\\n\\n    <!--If this breaks, add width-inital to style.css (input.group.fix)-->\\n    <compose view-model=\\\"components/car/car-tree\\\"></compose>\\n  </div>\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { Router } from \"aurelia-router\";\nimport { IRvsOrder } from \"domain/Sale/IRvsOrder\";\nimport { LogManager, autoinject, bindable } from \"aurelia-framework\";\nimport $ from \"jquery\";\nimport \"bootstrap\";\nimport { OrderService } from \"services/sale/order-service\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { Collapse } from \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.components.order-list\");\n\n@autoinject\nexport class OrderListCustomElement {\n  @bindable orders: IRvsOrder[];\n\n  options = {\n    showInvoiceId: false,\n    showWarehouse: false,\n    showTransport: false,\n    showAddToCart: true,\n    showAddToReturn: true,\n    showConvertToCart: true,\n  };\n\n  constructor(\n    private orderService: OrderService,\n    private eventAggregator: EventAggregator,\n    private router: Router,\n    private i18n: I18N\n  ) {}\n\n  attached() {\n    this.orders.forEach((order) => {\n      order.originalId = order.originalId.replace(\"*INTERNET*\", \"\");\n    });\n  }\n\n  convertToCart(order: IRvsOrder) {\n    this.orderService\n      .convertRvsOrderToCart(order.id)\n      .then(() => {\n        this.eventAggregator.publish(TKEvent.cartProductsChanged);\n        Utils.showSuccessToast(\n          this.i18n.tr(\"pages.orders.messages.convert-to-cart\")\n        );\n      })\n      .catch((error) =>\n        Utils.showErrorToast(\n          log,\n          Utils.getErrorMessage(error, this.i18n)\n        )\n      );\n  }\n\n  toggleProductList(target: HTMLElement, order: IRvsOrder) {\n    $(() => {\n      // Check if child element was clicked instead\n      if (\n        $(target).prop(\"tagName\") != \"TD\" &&\n        $(target).prop(\"tagName\") != \"TR\"\n      )\n        return;\n\n      const productListElement = document.querySelector(\n        `[data-product-list=\"${order.id}\"]`\n      );\n      if (productListElement)\n        new Collapse(productListElement, {\n          parent: \"#accordion-order\",\n        }).toggle();\n    });\n  }\n\n  canConvertToCart(order: IRvsOrder): boolean {\n    return order.products.some((p) => Number(p.amount) > 0);\n  }\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/mobile-cards\\\"></require>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"components/cart/nested-cart-product-list\\\"></require>\\n\\n  <table mobile-cards id=\\\"accordion-order\\\" class=\\\"table w-100\\\">\\n    <thead>\\n      <tr>\\n        <th>${'pages.orders.headers.number' & t}</th>\\n        <th>${'pages.orders.headers.original-number' & t}</th>\\n        <th>${'pages.orders.headers.comments' & t}</th>\\n        <th class=\\\"text-end\\\">${'pages.orders.headers.total' & t}</th>\\n        <th class=\\\"text-end\\\" if.bind=\\\"options.showConvertToCart\\\">\\n          ${'components.products.headers.add-to-cart' & t}\\n        </th>\\n      </tr>\\n    </thead>\\n\\n    <tbody repeat.for=\\\"order of orders\\\" class=\\\"hover\\\">\\n      <tr class=\\\"clickable\\\" click.delegate=\\\"toggleProductList($event.target, order)\\\">\\n        <td><span>${order.id}</span></td>\\n        <td><span>${order.originalId}</span></td>\\n        <td><span>${order.comment}</span></td>\\n        <td class=\\\"text-end\\\" data-value.bind=\\\"order.total\\\">\\n          <span>${order.total | currencyFormat}</span>\\n        </td>\\n        <td class=\\\"text-end clickable mc-action\\\" if.bind=\\\"options.showConvertToCart\\\">\\n          <button\\n            if.bind=\\\"canConvertToCart(order)\\\"\\n            type=\\\"button\\\"\\n            class=\\\"btn btn-success btn-sm\\\"\\n            click.delegate=\\\"convertToCart(order)\\\">\\n            ${'components.products.buttons.add-to-cart' & t}\\n          </button>\\n        </td>\\n      </tr>\\n\\n      <tr class=\\\"product-list-row hover\\\" data-disablesort=\\\"true\\\" data-order.bind=\\\"order.id\\\">\\n        <td colspan=\\\"7\\\" class=\\\"p-0\\\">\\n          <div\\n            class=\\\"collapse px-5\\\"\\n            data-product-list.bind=\\\"order.id\\\"\\n            data-bs-parent=\\\"#accordion-order\\\">\\n            <nested-cart-product-list\\n              products.bind=\\\"order.products\\\"\\n              rvs-order.bind=\\\"order\\\"\\n              options.bind=\\\"options\\\">\\n            </nested-cart-product-list>\\n          </div>\\n        </td>\\n      </tr>\\n    </tbody>\\n  </table>\\n</template>\\n\";","import { bindable } from 'aurelia-framework';\n\nexport class OrderSearchBarCustomElement {\n  @bindable searchIcon: string;\n  @bindable searchPlaceholder: string;\n\n  @bindable searchText: string;\n  @bindable searchDateFrom: string;\n  @bindable searchDateTo: string;\n\n  hasFocus = true;\n}\n","module.exports = \"<template>\\n  <div class=\\\"input-group mb-2 order-search-bar\\\">\\n    <i class='bi-search input-group-text'></i>\\n    <i class='bi-${searchIcon} input-group-text'></i>\\n\\n    <input focus.bind=\\\"hasFocus\\\" type=\\\"text\\\" class=\\\"form-control\\\"\\n           placeholder.bind=\\\"searchPlaceholder\\\" value.two-way=\\\"searchText\\\">\\n\\n    <i class='bi-calendar-range input-group-text'></i>\\n    <input type=\\\"date\\\" class=\\\"form-control\\\" value.two-way=\\\"searchDateFrom\\\" placeholder=\\\"yyyy-mm-dd\\\"\\n           pattern=\\\"^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9])$\\\">\\n\\n    <i class='bi-three-dots input-group-text'></i>\\n    <input type=\\\"date\\\" class=\\\"form-control\\\" value.two-way=\\\"searchDateTo\\\" placeholder=\\\"yyyy-mm-dd\\\"\\n           pattern=\\\"^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9])$\\\">\\n  </div>\\n</template>\\n\";","import { I18N } from \"aurelia-i18n\";\nimport { IWarehouse } from \"domain/Client/IWarehouse\";\nimport { AppConfig } from \"app-config\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { Router } from \"aurelia-router\";\nimport { LogManager, autoinject, bindable, observable } from \"aurelia-framework\";\nimport { ICart } from \"domain/Cart/ICart\";\nimport { ReturnService } from \"services/sale/return-service\";\nimport printJS from \"print-js\";\n\nexport const log = LogManager.getLogger(\"app.components.return.index\");\n\n@autoinject\nexport class ReturnIndexCustomElement {\n  warehouses: IWarehouse[];\n\n  returnCart: ICart;\n  error: string;\n\n  @observable({ changeHandler: \"queryChanged\" }) searchText = \"\";\n  @observable({ changeHandler: \"queryChanged\" }) searchDateFrom = \"\";\n  @observable({ changeHandler: \"queryChanged\" }) searchDateTo = \"\";\n\n  @bindable comment = \"\";\n\n  totalWithoutVat = 0;\n  totalVat = 0;\n  totalWithVat = 0;\n\n  options = {\n    showImages: false,\n    showEan: false,\n    showStock: false,\n    showWarehouse: false,\n    showReason: true,\n    showDisplayPrice: false,\n    isReturnCart: true,\n  };\n\n  constructor(\n    private returnService: ReturnService,\n    private router: Router,\n    private eventAggregator: EventAggregator,\n    private appConfig: AppConfig,\n    private i18n: I18N\n  ) {\n    this.eventAggregator.subscribe(TKEvent.cartProductsChanged, () => {\n      this.updateTotal();\n    });\n    this.eventAggregator.subscribe(TKEvent.returnCartChanged, (cart: ICart) => {\n      this.returnCart = cart;\n    });\n    this.eventAggregator.subscribeOnce(TKEvent.userSettingsLoaded, () => {\n      this.loadReturn();\n    });\n  }\n\n  attached() {\n    if (this.appConfig.userSettings) this.loadReturn();\n  }\n\n  // #region LISTENERS, OBSERVABLES\n\n  updateTotal() {\n    if (this.returnCart == undefined || this.returnCart.products == undefined) return;\n\n    this.totalWithoutVat = 0;\n\n    this.returnCart.products.forEach(p => {\n      if (p.finalPrice != null) this.totalWithoutVat += p.finalPrice * p.quantity;\n    });\n    this.totalWithoutVat = Utils.round(this.totalWithoutVat);\n\n    this.totalVat = Utils.round(this.totalWithoutVat * AppConfig.vatRate);\n    this.totalWithVat = this.totalWithoutVat + this.totalVat;\n  }\n\n  queryChanged(newValue: string, oldValue: string) {\n    // Required value haven't been set yet\n    if (oldValue === undefined) return;\n\n    const dateRegex = /^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9])$/;\n\n    if (this.searchDateFrom && !this.searchDateFrom.match(dateRegex)) return;\n\n    if (this.searchDateTo && !this.searchDateTo.match(dateRegex)) return;\n\n    const params = {\n      page: 1,\n    } as any;\n\n    if (this.searchText != \"\") params.query = Utils.encode(this.searchText);\n\n    if (this.searchDateFrom != \"\") params.dateFrom = Utils.encode(this.searchDateFrom);\n\n    if (this.searchDateTo != \"\") params.dateTo = Utils.encode(this.searchDateTo);\n\n    this.router.navigateToRoute(\"invoiceIndex\", params);\n  }\n\n  // #endregion\n\n  // #region LOAD\n\n  loadReturn() {\n    this.returnService\n      .fetchCurrent()\n      .then(result => {\n        this.returnCart = result;\n\n        this.updateTotal();\n      })\n      .catch(error => (this.error = Utils.getErrorMessage(error, this.i18n)));\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  sendReturn() {\n    let cancel = false;\n    this.returnCart.products.forEach(product => {\n      if (cancel) return;\n\n      if (!product.comment || !product.comment.trim()) cancel = true;\n    });\n\n    if (cancel) {\n      Utils.showErrorToast(log, this.i18n.tr(\"pages.returns.errors.cart.product-reason-missing\"));\n      return;\n    }\n\n    this.returnService\n      .sendReturn(this.comment)\n      .then(updatedCart => {\n        const returnId = this.returnCart.id;\n\n        this.returnCart = updatedCart;\n        this.updateTotal();\n        this.eventAggregator.publish(TKEvent.returnCartChanged, updatedCart);\n        this.eventAggregator.publish(TKEvent.cartProductsChanged);\n        this.eventAggregator.publish(TKEvent.returnSent);\n\n        if (confirm(this.i18n.tr(\"pages.returns.messages.print-message\")))\n          this.printMessage(returnId);\n      })\n      .catch(() => Utils.showErrorToast(log, this.i18n.tr(\"pages.returns.errors.cart.send\")));\n  }\n\n  clearReturn() {\n    if (!confirm(this.i18n.tr(\"pages.returns.messages.confirm-clear\"))) return;\n\n    this.returnService.clearReturnCart().then(() => {\n      this.loadReturn();\n      this.eventAggregator.publish(TKEvent.cartProductsChanged);\n    });\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  printMessage(id: number) {\n    this.returnService.fetchReturnText(id).then(result => {\n      printJS({ printable: result, type: \"raw-html\" });\n    });\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n  <require from=\\\"components/cart/cart-product-list\\\"></require>\\n  <require from=\\\"components/sale/order/order-search-bar\\\"></require>\\n  <require from=\\\"components/general/loading\\\"></require>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n\\n  <order-search-bar search-icon=\\\"file-earmark-text\\\"\\n                    search-placeholder=\\\"${'pages.invoices.messages.hint' & t}\\\"\\n                    search-date-from.two-way=\\\"searchDateFrom\\\" search-date-to.two-way=\\\"searchDateTo\\\"\\n                    search-text.two-way=\\\"searchText\\\">\\n  </order-search-bar>\\n\\n  <template if.bind=\\\"returnCart.products !== undefined && returnCart.products.length !== 0\\\">\\n    <cart-product-list products.bind=\\\"returnCart.products\\\" options.bind=\\\"options\\\">\\n    </cart-product-list>\\n\\n    <div class=\\\"input-group mt-3\\\">\\n      <div class=\\\"input-group-prepend\\\">\\n        <button type=\\\"button\\\" class=\\\"btn btn-danger\\\" click.trigger=\\\"clearReturn()\\\">\\n          ${'pages.returns.buttons.clear' & t}\\n        </button>\\n      </div>\\n\\n      <span class=\\\"input-group-text form-control\\\"></span>\\n\\n      <div class=\\\"input-group-append\\\">\\n        <span class=\\\"input-group-text text-end\\\">\\n          </b>${'pages.returns.fields.total' & t} ${totalWithVat | currencyFormat}</b>\\n        </span>\\n      </div>\\n    </div>\\n\\n    <div class=\\\"input-group mt-0\\\">\\n      <textarea class=\\\"form-control\\\" rows=\\\"1\\\" value.bind=\\\"comment\\\"\\n                placeholder=\\\"${'pages.returns.fields.comment-hint' & t}\\\"></textarea>\\n\\n      <div class=\\\"input-group-append\\\">\\n        <button type=\\\"button\\\" class=\\\"btn btn-success\\\" click.trigger=\\\"sendReturn()\\\">\\n          ${'pages.returns.buttons.submit' & t}\\n        </button>\\n      </div>\\n    </div>\\n  </template>\\n\\n  <div else class=\\\"mt-3\\\">\\n    <loading error.bind=\\\"error\\\" error-title=\\\"${'pages.returns.errors.cart.load' & t}\\\"\\n             error-details-class=\\\"font-italic\\\" error-details.bind=\\\"error\\\"\\n             not-found.bind=\\\"returnCart.products !== undefined && returnCart.products.length == 0\\\"\\n             not-found-title=\\\"${'pages.returns.errors.cart.not-found.title' & t}\\\"\\n             not-found-details=\\\"${'pages.returns.errors.cart.not-found.details' & t}\\\">\\n    </loading>\\n  </div>\\n\\n</template>\\n\";","import { encodeSearchRouteQuery } from \"utils/helpers/search-route\";\nimport { EventAggregator } from \"aurelia-event-aggregator\";\nimport { TKEvent } from \"utils/enums/TKEvent\";\nimport { ReturnService } from \"services/sale/return-service\";\nimport { I18N } from \"aurelia-i18n\";\nimport { SearchType } from \"utils/enums/SearchType\";\nimport { AppConfig } from \"app-config\";\nimport { ICart } from \"domain/Cart/ICart\";\nimport { Utils } from \"utils/helpers/utils\";\nimport { LogManager, autoinject, observable } from \"aurelia-framework\";\nimport { Router } from \"aurelia-router\";\nimport $ from \"jquery\";\nimport \"bootstrap\";\nimport printJS from \"print-js\";\nimport { Collapse } from \"bootstrap\";\n\nexport const log = LogManager.getLogger(\"app.components.return.list\");\n\n@autoinject\nexport class ReturnListCustomElement {\n  returns: ICart[] | undefined;\n  error: string;\n\n  @observable({ changeHandler: \"queryChanged\" }) currentPage = 1;\n  lastPage = 1;\n\n  options = {\n    showInvoiceId: true,\n    showWarehouse: false,\n    showTransport: false,\n    showAddToCart: false,\n    showAddToReturn: false,\n  };\n\n  constructor(\n    private returnService: ReturnService,\n    private router: Router,\n    private appConfig: AppConfig, // used by html\n    private eventAggregator: EventAggregator,\n    private i18n: I18N\n  ) {\n    this.eventAggregator.subscribeOnce(TKEvent.userSettingsLoaded, () => {\n      this.loadReturns();\n    });\n    this.eventAggregator.subscribe(TKEvent.returnSent, () => {\n      this.loadReturns();\n    });\n  }\n\n  attached() {\n    if (this.appConfig.userSettings) this.loadReturns();\n  }\n\n  queryChanged(newValue: number | string, oldValue: number | string) {\n    // Required value haven't been set yet\n    if (oldValue === undefined) return;\n\n    // Clear the old result so the loading icon could activate again\n    this.returns = undefined;\n\n    // Since navigating to the same route doesn't actually refresh the page\n    if (this.appConfig.userSettings) this.loadReturns();\n  }\n\n  // #region LOAD\n\n  loadReturns() {\n    this.returnService\n      .fetchReturns(this.currentPage)\n      .then((result) => {\n        this.returns = result.items;\n        this.currentPage = result.currentPage;\n        this.lastPage = result.lastPage;\n\n        this.returns.forEach((returnCart) => {\n          // make it UTC ISO8601\n          returnCart.closedDateTime = new Date(returnCart.closedDateTime + \"Z\");\n\n          returnCart.total = 0;\n          returnCart.products.forEach(\n            (product) =>\n              (returnCart.total += (product.finalPrice ?? 0) * product.quantity)\n          );\n        });\n\n        this.sortedListener();\n        Utils.loadSortable();\n      })\n      .catch((error) => (this.error = Utils.getErrorMessage(error, this.i18n)));\n  }\n\n  // #endregion\n\n  // #region ACTIONS\n\n  searchProduct(query: string) {\n    this.router.navigateToRoute(\"searchResult\", {\n      query: encodeSearchRouteQuery(query),\n      page: 1,\n      type: SearchType.Precise,\n    });\n  }\n\n  toggleProductList(target: HTMLElement, returnCart: ICart) {\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 collapseElement = document.querySelector(\n        `[data-product-list=\"${returnCart.id}\"]`\n      );\n\n      if (collapseElement)\n        return new Collapse(collapseElement, {\n          parent: \"#accordion-invoice\",\n        }).toggle();\n    });\n  }\n\n  // #endregion\n\n  // #region HELPERS\n\n  sortedListener() {\n    $(() => {\n      $(\".sortable\").on(\"sorted\", function () {\n        // Move product list rows along with their parent order row when sorted\n        $(this)\n          .find(\".product-list-row\")\n          .each(function () {\n            $(this).insertAfter(\n              $(`.return-row[data-return=\"${$(this).attr(\"data-return\")}\"]`)\n            );\n          });\n      });\n    });\n  }\n\n  printMessage(returnCart: ICart) {\n    returnCart.loading = true;\n    this.returnService\n      .fetchReturnText(returnCart.id)\n      .then((result) => {\n        printJS({ printable: result, type: \"raw-html\" });\n      })\n      .finally(() => (returnCart.loading = false));\n  }\n\n  // #endregion\n}\n","module.exports = \"<template>\\n  <require from=\\\"utils/classes/mobile-cards\\\"></require>\\n  <require from=\\\"components/general/loading\\\"></require>\\n  <require from=\\\"components/general/pager\\\"></require>\\n  <require from=\\\"components/cart/nested-cart-product-list\\\"></require>\\n  <require from=\\\"utils/classes/value-converters\\\"></require>\\n  <require from=\\\"!style-loader!css-loader!bootstrap-sortable/Contents/bootstrap-sortable.css\\\">\\n  </require>\\n\\n  <template if.bind=\\\"returns !== undefined && returns.length > 0\\\">\\n    <table mobile-cards id=\\\"accordion-invoice\\\"\\n           class=\\\"table table-borderless table-sm table-responsive-md sortable accordion\\\">\\n      <thead>\\n        <tr>\\n          <th data-defaultsign=\\\"nospan\\\">${'pages.returns.headers.number' & t}</th>\\n          <th data-defaultsign=\\\"nospan\\\">${'pages.returns.headers.creator' & t}</th>\\n          <th data-defaultsign=\\\"nospan\\\">${'pages.returns.headers.created' & t}</th>\\n          <th data-defaultsign=\\\"nospan\\\">${'pages.returns.headers.comments' & t}</th>\\n          <th data-defaultsign=\\\"nospan\\\" class=\\\"text-end\\\">${'pages.returns.headers.total' & t}</th>\\n          <th data-defaultsort=\\\"disabled\\\"></th>\\n        </tr>\\n      </thead>\\n      ​\\n      <tbody repeat.for=\\\"returnCart of returns\\\" class=\\\"hover\\\">\\n        <tr class=\\\"return-row clickable\\\" data-order.bind=\\\"returnCart.id\\\"\\n            click.delegate=\\\"toggleProductList($event.target, returnCart)\\\">\\n          <td><span>${returnCart.id}</span></td>\\n          <td><span>${returnCart.creator}</span></td>\\n          <td data-dateformat=\\\"${appConfig.datetimeFormat}\\\">\\n            <span>${returnCart.closedDateTime | datetimeFormat}</span>\\n          </td>\\n          <td class=\\\"mc-full\\\"><span>${returnCart.comment}</span></td>\\n          <td class=\\\"text-end\\\" data-value.bind=\\\"returnCart.total\\\">\\n            <span>${returnCart.total | currencyFormat}</span>\\n          </td>\\n          <td class=\\\"text-end mc-action ${returnCart.loading ? 'loading' : ''}\\\">\\n            <a href=\\\"#\\\" type=\\\"button\\\" click.trigger=\\\"printMessage(returnCart)\\\">\\n              ${'pages.returns.buttons.print' & t}\\n            </a>\\n          </td>\\n        </tr>\\n\\n        <tr class=\\\"product-list-row hover\\\" data-disablesort=\\\"true\\\" data-order.bind=\\\"returnCart.id\\\">\\n          <td colspan=\\\"6\\\" class=\\\"p-0\\\">\\n            <div class=\\\"collapse px-5\\\" data-bs-parent=\\\"#accordion-invoice\\\"\\n                 data-product-list.bind=\\\"returnCart.id\\\">\\n              <nested-cart-product-list products.bind=\\\"returnCart.products\\\" options.bind=\\\"options\\\">\\n              </nested-cart-product-list>\\n            </div>\\n          </td>\\n        </tr>\\n      </tbody>\\n    </table>\\n\\n    <pager current-page.two-way=\\\"currentPage\\\" last-page.bind=\\\"lastPage\\\"></pager>\\n  </template>\\n\\n  <loading else error.bind=\\\"error\\\" error-title=\\\"${'pages.returns.errors.history.load' & t}\\\"\\n           error-details.bind=\\\"error\\\" not-found.bind=\\\"returns !== undefined && returns.length == 0\\\"\\n           not-found-title=\\\"${'pages.returns.errors.history.not-found.title' & t}\\\"\\n           not-found-details=\\\"${'pages.returns.errors.history.not-found.details' & t}\\\">\\n  </loading>\\n\\n</template>\\n\";","// SAL-283: the server stores each cart line's origin at add/move (0 Internal, 1 Factory, 2 Partner).\n// Lines added before SAL-283 have no origin; only those still fall back to externalWarehouseId.\nexport const enum Origin {\n  Internal = 0,\n  Factory = 1,\n  Partner = 2,\n}\n\nexport const FACTORY_GROUP_ID = 1;\nexport const PARTNER_GROUP_ID = 2;\n\ntype OriginLine = { origin?: Origin | null; externalWarehouseId?: number | null };\n\nexport function hasStoredOrigin(product: OriginLine): boolean {\n  return product.origin !== undefined && product.origin !== null;\n}\n\nexport function isExternalProduct(product: OriginLine): boolean {\n  if (hasStoredOrigin(product)) return product.origin === Origin.Factory || product.origin === Origin.Partner;\n  return !!product.externalWarehouseId;\n}\n\nexport function getExternalGroupId(product: {\n  origin?: Origin | null;\n  externalWarehouseGroupId?: number | null;\n}): number | undefined {\n  if (product.externalWarehouseGroupId) return product.externalWarehouseGroupId;\n  if (product.origin === Origin.Factory) return FACTORY_GROUP_ID;\n  if (product.origin === Origin.Partner) return PARTNER_GROUP_ID;\n  return undefined;\n}\n","import { PriceType } from \"utils/enums/PriceType\";\n\ntype PriceLike = { type?: unknown } | null | undefined;\n\n/**\n * SAL-283 QA r6: true when any price depends on the amount. Safe for a cart line without a picked\n * stock row (prices undefined or null), which must still render its stored finalPrice.\n */\nexport function hasAmountDependentPrice(prices: PriceLike[] | null | undefined): boolean {\n  if (!Array.isArray(prices)) return false;\n  return prices.some(\n    price =>\n      price?.type === PriceType.AmountDiscount || price?.type === PriceType.AmountDiscountList,\n  );\n}\n\n/** Prices shown for a cart line: the picked stock row's, else the product's, else none. */\nexport function cartLinePrices<T>(\n  product:\n    | {\n        selectedStock?: { prices?: T[] | null } | null;\n        prices?: T[] | null;\n      }\n    | null\n    | undefined,\n): T[] {\n  return product?.selectedStock?.prices ?? product?.prices ?? [];\n}\n","import { lineTotalWithoutVat } from \"./CartProductUpdate\";\n\n// SAL-283 QA r5 check 4: the header badge and the cart page use ONE total (stored finalPrice x qty for\n// external lines, same rounding). When the cart page has the lines, it pushes its total to the badge at\n// once; an older server fetch still in flight must not overwrite that.\n\ntype BadgeLine = Parameters<typeof lineTotalWithoutVat>[0];\n\n/** Cart total without VAT, rounded to cents: the cart page total and the header badge. */\nexport function cartTotalWithoutVat(\n  products: BadgeLine[] | null | undefined,\n  wholesaleType: unknown,\n): number {\n  let total = 0;\n  for (const p of products ?? []) total += lineTotalWithoutVat(p, wholesaleType);\n  return roundCents(total);\n}\n\nexport type CartBadgeValue = { count: number; totalWithoutVat: number };\n\n/** Orders badge updates: only the latest source wins (a pushed page total or the newest fetch). */\nexport class CartBadgeState {\n  count = 0;\n  totalWithoutVat = 0;\n  private version = 0;\n\n  /** Call before fetching the cart; pass the token to acceptFetch. */\n  beginFetch(): number {\n    return ++this.version;\n  }\n\n  /** Applies a fetched cart unless something newer arrived meanwhile. Returns whether it applied. */\n  acceptFetch(\n    token: number,\n    products: BadgeLine[] | null | undefined,\n    wholesaleType: unknown,\n  ): boolean {\n    if (token !== this.version) return false;\n    // SAL-283 r8: an answer without a products list is not \"empty cart\"; keep the last known value.\n    if (!Array.isArray(products)) return false;\n    this.set({\n      count: products?.length ?? 0,\n      totalWithoutVat: cartTotalWithoutVat(products, wholesaleType),\n    });\n    return true;\n  }\n\n  /** The cart page's own total: applied at once and invalidates fetches already in flight. */\n  push(value: CartBadgeValue): void {\n    this.version++;\n    this.set(value);\n  }\n\n  private set(value: CartBadgeValue) {\n    this.count = value.count;\n    this.totalWithoutVat = value.totalWithoutVat;\n  }\n}\n\n/** Same rounding as Utils.round(num, 2) (kept local so this module has no framework imports). */\nfunction roundCents(num: number): number {\n  return +(Math.round(`${num}e+2` as any) + \"e-2\");\n}\n\ntype LineKeyed = { cartProductId?: number };\n\n/**\n * SAL-283 QA r5: applies a reloaded cart onto the one on screen. When it has the same lines, each line\n * object is updated in place, so UI-only state (picked stock row, thumbnail) stays and nothing blanks.\n */\nexport function mergeCartLines<C extends { products: P[] }, P extends LineKeyed>(\n  current: C | undefined,\n  next: C,\n): C {\n  const old = current?.products;\n  if (!old || old.length !== next.products.length) return next;\n  const byId = new Map(old.map(p => [p.cartProductId, p] as const));\n  if (next.products.some(p => p.cartProductId === undefined || !byId.has(p.cartProductId)))\n    return next;\n  const merged = next.products.map(p => {\n    const line = byId.get(p.cartProductId)! as P & {\n      externalWarehouseId?: number;\n      selectedStock?: unknown;\n      fallbackStock?: unknown;\n    };\n    // The server re-selected the supplier: the old stock row no longer belongs to the line.\n    if ((p as typeof line).externalWarehouseId !== line.externalWarehouseId) {\n      line.selectedStock = undefined;\n      line.fallbackStock = undefined;\n    }\n    return Object.assign(line, p);\n  });\n  return Object.assign(current!, next, { products: merged });\n}\n"],"sourceRoot":""}