2024-04-08 14:05:38 +00:00
|
|
|
|
import {
|
|
|
|
|
|
Avatar,
|
|
|
|
|
|
MenuItem,
|
|
|
|
|
|
Select,
|
|
|
|
|
|
SelectChangeEvent,
|
|
|
|
|
|
Typography,
|
|
|
|
|
|
useMediaQuery,
|
|
|
|
|
|
useTheme,
|
|
|
|
|
|
} from "@mui/material";
|
|
|
|
|
|
import Box from "@mui/material/Box";
|
2024-05-20 18:15:36 +00:00
|
|
|
|
import * as React from "react";
|
|
|
|
|
|
import { FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
2024-04-08 14:05:38 +00:00
|
|
|
|
import "./CustomSelect.css";
|
|
|
|
|
|
import arrow_down from "../../assets/icons/arrow_down.svg";
|
2024-05-20 18:15:36 +00:00
|
|
|
|
import { getUsers, PaginationRequest, User } from "@api/integration";
|
2024-04-08 14:05:38 +00:00
|
|
|
|
|
|
|
|
|
|
type CustomSelectProps = {
|
2024-04-09 13:07:42 +00:00
|
|
|
|
selectedItem: string | null;
|
|
|
|
|
|
setSelectedItem: (value: string | null) => void;
|
2024-05-20 18:15:36 +00:00
|
|
|
|
type?: string;
|
2024-04-08 14:05:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-04-09 13:07:42 +00:00
|
|
|
|
export const CustomSelect: FC<CustomSelectProps> = ({
|
2024-04-08 14:05:38 +00:00
|
|
|
|
selectedItem,
|
|
|
|
|
|
setSelectedItem,
|
2024-05-20 18:15:36 +00:00
|
|
|
|
type,
|
2024-04-09 13:07:42 +00:00
|
|
|
|
}) => {
|
2024-04-08 14:05:38 +00:00
|
|
|
|
const theme = useTheme();
|
|
|
|
|
|
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
|
|
|
|
|
const [opened, setOpened] = useState<boolean>(false);
|
2024-04-09 13:07:42 +00:00
|
|
|
|
const [currentValue, setCurrentValue] = useState<string | null>(selectedItem);
|
2024-05-20 18:15:36 +00:00
|
|
|
|
const [users, setUsers] = useState<User[]>([]);
|
|
|
|
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
|
|
const [page, setPage] = useState(1);
|
|
|
|
|
|
const [hasMoreItems, setHasMoreItems] = useState(true);
|
|
|
|
|
|
const SIZE = 25;
|
2024-04-08 14:05:38 +00:00
|
|
|
|
const ref = useRef<HTMLDivElement | null>(null);
|
2024-05-21 21:29:33 +00:00
|
|
|
|
const selectWidth = ref.current ? ref.current.offsetWidth : undefined;
|
|
|
|
|
|
|
|
|
|
|
|
const [savedValue, setSavedValue] = useState<number | null>(null);
|
2024-04-08 14:05:38 +00:00
|
|
|
|
|
2024-04-09 13:07:42 +00:00
|
|
|
|
const onSelectItem = useCallback(
|
2024-04-08 14:05:38 +00:00
|
|
|
|
(event: SelectChangeEvent<HTMLDivElement>) => {
|
2024-04-09 13:07:42 +00:00
|
|
|
|
const newValue = event.target.value.toString();
|
2024-05-21 21:29:33 +00:00
|
|
|
|
const selectedUser = users.find((user) => user.Name === newValue);
|
|
|
|
|
|
if (selectedUser) {
|
|
|
|
|
|
//для сохранения ID выбранного пользователя в стейт или конфиг...
|
|
|
|
|
|
setSavedValue(selectedUser.ID);
|
|
|
|
|
|
}
|
2024-04-09 13:07:42 +00:00
|
|
|
|
setCurrentValue(newValue);
|
|
|
|
|
|
setSelectedItem(newValue);
|
2024-04-08 14:05:38 +00:00
|
|
|
|
},
|
2024-05-21 21:29:33 +00:00
|
|
|
|
[setSelectedItem, setCurrentValue, setSavedValue, users],
|
2024-04-08 14:05:38 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const toggleOpened = useCallback(() => {
|
|
|
|
|
|
setOpened((isOpened) => !isOpened);
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
2024-05-20 18:15:36 +00:00
|
|
|
|
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
|
|
|
|
|
|
const scrollHeight = e.currentTarget.scrollHeight;
|
|
|
|
|
|
const scrollTop = e.currentTarget.scrollTop;
|
|
|
|
|
|
const clientHeight = e.currentTarget.clientHeight;
|
|
|
|
|
|
const scrolledToBottom = scrollTop / (scrollHeight - clientHeight) > 0.9;
|
|
|
|
|
|
|
|
|
|
|
|
if (scrolledToBottom && !isLoading && hasMoreItems) {
|
|
|
|
|
|
setPage((prevPage) => prevPage + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (type === "typeUsers" && hasMoreItems) {
|
|
|
|
|
|
setIsLoading(true);
|
|
|
|
|
|
const pagination: PaginationRequest = {
|
|
|
|
|
|
page: page,
|
|
|
|
|
|
size: SIZE,
|
|
|
|
|
|
};
|
|
|
|
|
|
getUsers(pagination).then(([response]) => {
|
|
|
|
|
|
if (response && response.items !== null) {
|
|
|
|
|
|
setUsers((prevItems) => [...prevItems, ...response.items]);
|
|
|
|
|
|
if (response.items.length < SIZE) {
|
|
|
|
|
|
setHasMoreItems(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
setIsLoading(false);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [page, type, hasMoreItems]);
|
|
|
|
|
|
|
|
|
|
|
|
const menuItems = useMemo(() => {
|
|
|
|
|
|
if (type === "typeUsers" && users && users.length !== 0) {
|
|
|
|
|
|
return users.map((user) => (
|
|
|
|
|
|
<MenuItem
|
|
|
|
|
|
key={user.ID}
|
|
|
|
|
|
value={user.Name}
|
2024-05-21 21:29:33 +00:00
|
|
|
|
sx={{
|
|
|
|
|
|
padding: "6px 0",
|
|
|
|
|
|
zIndex: 2,
|
|
|
|
|
|
borderTop: "1px solid rgba(154, 154, 175, 0.1)",
|
|
|
|
|
|
width: "auto",
|
|
|
|
|
|
}}
|
2024-05-20 18:15:36 +00:00
|
|
|
|
>
|
2024-05-21 21:29:33 +00:00
|
|
|
|
<Box
|
|
|
|
|
|
sx={{
|
|
|
|
|
|
fontSize: "16px",
|
|
|
|
|
|
color: "#4D4D4D",
|
|
|
|
|
|
display: "flex",
|
|
|
|
|
|
flexDirection: isMobile ? "column" : "row",
|
|
|
|
|
|
justifyContent: "space-evenly",
|
|
|
|
|
|
width: "100%",
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Typography
|
|
|
|
|
|
sx={{
|
|
|
|
|
|
width: "33%",
|
|
|
|
|
|
borderRight: isMobile
|
|
|
|
|
|
? "none"
|
|
|
|
|
|
: "1px solid rgba(154, 154, 175, 0.1)",
|
|
|
|
|
|
padding: isMobile ? "5px 0 5px 20px" : "10px 0 10px 20px",
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{user.Name}
|
|
|
|
|
|
</Typography>
|
|
|
|
|
|
<Typography
|
|
|
|
|
|
sx={{
|
|
|
|
|
|
width: "33%",
|
|
|
|
|
|
borderRight: isMobile
|
|
|
|
|
|
? "none"
|
|
|
|
|
|
: "1px solid rgba(154, 154, 175, 0.1)",
|
|
|
|
|
|
padding: isMobile ? "5px 0 5px 20px" : "10px 0 10px 20px",
|
|
|
|
|
|
color: isMobile ? "#9A9AAF" : "#4D4D4D",
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{user.Email}
|
|
|
|
|
|
</Typography>
|
|
|
|
|
|
<Typography
|
|
|
|
|
|
sx={{
|
|
|
|
|
|
width: "33%",
|
|
|
|
|
|
padding: isMobile ? "5px 0 5px 20px" : "10px 0 10px 20px",
|
|
|
|
|
|
color: isMobile ? "#9A9AAF" : "#4D4D4D",
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{user.Role}
|
|
|
|
|
|
</Typography>
|
|
|
|
|
|
</Box>
|
2024-05-20 18:15:36 +00:00
|
|
|
|
</MenuItem>
|
|
|
|
|
|
));
|
|
|
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
|
|
|
<MenuItem key={"-1"} disabled sx={{ padding: "12px", zIndex: 2 }}>
|
|
|
|
|
|
нет данных
|
|
|
|
|
|
</MenuItem>
|
|
|
|
|
|
);
|
|
|
|
|
|
}, [users, type]);
|
|
|
|
|
|
|
2024-04-08 14:05:38 +00:00
|
|
|
|
return (
|
|
|
|
|
|
<Box>
|
|
|
|
|
|
<Box
|
|
|
|
|
|
sx={{
|
2024-04-09 13:07:42 +00:00
|
|
|
|
zIndex: 3,
|
2024-04-08 14:05:38 +00:00
|
|
|
|
position: "relative",
|
|
|
|
|
|
width: "100%",
|
|
|
|
|
|
height: "56px",
|
|
|
|
|
|
padding: "5px",
|
2024-04-12 09:05:33 +00:00
|
|
|
|
color:
|
|
|
|
|
|
currentValue === null
|
|
|
|
|
|
? theme.palette.grey2.main
|
|
|
|
|
|
: theme.palette.brightPurple.main,
|
|
|
|
|
|
border: `2px solid ${theme.palette.common.white}`,
|
2024-04-08 14:05:38 +00:00
|
|
|
|
borderRadius: "30px",
|
|
|
|
|
|
background: "#EFF0F5",
|
|
|
|
|
|
display: "flex",
|
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
|
cursor: "pointer",
|
|
|
|
|
|
}}
|
|
|
|
|
|
onClick={() => ref.current?.click()}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Avatar sx={{ width: 46, height: 46, marginRight: 1 }} />
|
|
|
|
|
|
<Typography
|
|
|
|
|
|
sx={{
|
|
|
|
|
|
marginLeft: isMobile ? "10px" : "20px",
|
2024-04-09 13:07:42 +00:00
|
|
|
|
fontWeight: currentValue === null ? "400" : "500",
|
2024-04-08 14:05:38 +00:00
|
|
|
|
fontSize: isMobile ? "14px" : "16px",
|
|
|
|
|
|
textOverflow: "ellipsis",
|
|
|
|
|
|
whiteSpace: "nowrap",
|
|
|
|
|
|
overflow: "hidden",
|
|
|
|
|
|
flexGrow: 1,
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
2024-04-09 13:07:42 +00:00
|
|
|
|
{currentValue || "Выберите ответственного за сделку"}
|
2024-04-08 14:05:38 +00:00
|
|
|
|
</Typography>
|
|
|
|
|
|
<img
|
|
|
|
|
|
src={arrow_down}
|
|
|
|
|
|
alt="check"
|
|
|
|
|
|
style={{
|
|
|
|
|
|
position: "absolute",
|
|
|
|
|
|
top: "50%",
|
|
|
|
|
|
right: "10px",
|
|
|
|
|
|
transform: `translateY(-50%) rotate(${opened ? "180deg" : "0deg"}`,
|
|
|
|
|
|
height: "36px",
|
|
|
|
|
|
width: "36px",
|
|
|
|
|
|
}}
|
|
|
|
|
|
className={`select-icon ${opened ? "opened" : ""}`}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Box>
|
|
|
|
|
|
<Select
|
|
|
|
|
|
ref={ref}
|
|
|
|
|
|
className="select"
|
2024-04-09 13:07:42 +00:00
|
|
|
|
value={""}
|
2024-04-08 14:05:38 +00:00
|
|
|
|
open={opened}
|
|
|
|
|
|
MenuProps={{
|
|
|
|
|
|
disablePortal: true,
|
|
|
|
|
|
PaperProps: {
|
2024-05-20 18:15:36 +00:00
|
|
|
|
onScroll: handleScroll,
|
2024-04-08 14:05:38 +00:00
|
|
|
|
style: {
|
2024-04-09 13:07:42 +00:00
|
|
|
|
zIndex: 2,
|
2024-04-08 14:05:38 +00:00
|
|
|
|
maxHeight: "300px",
|
|
|
|
|
|
overflow: "auto",
|
2024-05-21 21:29:33 +00:00
|
|
|
|
overflowX: "auto",
|
|
|
|
|
|
maxWidth: selectWidth,
|
2024-04-08 14:05:38 +00:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}}
|
2024-05-21 21:29:33 +00:00
|
|
|
|
sx={{}}
|
2024-04-09 13:07:42 +00:00
|
|
|
|
onChange={onSelectItem}
|
2024-04-08 14:05:38 +00:00
|
|
|
|
onClick={toggleOpened}
|
|
|
|
|
|
>
|
2024-05-20 18:15:36 +00:00
|
|
|
|
{menuItems}
|
2024-04-08 14:05:38 +00:00
|
|
|
|
</Select>
|
|
|
|
|
|
</Box>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|