diff --git a/README.md b/README.md index 2f3e66a..8c3f8e1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,32 @@ -# vinted-favs-price +# Vinted Favorites Price Calculator +A simple browser extension that calculates and displays the total price of your favorite items on [vinted.de](https://www.vinted.de/member/items/favourite_list). You can toggle between the base price and the price including Vinted's buyer protection. +## Features + +- Adds a floating button to your favorites list page. +- Calculates the total sum of all visible favorite items. +- Toggle between base price and price including buyer protection. +- Updates automatically as you scroll and more items load. + +## Installation + +### Download + +- **[Get it for Firefox on Mozilla Add-ons](https://addons.mozilla.org/en-US/firefox/addon/vinted-favorites-price/)** + +Click the link above to download and install the extension directly from the official Firefox Add-ons store. + +## Usage + +1. Go to [https://www.vinted.de/member/items/favourite_list](https://www.vinted.de/member/items/favourite_list). +2. Wait for the page to load. A button labeled "Show Total Price (Incl. Protection)" will appear in the bottom right corner. +3. Click the button to toggle between showing the base price and the price including buyer protection. +4. The total sum will be displayed in the page header. + +## Notes + +- The sum updates when you refresh the page or scroll to load more items. +- The extension is designed to work on the favorites list page and may not function correctly on other pages of the Vinted website. + +## License +[MIT License](LICENSE) diff --git a/calculate-total.js b/calculate-total.js new file mode 100644 index 0000000..3d10d90 --- /dev/null +++ b/calculate-total.js @@ -0,0 +1,89 @@ +// Configuration & State +let showProtection = false; +const GRID_SELECTOR = '.feed-grid .feed-grid__item'; +const H1_SELECTOR = 'h1.web_ui__Text__text.web_ui__Text__heading.web_ui__Text__left.web_ui__Text__parent'; + +// 1. Create and Inject the Toggle Button +const btn = document.createElement('button'); +btn.id = 'vinted-helper-toggle'; +btn.innerText = "Show Total Price (Incl. Protection)"; +btn.style.cssText = ` + position: fixed; + bottom: 20px; + right: 20px; + z-index: 10000; + padding: 12px 20px; + background: #007782; + color: white; + border: 2px solid #005f68; + border-radius: 8px; + cursor: pointer; + font-family: sans-serif; + font-weight: bold; +`; +document.body.appendChild(btn); + +// 2. Calculation Logic +const updateDisplayAndSum = () => { + const items = document.querySelectorAll(GRID_SELECTOR); + let totalSum = 0; + let count = 0; + + items.forEach(item => { + const basePriceEl = item.querySelector('[data-testid*="--price-text"]'); + const protectPriceEl = item.querySelector('[data-testid*="--breakdown"] .web_ui__Text__subtitle'); + + if (basePriceEl && protectPriceEl) { + // Determine which price to use for the sum + const targetEl = showProtection ? protectPriceEl : basePriceEl; + const price = parseFloat(targetEl.innerText.replace(/[^\d,.]/g, '').replace(',', '.')); + + if (!isNaN(price)) { + totalSum += price; + count++; + } + + // Visual Toggling + if (showProtection) { + basePriceEl.style.display = 'none'; + protectPriceEl.style.color = '#eb5a62'; + protectPriceEl.style.fontWeight = 'bold'; + protectPriceEl.style.fontSize = '1.1em'; + } else { + basePriceEl.style.display = 'block'; + protectPriceEl.style.color = ''; + protectPriceEl.style.fontWeight = ''; + protectPriceEl.style.fontSize = ''; + } + } + }); + + // Update the H1 Header + const header = document.querySelector(H1_SELECTOR); + if (header && count > 0) { + const formattedSum = totalSum.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + const label = showProtection ? "Total (with Prot.)" : "Total"; + + // Remove old brackets if they exist, then append new total + const cleanTitle = header.innerText.split(' [')[0]; + header.innerText = `${cleanTitle} [${label}: €${formattedSum}]`; + } +}; + +// 3. Event Listener +btn.addEventListener('click', () => { + showProtection = !showProtection; + btn.innerText = showProtection ? "Show Base Price" : "Show Total Price (Incl. Protection)"; + btn.style.background = showProtection ? "#eb5a62" : "#007782"; + updateDisplayAndSum(); +}); + +// Initial run +setTimeout(updateDisplayAndSum, 2000); + +// Update sum when scrolling (lazy loading support) +let scrollTimeout; +window.addEventListener('scroll', () => { + clearTimeout(scrollTimeout); + scrollTimeout = setTimeout(updateDisplayAndSum, 500); +}); \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..e5cf49b --- /dev/null +++ b/manifest.json @@ -0,0 +1,18 @@ +{ + "manifest_version": 2, + "name": "vinted-favs-price", + "version": "1.0", + "content_scripts": [ + { + "matches": ["https://www.vinted.de/member/items/favourite_list"], + "js": ["calculate-total.js"] + } + ], + "browser_specific_settings": { + "gecko": { + "data_collection_permissions": { + "required": ["websiteContent"] + } + } + } +} \ No newline at end of file