Web: Shared: Adapt tabs to selector for people/groups

This commit is contained in:
Aleksandr Lushkin 2024-02-13 16:20:36 +01:00
parent 1fe703a0c9
commit 16cc8962ee
5 changed files with 91 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import { Base } from "../../themes";
import { ComboBox } from "../combobox";
import { Text } from "../text";
import { Submenu } from "../submenu";
const StyledSelector = styled.div`
width: 100%;
@ -53,6 +54,7 @@ const StyledBody = styled.div<{
withHeader?: boolean;
footerHeight: number;
headerHeight: number;
withTabs?: boolean;
}>`
width: 100%;
@ -65,7 +67,7 @@ const StyledBody = styled.div<{
? `calc(100% - 16px - ${props.headerHeight}px)`
: `calc(100% - 16px)`};
padding: 16px 0 0 0;
padding: ${({ withTabs }) => (withTabs ? "8px 0 0 0" : "16px 0 0 0")};
.search-input,
.search-loader {
@ -360,6 +362,15 @@ const StyledComboBox = styled(ComboBox)`
}
`;
const StyledTabs = styled(Submenu)`
padding: 0 16px;
margin-bottom: 16px;
.sticky-indent {
height: 0;
}
`;
StyledSelector.defaultProps = { theme: Base };
StyledHeader.defaultProps = { theme: Base };
StyledBody.defaultProps = { theme: Base };
@ -384,4 +395,5 @@ export {
StyledNewNameHeader,
StyledButtonContainer,
StyledComboBox,
StyledTabs,
};

View File

@ -83,7 +83,12 @@ const Selector = ({
cancelButtonId,
isChecked,
setIsChecked,
withTabs,
tabsData,
activeTabId,
}: SelectorProps) => {
const [areItemsUpdated, setAreItemsUpdated] = React.useState(false);
const [footerVisible, setFooterVisible] = React.useState<boolean>(false);
const [isSearch, setIsSearch] = React.useState<boolean>(false);
@ -304,6 +309,37 @@ const Selector = ({
compareSelectedItems(cloneSelectedItems);
}
}, [items, selectedItems, isMultiSelect, compareSelectedItems]);
React.useEffect(() => {
if (!areItemsUpdated) return;
if (!newSelectedItems.length || !isMultiSelect || !items) {
setAreItemsUpdated(false);
return;
}
let hasConflict = false;
const cloneItems = items.map((x) => {
if (x.isSelected) return { ...x };
const isSelected = newSelectedItems.some(
(selectedItem) => selectedItem.id === x.id,
);
if (isSelected) hasConflict = true;
return { ...x, isSelected };
});
if (hasConflict) {
setRenderedItems(cloneItems);
}
setAreItemsUpdated(false);
}, [areItemsUpdated, isMultiSelect, items, newSelectedItems]);
React.useEffect(() => {
setAreItemsUpdated(true);
}, [items]);
return (
<StyledSelector
id={id}
@ -366,6 +402,9 @@ const Selector = ({
withFooterInput={withFooterInput}
withFooterCheckbox={withFooterCheckbox}
descriptionText={descriptionText}
withTabs={withTabs}
tabsData={tabsData}
activeTabId={activeTabId}
/>
{(footerVisible || alwaysShowFooter) && (
@ -415,6 +454,7 @@ Selector.defaultProps = {
alwaysShowFooter: false,
disableAcceptButton: false,
withHeader: true,
withTabs: false,
selectedItems: [],
};

View File

@ -1,6 +1,7 @@
import React from "react";
import { RoomsType } from "../../enums";
import { AvatarRole } from "../avatar";
import { TSubmenuItem } from "../submenu";
export type AccessRight = {
key: string;
@ -84,6 +85,10 @@ export interface SelectorProps {
cancelButtonId?: string;
isChecked?: boolean;
setIsChecked?: React.Dispatch<React.SetStateAction<boolean>>;
withTabs?: boolean;
tabsData?: TSubmenuItem[];
activeTabId?: number;
}
export interface HeaderProps {
@ -135,6 +140,10 @@ export interface BodyProps {
withFooterCheckbox?: boolean;
descriptionText?: string;
withTabs?: boolean;
tabsData?: TSubmenuItem[];
activeTabId?: number;
}
export interface FooterProps {
@ -177,6 +186,7 @@ export type TSelectorItem = {
isDisabled?: boolean;
color?: string;
fileExst?: string;
isGroup?: boolean;
roomType?: RoomsType;
shared: boolean;
};

View File

@ -11,7 +11,7 @@ import { SelectAll } from "./SelectAll";
import { EmptyScreen } from "./EmptyScreen";
import { BreadCrumbs } from "./BreadCrumbs";
import { StyledBody } from "../Selector.styled";
import { StyledBody, StyledTabs } from "../Selector.styled";
import { BodyProps } from "../Selector.types";
import { Item } from "./Item";
@ -65,6 +65,10 @@ const Body = ({
withFooterCheckbox,
descriptionText,
withHeader,
withTabs,
tabsData,
activeTabId,
}: BodyProps) => {
const [bodyHeight, setBodyHeight] = React.useState(0);
@ -152,6 +156,7 @@ const Body = ({
headerHeight={HEADER_HEIGHT}
footerVisible={footerVisible}
withHeader={withHeader}
withTabs={withTabs}
>
{withBreadCrumbs ? (
isBreadCrumbsLoading ? (
@ -165,6 +170,14 @@ const Body = ({
)
) : null}
{withTabs && tabsData && (
<StyledTabs
startSelect={0}
data={tabsData}
forsedActiveItemId={activeTabId}
/>
)}
{isSearchLoading || isBreadCrumbsLoading ? (
searchLoader
) : withSearch || isSearch || (itemsCount > 0 && withSearch) ? (

View File

@ -47,8 +47,17 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
if (!item || (item && !item.id))
return <div style={style}>{rowLoader}</div>;
const { label, avatar, icon, role, isSelected, isDisabled, color, email } =
item;
const {
label,
avatar,
icon,
role,
isSelected,
isDisabled,
color,
email,
isGroup,
} = item;
const currentRole = role || AvatarRole.user;
@ -87,6 +96,8 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
source={avatar || ""}
role={currentRole}
size={AvatarSize.min}
isGroup={isGroup}
userName={isGroup ? label : ""}
/>
) : (
<RoomIcon
@ -98,7 +109,7 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
/>
)}
{renderCustomItem ? (
renderCustomItem(label, typeLabel, email)
renderCustomItem(label, typeLabel, email, isGroup)
) : (
<Text
className="label"