diff --git a/app/assets/stylesheets/pages/casa_cases.scss b/app/assets/stylesheets/pages/casa_cases.scss index 34ad221b4f..2fbf9464e7 100644 --- a/app/assets/stylesheets/pages/casa_cases.scss +++ b/app/assets/stylesheets/pages/casa_cases.scss @@ -169,4 +169,25 @@ body.casa_cases-show { flex-direction: column; gap: .2rem; } -} \ No newline at end of file +} + +#case-selection:required, .select2.select2-container { + background: transparent; + border: 1px solid #e5e5e5; + border-radius: 10px; + padding: 8px; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; +} + +.select-wrapper { + display: flex; + flex-direction: column; + gap: 8px; +} + +span[role=combobox] { + padding-top: 2px; +} + diff --git a/app/javascript/src/casa_case.js b/app/javascript/src/casa_case.js index d0c39a679b..a11a65ef94 100644 --- a/app/javascript/src/casa_case.js +++ b/app/javascript/src/casa_case.js @@ -85,11 +85,25 @@ function showAlert (html) { flashContainer && flashContainer.replaceWith(alertEl) } +function validateForm (formEl, errorEl) { + if (!formEl) { + return + } + + // check html validations, checkValidity returns false if doesn't pass validation + if (errorEl && !formEl.checkValidity()) { + errorEl.classList.remove('d-none') + } +} + function handleGenerateReport (e) { e.preventDefault() - const formData = Object.fromEntries(new FormData(e.currentTarget.form)) + const form = e.currentTarget.form + const formData = Object.fromEntries(new FormData(form)) + const errorEl = document.querySelector('.select-required-error') + validateForm(form, errorEl ?? null) if (formData.case_number.length === 0) return const generateBtn = e.currentTarget @@ -127,6 +141,24 @@ function handleGenerateReport (e) { }) } +function clearSelectErrors () { + const errorEl = document.querySelector('.select-required-error') + + if (!errorEl) return + + errorEl.classList.add('d-none') +} + +function handleModalClose () { + const selectEl = document.querySelector('#case-selection') + + if (!selectEl) return + + clearSelectErrors() + // this line taken from docs https://select2.org/programmatic-control/add-select-clear-items + $('#case-selection').val(null).trigger('change') +} + $(() => { // JQuery's callback for the DOM loading $('button.copy-court-button').on('click', copyOrdersFromCaseWithConfirmation) @@ -134,6 +166,8 @@ $(() => { // JQuery's callback for the DOM loading disableBtn($('button.copy-court-button')[0]) } + $('#case-selection').on('change', clearSelectErrors) + $('select.siblings-casa-cases').on('change', () => { if ($('select.siblings-casa-cases').find(':selected').text()) { enableBtn($('button.copy-court-button')[0]) @@ -141,6 +175,9 @@ $(() => { // JQuery's callback for the DOM loading disableBtn($('button.copy-court-button')[0]) } }) + // modal id is defined in _generate_docx.html.erb so would like to be able to implement modal close logic in that file + // but not sure how to + $('#generate-docx-report-modal').on('hidden.bs.modal', () => handleModalClose()) $('#btnGenerateReport').on('click', handleGenerateReport) diff --git a/app/views/case_court_reports/_generate_docx.html.erb b/app/views/case_court_reports/_generate_docx.html.erb index 87d3ffc1f7..66a1214e7c 100644 --- a/app/views/case_court_reports/_generate_docx.html.erb +++ b/app/views/case_court_reports/_generate_docx.html.erb @@ -27,14 +27,17 @@ <% select_case_prompt = show_search ? "Search by volunteer name or case number" : "Select case number" %> <% select2_class = show_search ? " select2" : "" %> - <%= select_tag :case_number, - options_for_select(select_options), - prompt: select_case_prompt, - include_blank: false, - id: "case-selection", - class: "custom-select#{select2_class}", - data: { dropdown_parent: "##{id}" } %> - +
+ <%= select_tag :case_number, + options_for_select(select_options), + prompt: select_case_prompt, + include_blank: false, + id: "case-selection", + class: "custom-select#{select2_class}", + required: true, + data: { dropdown_parent: "##{id}", width: "100%" } %> +

Case selection is required.

+
<%= form.hidden_field :time_zone, id: "user-time-zone" %>
diff --git a/spec/system/case_court_reports/index_spec.rb b/spec/system/case_court_reports/index_spec.rb index 05fe8a1726..985fcc7baa 100644 --- a/spec/system/case_court_reports/index_spec.rb +++ b/spec/system/case_court_reports/index_spec.rb @@ -73,6 +73,26 @@ expect(page).to have_selector("#btnGenerateReport .lni-download", visible: true) expect(page).not_to have_selector("#btnGenerateReport[disabled]") expect(page).to have_selector("#spinner", visible: :hidden) + + # when 'Generate Report' button is clicked without a selection, should display an error saying to make a selection + expect(page).to have_selector(".select-required-error", visible: :visible) + + test_case_number = casa_cases.find(&:in_transition_age?).case_number.to_s + + # when we make a selection, the error is no longer visible + page.select test_case_number, from: "case-selection" + expect(page).not_to have_selector(".select-required-error", visible: :visible) + + # test the flow for clearing case selection error message by closing modal + click_button "Close" + page.find(modal_selector).click + click_button "Generate Report" + # expect the error message to be visible because we tried to generate the doc without making a selection + expect(page).to have_selector(".select-required-error", visible: :visible) + # expect error message to be gone after we close and re-open the modal + click_button "Close" + page.find(modal_selector).click + expect(page).not_to have_selector(".select-required-error", visible: :visible) end end