diff --git a/src/i18n/en.json b/src/i18n/en.json index 3fb5ca6c3..459716da0 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -113,7 +113,8 @@ "maximum": "Must be at most {maximum}", "time": "Wrong time format.", "wrong_format": "Wrong format.", - "add_on_required": "Select at least one add-on" + "add_on_required": "Select at least one add-on", + "additional_items": "Unable to save due to missing required additional info — click the ⚙ icon to review" }, "price_tiers": { "early_bird_rate": "Early Bird Rate", diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/__tests__/edit-cart-form.test.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/__tests__/edit-cart-form.test.js index d9492bff4..bf44ceef2 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/__tests__/edit-cart-form.test.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/__tests__/edit-cart-form.test.js @@ -446,6 +446,60 @@ describe("EditCartForm", () => { }); }); + describe("Item Field Error Message", () => { + test("shows error message below Save when a required Item field is empty after submit", async () => { + const formWithRequiredItemField = { + ...mockCartForm, + items: [ + { + ...mockCartForm.items[0], + meta_fields: [ + { + type_id: 2, + type: "Text", + class_field: "Item", + current_value: "", + is_required: true + } + ] + } + ] + }; + + renderWithStore({}, { cartForm: formWithRequiredItemField }); + + await waitFor(() => { + expect(screen.getByText(/general.save/)).toBeInTheDocument(); + }); + + await userEvent.click(screen.getByText(/general.save/)); + + await waitFor(() => { + expect( + screen.getByText("validation.additional_items") + ).toBeInTheDocument(); + }); + }); + + test("does not show error message when no Item fields have validation errors", async () => { + renderWithStore(); + + await waitFor(() => { + expect(screen.getByText(/general.save/)).toBeInTheDocument(); + }); + + await userEvent.click(screen.getByText(/general.save/)); + + await waitFor(() => { + expect(mockUpdateCartForm).toHaveBeenCalled(); + }); + + expect( + screen.queryByText("validation.additional_items") + ).not.toBeInTheDocument(); + }); + }); + describe("Edge Cases", () => { test("handles empty items array", async () => { const emptyForm = { diff --git a/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/index.js b/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/index.js index 9be1f8f13..35f3fef96 100644 --- a/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/index.js +++ b/src/pages/sponsors/sponsor-page/tabs/sponsor-cart-tab/components/edit-form/index.js @@ -277,6 +277,10 @@ const EditForm = ({ // wait for formik to re-initialize with form items if (!form || Object.keys(formik.values).length === 0) return null; + const hasItemFieldErrors = Object.keys(formik.errors).some( + (key) => key.includes("-c-Item-") && formik.touched[key] + ); + return ( <> @@ -319,6 +323,18 @@ const EditForm = ({ {T.translate("general.save")} + {hasItemFieldErrors && ( + + + {T.translate("validation.additional_items")} + + + )}