diff --git a/app/javascript/packs/admin/editUser.jsx b/app/javascript/packs/admin/editUser.jsx index c71b37e87..235388220 100644 --- a/app/javascript/packs/admin/editUser.jsx +++ b/app/javascript/packs/admin/editUser.jsx @@ -1,8 +1,42 @@ import { initializeDropdown } from '@utilities/dropdownUtils'; -let preact; -let AdminModal; -const modalContents = new Map(); +function adjustCreditRange(event) { + const { + target: { value, name, form }, + } = event; + + if (name === 'user[credit_action]') { + const creditAmount = form['user[credit_amount]']; + + if (value === 'Add') { + if (creditAmount.getAttribute('data-old-max')) { + creditAmount.setAttribute( + 'max', + creditAmount.getAttribute('data-old-max'), + ); + } + } else { + creditAmount.setAttribute( + 'data-old-max', + creditAmount.getAttribute('max'), + ); + creditAmount.setAttribute('max', creditAmount.dataset.unspentCredits); + } + } +} + +function enableEvents(key, enabled = true) { + if (!eventMap.has(key)) { + return; + } + + const [eventType, handler] = eventMap.get(key); + + modalContainer[enabled ? 'addEventListener' : 'removeEventListener']( + eventType, + handler, + ); +} function getModalContents(modalContentSelector) { if (!modalContents.has(modalContentSelector)) { @@ -17,6 +51,16 @@ function getModalContents(modalContentSelector) { return modalContents.get(modalContentSelector); } +let preact; +let AdminModal; +const modalContents = new Map(); + +// Keys are the modalContentSelector data attribute on a button that opens a modal. +// Values are a tuple containing the event type and handler to add to the modal container. +const eventMap = new Map(); + +eventMap.set('#adjust-balance', ['change', adjustCreditRange]); + // Append an empty div to the end of the document so that is does not affect the layout. const modalContainer = document.createElement('div'); document.body.appendChild(modalContainer); @@ -48,12 +92,15 @@ const openModal = async (event) => { const { modalTitle, modalSize, modalContentSelector } = dataset; + enableEvents(modalContentSelector); + render( { render(null, modalContainer); + enableEvents(modalContentSelector, false); }} >
+ max: 9999, + data: { + "unspent-credits": @user.unspent_credits_count + } %> <%= f.label :credit_amount, "credits", class: "color-secondary flex-1", "aria-label": "Amount of credits to add or remove" %>
diff --git a/cypress/integration/seededFlows/adminFlows/users/manageCredits.spec.js b/cypress/integration/seededFlows/adminFlows/users/manageCredits.spec.js index 546cc74d8..db848e59e 100644 --- a/cypress/integration/seededFlows/adminFlows/users/manageCredits.spec.js +++ b/cypress/integration/seededFlows/adminFlows/users/manageCredits.spec.js @@ -68,16 +68,38 @@ describe('Manage User Credits', () => { cy.findByRole('combobox', { name: 'Adjust balance' }).select('Remove'); cy.findByRole('spinbutton', { name: 'Amount of credits to add or remove', - }).type('10'); + }) + .as('credits') + .type('10'); cy.findByRole('textbox', { name: 'Why are you adjusting credits?', }).type('some reason'); cy.findByRole('button', { name: 'Adjust' }).click(); }); - cy.getModal().should('not.exist'); - closeUserUpdatedMessage('Credits have been removed.'); - cy.findByTestId('user-credits').should('have.text', '0'); + cy.getModal().should('exist'); + cy.findByTestId('user-credits').should('have.text', '100'); + }); + + it('should have correct max credits for adding and removing credits', () => { + cy.findByTestId('user-credits').should('have.text', '100'); + + openCreditsModal().within(() => { + cy.findByRole('combobox', { name: 'Adjust balance' }) + .as('adjustBalance') + .select('Add'); + cy.findByRole('spinbutton', { + name: 'Amount of credits to add or remove', + }) + .as('creditAmount') + .should('have.attr', 'max', '9999'); + + cy.get('@adjustBalance').select('Remove'); + cy.get('@creditAmount').should('have.attr', 'max', '100'); + + cy.get('@adjustBalance').select('Add'); + cy.get('@creditAmount').should('have.attr', 'max', '9999'); + }); }); }); });