diff --git a/web/static/custom/bountyhub.js b/web/static/custom/bountyhub.js index eee34109..5372a550 100644 --- a/web/static/custom/bountyhub.js +++ b/web/static/custom/bountyhub.js @@ -53,7 +53,7 @@ document.addEventListener('DOMContentLoaded', function() { const card = document.createElement('div'); card.className = 'col-md-6 col-lg-4 col-xl-3 mb-3'; card.innerHTML = ` -
+
@@ -84,7 +84,7 @@ document.addEventListener('DOMContentLoaded', function() {
Since ${new Date(attributes.started_accepting_at).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
${attributes.currency.toUpperCase()}
- See details + See details
`; @@ -111,21 +111,44 @@ document.addEventListener('DOMContentLoaded', function() { } // below has everything to do with card selection and import button + const container = document.getElementById('program_cards'); + const importBtn = document.getElementById('importProgramsBtn'); + + + container.addEventListener('click', function(event) { + const card = event.target.closest('.card-selectable'); + if (card) { + toggleCardSelection(event, card); + } + }); + + function toggleCardSelection(event, card) { + if (event.target.closest('#btn-see-details')) { + // If it's the "See details" button, don't toggle selection, maybe we need other actions in the future here + return; + } - function toggleCardSelection(card) { card.classList.toggle('card-selected'); updateImportButton(); } - // lets create func and listeners if cards are selected - const importBtn = document.getElementById('importProgramsBtn'); - const container = document.getElementById('program_cards'); - function updateImportButton() { const selectedCards = container.querySelectorAll('.card-selected'); - importBtn.disabled = selectedCards.length === 0; + const count = selectedCards.length; + + if (count === 0) { + importBtn.disabled = true; + importBtn.innerHTML = ' Import Programs'; + importBtn.classList.remove('button-updated'); + } else { + importBtn.disabled = false; + importBtn.innerHTML = ` Import ${count} Program${count !== 1 ? 's' : ''}`; + + // Trigger the animation + importBtn.classList.remove('button-updated'); + void importBtn.offsetWidth; // Trigger reflow + importBtn.classList.add('button-updated'); + } } - window.toggleCardSelection = toggleCardSelection; - }); \ No newline at end of file diff --git a/web/static/custom/custom.css b/web/static/custom/custom.css index 79632992..80e31ed8 100644 --- a/web/static/custom/custom.css +++ b/web/static/custom/custom.css @@ -702,4 +702,38 @@ mark{ .import-programs-btn:disabled { animation: disableButton 0.3s ease forwards; +} + +/* update on counter increase */ +@keyframes gentlePulse { + 0% { + box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7); + } + 70% { + box-shadow: 0 0 0 10px rgba(0, 123, 255, 0); + } + 100% { + box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); + } +} + +@keyframes colorTransition { + 0% { + background-color: #007bff; + } + 100% { + background-color: #007bff; + } +} + +.import-programs-btn { + transition: all 0.3s ease; +} + +.import-programs-btn:not(:disabled) { + animation: gentlePulse 1.5s infinite; +} + +.import-programs-btn.button-updated { + animation: gentlePulse 1.5s infinite, colorTransition 0.5s ease; } \ No newline at end of file