Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/actions/sponsor-users-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -328,9 +329,11 @@ 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.company?.id) payload.company_id = request.company.id;
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 > 0) payload.company_id = request.company.id;
else payload.company_name = request.company.name;
payload.sponsorship_types = request.tiers.map((st) => st.id);
}
Expand Down
54 changes: 49 additions & 5 deletions src/components/mui/formik-inputs/company-input-mui.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,30 @@
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);
const [options, setOptions] = useState([]);
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;
Expand All @@ -44,6 +48,7 @@ const CompanyInputMUI = ({
return;
}

setIsDebouncing(false);
setLoading(true);

const normalize = (results) =>
Expand All @@ -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(() => {
Expand Down Expand Up @@ -96,30 +103,66 @@ 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 (
<Autocomplete
open={open}
onOpen={() => setOpen(true)}
onClose={() => 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={<ExpandMoreIcon />}
renderOption={(props, option) => (
<li {...props} key={option.value ?? `create-${option.inputValue}`}>
{option.label}
</li>
)}
renderInput={(params) => (
<TextField
{...params}
Expand Down Expand Up @@ -156,7 +199,8 @@ CompanyInputMUI.propTypes = {
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
plainValue: PropTypes.bool,
isMulti: PropTypes.bool
isMulti: PropTypes.bool,
allowCreate: PropTypes.bool
};

export default CompanyInputMUI;
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -32,9 +33,11 @@ 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 = "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;
};
Expand All @@ -50,7 +53,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(),
Expand All @@ -62,10 +65,13 @@ 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(),
id: yup
.number()
.min(0, T.translate("validation.required"))
.required(),
name: yup.string().required()
}),
otherwise: (schema) => schema.notRequired()
Expand All @@ -79,7 +85,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 }))
Expand Down Expand Up @@ -177,13 +183,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"
)
Expand All @@ -194,7 +200,10 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => {
<Grid2 size={6}>
<MuiSponsorInput
name="sponsor"
disabled={formik.values.sponsor_type === "new"}
disabled={
formik.values.sponsor_type ===
SPONSOR_USER_ASSIGNMENT_TYPE.NEW
}
summitId={summit.id}
placeholder={T.translate(
"sponsor_users.process_request.select_sponsor"
Expand All @@ -204,15 +213,19 @@ const ProcessRequestForm = ({ request, userGroups, summit, onSubmit }) => {
<Grid2 size={6}>
<CompanyInputMUI
name="company"
disabled={formik.values.sponsor_type === "existing"}
disabled={
formik.values.sponsor_type ===
SPONSOR_USER_ASSIGNMENT_TYPE.EXISTING
}
placeholder={T.translate(
"sponsor_users.process_request.select_company"
)}
allowCreate
/>
</Grid2>
</Grid2>
<Divider sx={{ margin: "10px -16px 20px -16px" }} />
{formik.values.sponsor_type === "new" && (
{formik.values.sponsor_type === SPONSOR_USER_ASSIGNMENT_TYPE.NEW && (
<>
<Typography variant="h6" gutterBottom>
{T.translate("sponsor_users.process_request.show_details")}
Expand Down
5 changes: 5 additions & 0 deletions src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,9 @@ export const PURCHASE_STATUS = {
PENDING: "Pending",
PAID: "Paid",
CANCELLED: "Cancelled"
}

export const SPONSOR_USER_ASSIGNMENT_TYPE = {
EXISTING: "existing",
NEW: "new"
};