110 lines
3.2 KiB
TypeScript
110 lines
3.2 KiB
TypeScript
import { Box } from "@mui/material";
|
|
import SearchSelect, { Option } from "common/SearchSelect";
|
|
import { useGlobalState, useTeamAPI, useUserAPI } from "providers";
|
|
import React, { useCallback, useEffect, useState } from "react";
|
|
|
|
interface Props {
|
|
className?: string;
|
|
setTeamCallback?: React.Dispatch<React.SetStateAction<string>>;
|
|
style?: React.CSSProperties;
|
|
label?: string;
|
|
loadUsers?: boolean;
|
|
}
|
|
|
|
export default function TeamSearch(props: Props) {
|
|
const { className, setTeamCallback, style, label, loadUsers } = props;
|
|
const teamAPI = useTeamAPI();
|
|
const userAPI = useUserAPI();
|
|
const [selectedTeam, setSelectedTeam] = useState<Option | null>(null);
|
|
const [handler, setHandler] = useState<NodeJS.Timeout | undefined>(undefined);
|
|
const [teams, setTeams] = useState<Option[]>([]);
|
|
const [searchText, setSearchText] = useState("");
|
|
const [search, setSearch] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
const [{ user }] = useGlobalState();
|
|
|
|
useEffect(() => {
|
|
if (!setSearch) return;
|
|
if (searchText === undefined) return;
|
|
setHandler(setTimeout(() => {
|
|
setSearch(searchText);
|
|
}, 750)); // Delay of 750ms
|
|
|
|
return () => clearTimeout(handler); // Cleanup on change
|
|
}, [searchText]);
|
|
|
|
const onChange = (e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
|
|
setSearchText(e.target.value);
|
|
};
|
|
|
|
const loadTeams = useCallback(() => {
|
|
let options: Option[] = [];
|
|
setLoading(true);
|
|
teamAPI
|
|
.listTeams(10, 0, "desc", undefined, undefined, undefined, " ", search)
|
|
.then(resp => {
|
|
if (loadUsers)
|
|
options.push({
|
|
value: user.id(),
|
|
label: "Yourself",
|
|
icon: "default",
|
|
group: "Users"
|
|
});
|
|
resp.data.teams.forEach(team => {
|
|
let o = {
|
|
value: team.settings?.key,
|
|
label: team.settings!.name,
|
|
icon: team.settings?.avatar,
|
|
group: "Teams"
|
|
};
|
|
options.push(o);
|
|
});
|
|
})
|
|
.finally(() => {
|
|
if (loadUsers) {
|
|
userAPI
|
|
.listUsers(10, 0, "desc", undefined, undefined, search)
|
|
.then(resp => {
|
|
resp.users.forEach(user => {
|
|
options.push({
|
|
value: user.id(),
|
|
label: user.name(),
|
|
icon: user.settings.avatar,
|
|
group: "Users"
|
|
});
|
|
});
|
|
})
|
|
.finally(() => {
|
|
setLoading(false);
|
|
});
|
|
} else {
|
|
setLoading(false);
|
|
}
|
|
setTeams(options);
|
|
});
|
|
}, [teamAPI, loadUsers, userAPI, user, search]);
|
|
|
|
useEffect(() => {
|
|
loadTeams();
|
|
}, [loadTeams]);
|
|
|
|
return (
|
|
<Box className={className} style={style}>
|
|
<SearchSelect
|
|
getOptionSelected={() => {
|
|
return true;
|
|
}}
|
|
label={label ? label : "View As"}
|
|
options={teams}
|
|
loading={loading}
|
|
group
|
|
selected={selectedTeam}
|
|
onChange={onChange}
|
|
changeSelection={(option: Option | null) => {
|
|
setSelectedTeam(option);
|
|
if (setTeamCallback) setTeamCallback(option?.value);
|
|
}}
|
|
/>
|
|
</Box>
|
|
);
|
|
}
|