@proca/widget
Version:
Proca is an open-source campaign toolkit designed to empower activists and organisations in their digital advocacy efforts. It provides a flexible and customisable platform for creating and managing online petitions, email campaigns, and other forms of di
136 lines (124 loc) • 3.9 kB
JavaScript
import React, { useState, useCallback } from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import { debounce, makeStyles } from "@material-ui/core";
import CircularProgress from "@material-ui/core/CircularProgress";
import TextField from "@components/TextField";
import CountryFlag from "react-emoji-flag";
import Hidden from "@components/field/Hidden";
const useStyles = makeStyles(() => ({
root: {
"& .proca-MuiInputBase-root": {
paddingTop: "0!important",
},
},
}));
const AffiliationInput = ({ form }) => {
const classes = useStyles();
const [options, setOptions] = useState([]);
const [inputValue, setInputValue] = useState("");
const [open, setOpen] = React.useState(false);
const [loading, setLoading] = useState(false);
const fetchOptions = async query => {
if (query.length > 2) {
setLoading(true);
try {
const response = await fetch(
`https://api.ror.org/organizations?query=${encodeURIComponent(query)}`
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
const organizations = data.items.map(item => ({
name: item.name,
id: item.id,
country: item.country?.country_code,
}));
setOptions(organizations);
} catch (error) {
console.error("Error fetching data from ROR API:", error);
setOptions([]);
} finally {
setLoading(false);
}
} else {
setOptions([]);
}
};
// Debounce the fetch function
const debouncedFetchOptions = useCallback(debounce(fetchOptions, 300), []);
const handleInputChange = (_event, newInputValue, reason) => {
setInputValue(newInputValue);
if (reason === "input") debouncedFetchOptions(newInputValue);
if (reason === "clear") {
form.setValue("ror", undefined);
form.setValue("organisation", undefined);
}
if (reason === "reset") {
const institution = options.find(d => d.name === newInputValue);
if (!institution) {
console.error("didn't find organisation", newInputValue);
return;
}
form.setValue("ror", institution.id);
form.setValue("country", institution.country);
form.setValue("organisation", institution.name);
}
};
return (
<>
<Hidden name="ror" form={form} />
<Autocomplete
id="affiliation-input"
open={open}
loading={loading}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
options={options}
getOptionLabel={option => option.name}
inputValue={inputValue}
onInputChange={handleInputChange}
openOnFocus={true}
classes={{ root: classes.root }}
noOptionsText={
inputValue.length > 2
? "No organisation found"
: "Type to search your organisation"
}
loadingText={"Searching " + inputValue + "..."}
autoSelect
autoHighlight
renderOption={option => (
<>
<CountryFlag countryCode={option.country} /> {option.name}
</>
)}
renderInput={params => (
<TextField
name="organisation"
required
form={form}
{...params}
label="Affiliation"
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loading ? (
<CircularProgress color="inherit" size={20} />
) : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)}
/>
</>
);
};
export default AffiliationInput;