From d75ded158b22bc2efe8042a60f099b089dd714d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Thu, 5 Feb 2026 17:48:04 -0300 Subject: [PATCH 1/4] fix: add constants, wip change payload structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/actions/sponsor-users-actions.js | 9 ++++-- .../components/process-request-form.js | 28 ++++++++++++------- src/utils/constants.js | 5 ++++ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/actions/sponsor-users-actions.js b/src/actions/sponsor-users-actions.js index 84db7ab48..4656ce4ed 100644 --- a/src/actions/sponsor-users-actions.js +++ b/src/actions/sponsor-users-actions.js @@ -29,7 +29,8 @@ import { DEFAULT_CURRENT_PAGE, DEFAULT_ORDER_DIR, DEFAULT_PER_PAGE, - DUMMY_ACTION + DUMMY_ACTION, + SPONSOR_USER_ASSIGNMENT_TYPE } from "../utils/constants"; import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions"; @@ -328,8 +329,10 @@ export const processSponsorUserRequest = (request) => async (dispatch) => { send_activation_email: request.send_email }; - if (request.sponsor?.id) payload.sponsor_id = request.sponsor.id; - else { + if (request.sponsor_type === SPONSOR_USER_ASSIGNMENT_TYPE.EXISTING) + payload.sponsor_id = request.sponsor.id; + + if (request.sponsor_type === SPONSOR_USER_ASSIGNMENT_TYPE.NEW) { if (request.company?.id) payload.company_id = request.company.id; else payload.company_name = request.company.name; payload.sponsorship_types = request.tiers.map((st) => st.id); diff --git a/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js b/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js index 377b6a585..cb8a78de3 100644 --- a/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js +++ b/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js @@ -21,6 +21,7 @@ import MuiSponsorInput from "../../../../components/mui/formik-inputs/mui-sponso import { titleCase } from "../../../../utils/methods"; import MuiFormikSwitch from "../../../../components/mui/formik-inputs/mui-formik-switch"; import SponsorshipsBySummitSelectMUI from "../../../../components/mui/formik-inputs/sponsorship-summit-select-mui"; +import { SPONSOR_USER_ASSIGNMENT_TYPE } from "../../../../utils/constants"; const buildInitialValues = (data) => { const normalized = { ...data }; @@ -33,8 +34,9 @@ const buildInitialValues = (data) => { normalized.send_email = true; if (data.company_id !== 0 && data.sponsor) - normalized.sponsor_type = "existing"; - else if (data.company_name) normalized.sponsor_type = "new"; + normalized.sponsor_type = SPONSOR_USER_ASSIGNMENT_TYPE.EXISTING; + else if (data.company_name) + normalized.sponsor_type = SPONSOR_USER_ASSIGNMENT_TYPE.NEW; return normalized; }; @@ -50,7 +52,7 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => { .object() .nullable() .when("sponsor_type", { - is: "existing", + is: SPONSOR_USER_ASSIGNMENT_TYPE.EXISTING, then: (schema) => schema.required(T.translate("validation.required")).shape({ id: yup.number().required(), @@ -62,7 +64,7 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => { .object() .nullable() .when("sponsor_type", { - is: "new", + is: SPONSOR_USER_ASSIGNMENT_TYPE.NEW, then: (schema) => schema.required(T.translate("validation.required")).shape({ id: yup.number().required(), @@ -79,7 +81,7 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => { }) ) .when("sponsor_type", { - is: "new", + is: SPONSOR_USER_ASSIGNMENT_TYPE.NEW, then: (schema) => schema .min(1, T.translate("validation.required", { count: 1 })) @@ -177,13 +179,13 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => { }} options={[ { - value: "existing", + value: SPONSOR_USER_ASSIGNMENT_TYPE.EXISTING, label: T.translate( "sponsor_users.process_request.assign_to_existing" ) }, { - value: "new", + value: SPONSOR_USER_ASSIGNMENT_TYPE.NEW, label: T.translate( "sponsor_users.process_request.assign_to_new" ) @@ -194,7 +196,10 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => { { { - {formik.values.sponsor_type === "new" && ( + {formik.values.sponsor_type === SPONSOR_USER_ASSIGNMENT_TYPE.NEW && ( <> {T.translate("sponsor_users.process_request.show_details")} diff --git a/src/utils/constants.js b/src/utils/constants.js index 93939c429..738fefa11 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -256,4 +256,9 @@ export const PURCHASE_STATUS = { PENDING: "Pending", PAID: "Paid", CANCELLED: "Cancelled" +} + +export const SPONSOR_USER_ASSIGNMENT_TYPE = { + EXISTING: "existing", + NEW: "new" }; From 443fd6fd2e5d6be19c316dbc11c82da244860294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Fri, 6 Feb 2026 15:20:18 -0300 Subject: [PATCH 2/4] fix: allow create companies from company input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- .../mui/formik-inputs/company-input-mui.js | 54 +++++++++++++++++-- .../components/process-request-form.js | 1 + 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/components/mui/formik-inputs/company-input-mui.js b/src/components/mui/formik-inputs/company-input-mui.js index 8bf851beb..301a451a0 100644 --- a/src/components/mui/formik-inputs/company-input-mui.js +++ b/src/components/mui/formik-inputs/company-input-mui.js @@ -14,19 +14,22 @@ import React, { useState, useEffect, useMemo } from "react"; import PropTypes from "prop-types"; import TextField from "@mui/material/TextField"; -import Autocomplete from "@mui/material/Autocomplete"; +import Autocomplete, { createFilterOptions } from "@mui/material/Autocomplete"; import CircularProgress from "@mui/material/CircularProgress"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { useField } from "formik"; import { queryCompanies } from "../../../actions/company-actions"; import { DEBOUNCE_WAIT_250 } from "../../../utils/constants"; +const filter = createFilterOptions(); + const CompanyInputMUI = ({ id, name, placeholder, plainValue, isMulti = false, + allowCreate = false, ...rest }) => { const [field, meta, helpers] = useField(name); @@ -34,6 +37,7 @@ const CompanyInputMUI = ({ const [open, setOpen] = useState(false); const [inputValue, setInputValue] = useState(""); const [loading, setLoading] = useState(false); + const [isDebouncing, setIsDebouncing] = useState(false); const { value } = field; const error = meta.touched && meta.error; @@ -44,6 +48,7 @@ const CompanyInputMUI = ({ return; } + setIsDebouncing(false); setLoading(true); const normalize = (results) => @@ -60,11 +65,13 @@ const CompanyInputMUI = ({ useEffect(() => { if (inputValue) { + setIsDebouncing(true); const delayDebounce = setTimeout(() => { fetchOptions(inputValue); }, DEBOUNCE_WAIT_250); return () => clearTimeout(delayDebounce); } + setIsDebouncing(false); }, [inputValue]); const selectedValue = useMemo(() => { @@ -96,13 +103,43 @@ const CompanyInputMUI = ({ })); } else { theValue = plainValue - ? newValue.label - : { id: parseInt(newValue.value), name: newValue.label }; + ? newValue.inputValue || newValue.label + : { + id: newValue.inputValue ? 0 : parseInt(newValue.value), + name: newValue.inputValue || newValue.label + }; } helpers.setValue(theValue); }; + const handleFilterOptions = (options, params) => { + const filtered = filter(options, params); + + if (!allowCreate || loading || isDebouncing) return filtered; + + const { inputValue } = params; + const isExisting = options.some( + (option) => inputValue.toLowerCase() === option.label.toLowerCase() + ); + + if (inputValue !== "" && !isExisting) { + filtered.push({ + inputValue, + value: null, + label: `Create "${inputValue}"` + }); + } + return filtered; + }; + + const getOptionLabel = (option) => { + if (option.inputValue) { + return option.inputValue; + } + return option.label || ""; + }; + return ( setOpen(false)} options={options} value={selectedValue} - getOptionLabel={(option) => option.label} + getOptionLabel={getOptionLabel} isOptionEqualToValue={(option, value) => option.value === value.value} onInputChange={(_, newInputValue) => { setInputValue(newInputValue); }} + filterOptions={handleFilterOptions} multiple={isMulti} onChange={handleChange} loading={loading} fullWidth popupIcon={} + renderOption={(props, option) => ( +
  • + {option.label} +
  • + )} renderInput={(params) => ( { placeholder={T.translate( "sponsor_users.process_request.select_company" )} + allowCreate /> From beb6ae1277399310fcd5a1068a7e222b873ae54a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Tue, 10 Feb 2026 13:27:56 -0300 Subject: [PATCH 3/4] fix: adjust company id validations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- src/actions/sponsor-users-actions.js | 2 +- .../components/process-request-form.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/actions/sponsor-users-actions.js b/src/actions/sponsor-users-actions.js index 4656ce4ed..6360ebca1 100644 --- a/src/actions/sponsor-users-actions.js +++ b/src/actions/sponsor-users-actions.js @@ -333,7 +333,7 @@ export const processSponsorUserRequest = (request) => async (dispatch) => { payload.sponsor_id = request.sponsor.id; if (request.sponsor_type === SPONSOR_USER_ASSIGNMENT_TYPE.NEW) { - if (request.company?.id) payload.company_id = request.company.id; + if (request.company?.id > 0) payload.company_id = request.company.id; else payload.company_name = request.company.name; payload.sponsorship_types = request.tiers.map((st) => st.id); } diff --git a/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js b/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js index 28b65d71e..2a55e66b7 100644 --- a/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js +++ b/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js @@ -67,7 +67,10 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => { is: SPONSOR_USER_ASSIGNMENT_TYPE.NEW, then: (schema) => schema.required(T.translate("validation.required")).shape({ - id: yup.number().required(), + id: yup + .number() + .min(0, T.translate("validation.required")) + .required(), name: yup.string().required() }), otherwise: (schema) => schema.notRequired() From 75f6ec9857c0d69188fd790af480361a7a1c416a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Castillo?= Date: Tue, 10 Feb 2026 13:30:24 -0300 Subject: [PATCH 4/4] fix: add initial value for sponsor type on buildInitialValues function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Castillo --- .../sponsor-users-list-page/components/process-request-form.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js b/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js index 2a55e66b7..2ee0cffa6 100644 --- a/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js +++ b/src/pages/sponsors/sponsor-users-list-page/components/process-request-form.js @@ -33,6 +33,7 @@ const buildInitialValues = (data) => { normalized.access_rights = []; normalized.send_email = true; + normalized.sponsor_type = SPONSOR_USER_ASSIGNMENT_TYPE.NEW; if (data.company_id !== 0 && data.sponsor) normalized.sponsor_type = SPONSOR_USER_ASSIGNMENT_TYPE.EXISTING; else if (data.company_name)