frontPanel/src/components/CustomSelect/CustomSelect.tsx

233 lines
6.8 KiB
TypeScript
Raw Normal View History

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);
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();
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
},
[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}
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
>
<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",
overflowX: "auto",
maxWidth: selectWidth,
2024-04-08 14:05:38 +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>
);
};