{"version":3,"file":"savedProduct-89b81e6a.js","sources":["../../../src/js/modules/saved-products.js"],"sourcesContent":["import FetchWrapper from './fetch-wrapper.js';\nimport * as Helpers from './helpers.js';\n\nconst API = new FetchWrapper( window.origin );\nlet currentPreference = Helpers.getPreferredVAT();\n\n// To use this, you'll need to add a button to any entry you want saveable:\n// \n// \tSave\n// \n//\n// You'll also need to add the JS and CSS to any page that needs it:\n// {{ craft.vite.script('src/js/modules/saved-products.js', false) }}\n//\n// In the screen.pcss file:\n// @import \"components/saved-products.pcss\";\n\nfunction initialiseSaveButtons() { // Sets the state etc for all save buttons on the page\n\tconst saveButtons = document.querySelectorAll('button[data-save-button]');\n\tlet savedProductIds = [];\n\n\tif ( localStorage.getItem('savedProductIds') ) {\n\t\tsavedProductIds = JSON.parse( localStorage.getItem('savedProductIds') );\n\t}\n\n\tsaveButtons.forEach(saveButton => {\n\t\tif(!saveButton.dataset.productId) {\n\t\t\tconsole.error(`Button is missing a data-product-id parameter value`);\n\t\t\treturn null;\n\t\t}\n\n\t\tconsole.log({savedProductIds: savedProductIds, saveButton});\n\n\t\tif (savedProductIds.includes( saveButton.dataset.productId )) {\n\t\t\t// The button we're looking at already has its associated entry in localStorage\n\t\t\tsaveButton.dataset.state = 'saved';\n\t\t\tsaveButton.setAttribute('aria-label', 'Un-save this');\n\t\t\tsaveButton.querySelector('span').textContent = 'un-save';\n\t\t} else {\n\t\t\tsaveButton.dataset.state = null;\n\t\t\tsaveButton.setAttribute('aria-label', 'Save this');\n\t\t\tsaveButton.querySelector('span').textContent = 'Save';\n\t\t}\n\n\t\tsaveButton.addEventListener('click', handleSaveButtonClick);\n\t});\n}\n\nfunction handleSaveButtonClick( event ) { // Hand off to the correct action function when clicked\n\tconst clickedButton = event.currentTarget;\n\n\tif(!clickedButton.dataset.state || !clickedButton.dataset.productId) {\n\t\tconsole.error( `Button missing required data attributes` );\n\t\treturn false;\n\t}\n\n\tif (clickedButton.dataset.state == 'saved') {\n\t\tunsave( clickedButton );\n\t} else {\n\t\tsave( clickedButton );\n\t}\n\n\t// The state has changed, so lets refresh the drawer contents\n\tconsole.log('please repopulate...')\n\tpopulateMySavedDrawer();\n}\n\nfunction save( clickedButton ) {\n\t// Do what we need when a button is clicked to store a \"save/like\"\n\t// we know the button has the attributes we need as the handleSaveClick function has enforced that\n\n\tconst candidateProductId = clickedButton.dataset.productId;\n\tlet savedProducts = [];\n\n\tif ( localStorage.getItem('savedProductIds') ) {\n\t\tsavedProducts = JSON.parse( localStorage.getItem('savedProductIds') );\n\t}\n\n\tif( savedProducts.includes( candidateProductId ) ) {\n\t\tconsole.error(`Product is already saved`);\n\t\treturn false;\n\t}\n\n\tsavedProducts.push( candidateProductId );\n\tlocalStorage.setItem('savedProductIds', JSON.stringify( savedProducts) );\n\n\tclickedButton.dataset.state = 'saved';\n\tclickedButton.setAttribute('aria-label', `Remove from saved`);\n\tclickedButton.querySelector('span').textContent = 'Un-Save';\n\n\tlocalStorage.setItem('mySavedProductsStatus', 'stale');\n}\n\nfunction unsave( clickedButton ) {\n\t// Do what we need when a button is clicked to remove a \"like\"\n\t// we know the button has the attributes we need as the handleLikeClick function has enforced that\n\n\tconst candidateProductId = clickedButton.dataset.productId;\n\tlet savedProducts = [];\n\n\tif ( localStorage.getItem('savedProductIds') ) {\n\t\tsavedProducts = JSON.parse( localStorage.getItem('savedProductIds') );\n\t}\n\n\tif( ! savedProducts.includes( candidateProductId ) ) {\n\t\tconsole.error(`Product is not in the saved list`);\n\t\treturn false;\n\t}\n\n\tsavedProducts.splice( savedProducts.indexOf( candidateProductId ), 1 );\n\tlocalStorage.setItem('savedProductIds', JSON.stringify( savedProducts) );\n\n\tclickedButton.dataset.state = null;\n\tclickedButton.setAttribute('aria-label', `Add to saved`);\n\tclickedButton.querySelector('span').textContent = 'Save';\n\n\tlet parent = clickedButton.closest('.cardListing');\n\tparent?.classList?.add('js-justRemoved');\n\n\tlocalStorage.setItem('mySavedProductsStatus', 'stale');\n}\n\n/**\n * Retrieve saved item IDs from Local Storage, query Craft for those items, inject the response into the drawer, initialise JS parts of the cards.\n */\nfunction populateMySavedDrawer() {\n\tlet productIds = JSON.parse( localStorage.getItem('savedProductIds') ).join(',');\n\tconsole.log(`/saved-products?productIds=${productIds}`);\n\n\tif (!productIds) {\n\t\tconsole.log('No products in local storage');\n\t\tdocument.querySelector('#mySavedProducts .theSavedProducts').innerHTML = `

There are no saved items.

`;\n\t\treturn;\n\t}\n\n\tAPI.getHtml(`/saved-products?productIds=${productIds}`).then(response => {\n\t\tlet responseAsDOM = document.createRange().createContextualFragment(response);\n\t\tdocument.querySelector('#mySavedProducts .theSavedProducts').replaceChildren(responseAsDOM);\n\n\t\tinitialiseSaveButtons(); // Re-initialise, because the loaded content can itself have like buttons inside\n\t\tlocalStorage.setItem('mySavedProductsStatus', 'fresh');\n\n\t\t/* Now that they're all loaded into the drawer, also make sure the prices are being displayed in the mode the user prefers */\n\t\tHelpers.updateAllPrices( currentPreference );\n\t});\n}\n\nfunction toggleMySavedDrawer() {\n\tlet myFavRow = document.querySelector('#mySavedProducts');\n\tmyFavRow.classList.toggle('active');\n}\n\nfunction initialiseMySavedDrawer() {\n\t// First, build and add the drawer to the mark-up\n\tconst drawer = `\n\t\t
\n\t\t\t
\n\t\t\t\t\n\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t

There are no saved items.

\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t
`;\n\tdocument.querySelector('body').insertAdjacentHTML('beforeend', drawer);\n\n\tconst showHideToggles = document.querySelectorAll('button.toggleMySavedProducts');\n\n\t// as this is the initial load, ensure state management knows we have no items dynamically loaded into the drawer yet\n\tlocalStorage.setItem('mySavedProductsStatus', 'stale');\n\n\tshowHideToggles.forEach( toggle => {\n\t\ttoggle.addEventListener('click', handleMySavedButtonClick);\n\t});\n}\n\nfunction handleMySavedButtonClick() {\n\tlet savedProducts = [];\n\n\tif (localStorage.getItem('savedProductIds')) {\n\t\tsavedProducts = JSON.parse(localStorage.getItem('savedProductIds'));\n\t}\n\n\tif (\n\t\tsavedProducts.length > 0\n\t\t&&\n\t\tlocalStorage.getItem('mySavedProductsStatus') != 'fresh'\n\t) {\n\t\tconsole.log('You have items saved, but they need to be loaded via fetch');\n\n\t\t// Replace default drawer message with \"Loading message\"\n\t\tdocument.querySelector('#mySavedProducts .theSavedProducts').innerHTML = `

Loading

`;\n\n\t\tpopulateMySavedDrawer();\n\t\ttoggleMySavedDrawer();\n\t} else {\n\t\tconsole.log('just show/hide whatever content is in the div at the moment');\n\n\t\ttoggleMySavedDrawer();\n\t}\n}\n\ninitialiseMySavedDrawer(); // create the panel full of saved items\ninitialiseSaveButtons(); // the heart toggles on various Product listing items\n"],"names":["API","FetchWrapper","currentPreference","Helpers.getPreferredVAT","initialiseSaveButtons","saveButtons","savedProductIds","saveButton","handleSaveButtonClick","event","clickedButton","unsave","save","populateMySavedDrawer","candidateProductId","savedProducts","parent","_a","productIds","response","responseAsDOM","Helpers.updateAllPrices","toggleMySavedDrawer","initialiseMySavedDrawer","drawer","showHideToggles","toggle","handleMySavedButtonClick"],"mappings":"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"}