{"version":3,"mappings":"qjCAOA,MAAMA,EAAcC,EAAqB,IAAMC,EAAA,WAAO,2BAA8B,0FAAC,EAC/EC,EAAcF,EAAqB,IAAMC,EAAA,WAAO,2BAA8B,0FAAC,EAE/EE,EAAWC,IAEXC,EAAQC,EAMV,IAAAC,EAAYC,EAAI,EAAK,EACrBC,EAAUD,EAAI,EAAK,EACnBE,EAAiBF,EAAI,EAAE,EACvBG,EAAQH,EAAI,EAAE,EACZ,MAAAI,EAAgCJ,EAAI,EAAE,EACtCK,EAAgBL,IAClB,IAAAM,EAAgBN,EAAI,EAAE,EACtBO,EAAeP,EAAI,EAAE,EACrBQ,EAAsBR,EAAI,EAAE,EAC5BS,EAAgBT,EAAI,EAAE,EAEpB,MAAAU,EAAiB,KAAK,UAAU,CACrC,QAAW,CACV,MAAS,GACT,WAAc,GACd,SAAY,GACZ,QAAW,GACX,iBAAoB,GACpB,qBAAwB,GACxB,qBAAwB,EACzB,EACA,EAEKC,EAAS,SAAY,CAC1BV,EAAQ,MAAQ,GAEhB,MAAM,MAAM,+CAA+CE,EAAM,KAAK,UAAW,CAChF,OAAQ,OACR,QAAS,CACR,eAAgB,kBACjB,EACA,KAAMO,CAAA,CACN,EACC,KAAiBE,GAAA,CACb,IAACA,EAAS,GACP,UAAI,MAAM,6BAA6B,EAE9C,OAAOA,EAAS,MAAK,CACrB,EACA,KAAaC,GAAA,CACL,YAAI,OAAQA,EAAK,MAAM,EAC3BA,EAAK,cAAgB,EACxBT,EAAS,MAAQS,EAAK,SAEtBJ,EAAc,MAAQZ,EAAM,UAE7BI,EAAQ,MAAQ,GAChB,EACA,MAAea,GAAA,CACfT,EAAc,MAAQS,EACtB,QAAQ,MAAMA,CAAK,EACnB,GAEH,SAASC,GAAiB,CACrBZ,EAAM,MAAM,OAAS,IACxB,OAAO,SAAS,KAAO,GAAGR,GAAA,YAAAA,EAAU,gBAAgB,MAAMQ,EAAM,KAAK,aAEvE,CAgCA,eAAea,GAAmB,CAC3B,YAAM,mDAAmD,EAC7D,KAAKJ,GAAYA,EAAS,KAAM,GAChC,KAAaC,GAAA,CACbP,EAAc,MAAQO,CAAA,CACtB,CACH,CAEA,eAAeI,GAAkB,CAChC,MAAM,MAAM,2EAA2EtB,EAAS,WAAW,EAAE,EAC3G,KAAKiB,GAAYA,EAAS,MAAM,EAChC,KAAaC,GAAA,CACbN,EAAa,MAAQM,CAAA,CACrB,CACH,CAEA,eAAeK,EAAwBC,EAAcC,EAAe,GAAIC,EAAe,EAAG,CACzF,MAAM,MAAM,2DAA2DF,CAAI,SAASC,CAAI,SAASC,CAAI,EAAE,EACrG,QAAiBT,EAAS,MAAM,EAChC,KAAaC,GAAA,CACbL,EAAqB,MAAQK,CAAA,CAC7B,CACH,CAEA,OAAAS,EAAU,IAAM,CACf,MAAMC,EAAY,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAExDA,EAAU,IAAI,GAAG,IACpBpB,EAAM,MAAQoB,EAAU,IAAI,GAAG,GAAK,GACrC,CAEA,EAEKC,EAAArB,EAAOsB,EAAUC,GAAkB,CAEpCA,EAAM,OAAS,GAClBtB,EAAS,MAAQ,GACVO,IACPO,EAAwBQ,CAAK,IAE7BtB,EAAS,MAAQ,GACjBI,EAAqB,MAAQ,GAC7BC,EAAc,MAAQ,GACvB,EACE,GAAG,CAAC,EAGDe,EAAAzB,EAAY2B,GAAU,CAIvBA,GAASpB,EAAc,MAAM,SAAW,IAC1BU,IACDC,KAGbS,EACH,SAAS,gBAAgB,UAAU,IAAI,kBAAmB,YAAY,GAEtE,SAAS,gBAAgB,UAAU,OAAO,kBAAmB,YAAY,EACzExB,EAAe,MAAM,OACtB,CACA","names":["SearchModal","defineAsyncComponent","__vitePreload","ProductCard","settings","getSettings","props","__props","showModal","ref","loading","searchInputRef","query","products","productsError","popularGroups","popularTerms","relatedProductGroups","noResultsText","productOptions","search","response","data","error","goToSearchPage","getPopularGroups","getPopularTerms","getRelatedProductGroups","term","take","skip","onMounted","urlParams","watch","debounce","value"],"sources":["../../src/components/Files/Templates/Designs/Mobler/src/components/SearchBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport {defineAsyncComponent, ref, onMounted, watch} from 'vue'\r\nimport {debounce} from 'vue-debounce'\r\nimport {getTranslation, getSettings} from \"@/ts/utilities.ts\";\r\nimport { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'\r\nimport {ProductListViewData} from '@/interfaces/ProductListViewInterface.ts'\r\n\r\nconst SearchModal = defineAsyncComponent(() => import('@/components/SearchModal.vue'))\r\nconst ProductCard = defineAsyncComponent(() => import('@/components/ProductCard.vue'))\r\n\r\nconst settings = getSettings()\r\n\r\nconst props = defineProps({\r\n\tnoResults: {\r\n\t\ttype: Number,\r\n\t}\r\n})\r\n\r\nlet showModal = ref(false)\r\nlet loading = ref(false)\r\nlet searchInputRef = ref('')\r\nlet query = ref('')\r\nconst products: ProductListViewData = ref([])\r\nconst productsError = ref()\r\nlet popularGroups = ref([])\r\nlet popularTerms = ref([])\r\nlet relatedProductGroups= ref([])\r\nlet noResultsText = ref('')\r\n\r\nconst productOptions = JSON.stringify({\r\n\t'options': {\r\n\t\t'media': true,\r\n\t\t'dimensions': true,\r\n\t\t'delivery': true,\r\n\t\t'cylindo': true,\r\n\t\t'priceAndCampaign': true,\r\n\t\t'variantOptionsSimple': true,\r\n\t\t'productDetailsSimple': true\r\n\t}\r\n})\r\n\r\nconst search = async () => {\r\n\tloading.value = true\r\n\r\n\tawait fetch(`/mobler-api/v2/products/productsearchfeed?q=${query.value}&take=9`, {\r\n\t\tmethod: 'POST',\r\n\t\theaders: {\r\n\t\t\t'Content-Type': 'application/json'\r\n\t\t},\r\n\t\tbody: productOptions\r\n\t})\r\n\t\t.then(response => {\r\n\t\t\tif (!response.ok) {\r\n\t\t\t\tthrow new Error('Network response was not ok')\r\n\t\t\t}\r\n\t\t\treturn response.json()\r\n\t\t})\r\n\t\t.then(data => {\r\n\t\t\tconsole.log('data', data.length)\r\n\t\t\tif (data.totalProducts > 0) {\r\n\t\t\t\tproducts.value = data.products\r\n\t\t\t} else {\r\n\t\t\t\tnoResultsText.value = props.noResults\r\n\t\t\t}\r\n\t\t\tloading.value = false\r\n\t\t})\r\n\t\t.catch(error => {\r\n\t\t\tproductsError.value = error\r\n\t\t\tconsole.error(error)\r\n\t\t})\r\n}\r\nfunction goToSearchPage() {\r\n\tif (query.value.length > 2) {\r\n\t\twindow.location.href = `${settings?.searchResultPage}?q=${query.value}&take=1000`\r\n\t}\r\n}\r\n\r\n// Calculate the top positioning of the modal,the modal should always be positioned so the search input is 20px inside from the top\r\nfunction calculateModalPosition() {\r\n\tlet searchInput = document.getElementById('js-search-bar')\r\n\tlet modal = document.getElementById('js-search-modal')\r\n\tlet searchInputPosition = searchInput?.getBoundingClientRect()\r\n\tlet modalTop = 0\r\n\tlet searchTop\r\n\r\n\t// Only if viewport width is above 768px\r\n\tif (window.innerWidth > 768) {\r\n\t\tmodalTop = (searchInputPosition?.top ?? 0) - 20\r\n\t} else {\r\n\t\t// Move search input to the top of the viewport\r\n\t\tsearchTop = (searchInputPosition?.top ?? 0) * -1 + 20\r\n\t\tsearchInput?.classList.add('absolute')\r\n\t}\r\n\r\n\t// When search is closed, remove the absolute positioning\r\n\tif (!showModal.value) {\r\n\t\tsearchInput?.classList.remove('absolute')\r\n\t}\r\n\r\n\tif (modal) {\r\n\t\tmodal.style.top = `${modalTop}px`\r\n\t}\r\n\tif (searchInput) {\r\n\t\tsearchInput.style.top = `${searchTop}px`\r\n\t}\r\n}\r\n\r\nasync function getPopularGroups() {\r\n\tawait fetch('/mobler-api/session/Relewise/PopularProductGroups')\r\n\t\t.then(response => response.json())\r\n\t\t.then(data => {\r\n\t\t\tpopularGroups.value = data\r\n\t\t})\r\n}\r\n\r\nasync function getPopularTerms() {\r\n\tawait fetch(`/mobler-api/session/Relewise/PopularSearchTerms?pageId=7177&isLocalshop=${settings.isLocalshop}`)\r\n\t\t.then(response => response.json())\r\n\t\t.then(data => {\r\n\t\t\tpopularTerms.value = data\r\n\t\t})\r\n}\r\n\r\nasync function getRelatedProductGroups(term: string, take: number = 10, skip: number = 0) {\r\n\tawait fetch(`/mobler-api/session/Relewise/ProductCategorySearch?term=${term}&take=${take}&skip=${skip}`)\r\n\t\t.then(response => response.json())\r\n\t\t.then(data => {\r\n\t\t\trelatedProductGroups.value = data\r\n\t\t})\r\n}\r\n\r\nonMounted(() => {\r\n\tconst urlParams = new URLSearchParams(window.location.search)\r\n\r\n\tif (urlParams.has('q')) {\r\n\t\tquery.value = urlParams.get('q') ?? ''\r\n\t}\r\n\r\n})\r\n\r\nwatch(query, debounce((value: string) => {\r\n\t// Whilst query is above 2 characters, clear and search, if under clear\r\n\tif (value.length > 2) {\r\n\t\tproducts.value = []\r\n\t\tsearch()\r\n\t\tgetRelatedProductGroups(value)\r\n\t} else {\r\n\t\tproducts.value = []\r\n\t\trelatedProductGroups.value = []\r\n\t\tnoResultsText.value = ''\r\n\t}\r\n}, 400))\r\n\r\n// If modal is opened, append the overflow-hidden class to the html element\r\nwatch(showModal, (value) => {\r\n\t//calculateModalPosition()\r\n\r\n\t// The first time the modal is opened, get the popular groups and terms\r\n\tif (value && popularGroups.value.length === 0) {\r\n\t\tgetPopularGroups()\r\n\t\tgetPopularTerms()\r\n\t}\r\n\r\n\tif (value) {\r\n\t\tdocument.documentElement.classList.add('overflow-hidden', 'modal-open')\r\n\t} else {\r\n\t\tdocument.documentElement.classList.remove('overflow-hidden', 'modal-open')\r\n\t\tsearchInputRef.value.blur()\r\n\t}\r\n})\r\n\r\n</script>\r\n\r\n<template>\r\n\t<div class=\"flex items-center w-full\">\r\n\t<form\r\n\t\tclass=\"relative rounded-full border border-grey flex w-full\"\r\n\t\t:class=\"showModal ? 'z-50 transform w-[70vw] lg:w-full -translate-y-16 lg:translate-y-0' : ''\"\r\n\t\t@submit.prevent=\"goToSearchPage\"\r\n\t>\r\n\t\t<font-awesome-icon :icon=\"['fal', 'magnifying-glass']\" class=\"flex items-center pl-4 absolute top-4\" />\r\n\t\t<input\r\n\t\t\ttype=\"text\"\r\n\t\t\tclass=\"w-full h-12 pl-10 rounded-full border-transparent focus:ring-0 focus:border-none focus:outline-none\"\r\n\t\t\tref=\"searchInputRef\"\r\n\t\t\t@focus=\"showModal = true\"\r\n\t\t\t:placeholder=\"getTranslation('Search.Placeholder')\"\r\n\t\t\tv-model=\"query\"\r\n\t\t>\r\n\t\t<button type=\"submit\" class=\"rounded-full bg-grey-light text-black font-bold border-2 border-transparent hover:text-black hover:border-grey-dark active:border-grey-dark active:bg-grey py-2 px-4\">\r\n\t\t\t{{ getTranslation('Search') }}\r\n\t\t</button>\r\n\t</form>\r\n\r\n\t\t<!-- TODO: RenderAction -->\r\n\t<button\r\n\t\ttype=\"button\"\r\n\t\tclass=\"items-center ml-auto px-3 text-base hover:underline\"\r\n\t\t:class=\"showModal ? 'flex lg:hidden z-50 transform -translate-y-16 lg:translate-y-0' : 'hidden'\"\r\n\t\t@click=\"showModal = false\"\r\n\t>\r\n\t\t<span class=\"mr-2\">{{ getTranslation('Close') }}</span>\r\n\t\t<font-awesome-icon :icon=\"['fal', 'close']\" />\r\n\t</button>\r\n\t</div>\r\n\r\n\r\n\t<SearchModal\r\n\t\t:show=\"showModal\"\r\n\t\t:loading=\"loading\"\r\n\t\t@close=\"showModal = false\">\r\n\t\t<template #modal-title>\r\n\t\t\t<!-- TODO: SetShop based text -->\r\n\t\t</template>\r\n\t\t<template #search>\r\n\t\t</template>\r\n\t\t<template #popular>\r\n\t\t\t<template v-if=\"relatedProductGroups.length > 0\">\r\n\t\t\t\t<span class=\"flex font-bold mb-2\">\r\n\t\t\t\t\t{{ getTranslation('Search.Categories') }}\r\n\t\t\t\t</span>\r\n\t\t\t\t<ul class=\"p-0 list-none border-t\">\r\n\t\t\t\t\t<li v-for=\"group in relatedProductGroups\" :key=\"group.key\">\r\n\t\t\t\t\t\t<a :href=\"group.Link\" class=\"flex py-2 border-b cursor-pointer text-black hover:border-black\">{{ group.Name }}</a>\r\n\t\t\t\t\t</li>\r\n\t\t\t\t</ul>\r\n\t\t\t</template>\r\n\t\t\t<template v-else-if=\"popularTerms.length > 0\">\r\n\t\t\t\t<span class=\"flex font-bold mb-2\">\r\n\t\t\t\t\t{{ getTranslation('Search.PopularSearchTerms') }}\r\n\t\t\t\t</span>\r\n\t\t\t\t<ul class=\"p-0 list-none border-t\">\r\n\t\t\t\t\t<li v-for=\"term in popularTerms\" :key=\"term.key\">\r\n\t\t\t\t\t\t<a :href=\"term.Link\" class=\"flex py-2 border-b cursor-pointer text-black hover:border-black\">{{ term.Term }}</a>\r\n\t\t\t\t\t</li>\r\n\t\t\t\t</ul>\r\n\t\t\t</template>\r\n\t\t</template>\r\n\t\t<template #content>\r\n\t\t\t<div v-if=\"products.length > 0\" class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-4\">\r\n\t\t\t\t<ProductCard v-for=\"product in products\" :product=\"product\" :key=\"product.key\" />\r\n\t\t\t</div>\r\n\t\t\t<div v-else-if=\"noResults\" v-html=\"noResults\">\r\n\t\t\t</div>\r\n\t\t\t<div v-else class=\"grid grid-cols-2 lg:grid-cols-3 gap-x-4 gap-y-6\">\r\n\t\t\t\t<div v-for=\"group in popularGroups\" class=\"group\" :key=\"group.key\">\r\n\t\t\t\t\t<a :href=\"group.Link\">\r\n\t\t\t\t\t\t<div class=\"bg-beige-light rounded-md overflow-hidden mb-2\">\r\n\t\t\t\t\t\t\t<img :src=\"group.Image\" class=\"object-cover object-center w-full aspect-[16/10] transition-opacity group-hover:opacity-85\" :alt=\"group.Title\" width=\"320\" height=\"200\" loading=\"lazy\" />\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t<p class=\"text-black group-hover:underline\"><strong>{{ group.Name }}</strong></p>\r\n\t\t\t\t\t</a>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t\t<div v-if=\"products.length > 8\" class=\"flex align-center justify-center\">\r\n\t\t\t\t<a :href=\"`${settings?.searchResultPage}?q=${query}&autoload=true`\" class=\"mt-8 btn brand-black btn-big transition py-2 bg-black text-white hover:no-underline\">\r\n\t\t\t\t\t{{ getTranslation('Search.ShowAllResults') }}\r\n\t\t\t\t</a>\r\n\t\t\t</div>\r\n\t\t</template>\r\n\t</SearchModal>\r\n</template>\r\n"],"file":"assets/SearchBar-5ee803df.js"}