This commit is contained in:
Виталий Лавшонок
2025-10-30 20:43:01 +03:00
parent 5ef7933446
commit 99018537c5
21 changed files with 518 additions and 42 deletions

View File

@@ -0,0 +1,59 @@
import { cn } from "../../../lib/cn";
import { Book, UserAdd, Edit, EyeClosed, EyeOpen } from "../../../assets/icons/groups";
export interface GroupItemProps {
id: number;
role: "menager" | "member" | "owner" | "viewer";
visible: boolean;
name: string;
}
interface IconComponentProps {
src: string;
}
const IconComponent: React.FC<IconComponentProps> = ({
src
}) => {
return <img
src={src}
className="hover:bg-liquid-light rounded-[5px] cursor-pointer transition-all duration-300"
/>
}
const GroupItem: React.FC<GroupItemProps> = ({
id, name, visible, role
}) => {
console.log(id);
return (
<div className={cn("w-full h-[120px] box-border relative rounded-[10px] p-[10px] text-liquid-white bg-liquid-lighter",
)}>
<div className="grid grid-cols-[100px,1fr] gap-[20px]">
<img src={Book} className="bg-liquid-brightmain rounded-[10px]"/>
<div className="grid grid-flow-row grid-rows-[1fr,24px]">
<div className="text-[18px] font-bold">
{name}
</div>
<div className=" flex gap-[10px]">
{
(role == "menager" || role == "owner") && <IconComponent src={UserAdd}/>
}
{
(role == "menager" || role == "owner") && <IconComponent src={Edit}/>
}
{
visible == false && <IconComponent src={EyeOpen} />
}
{
visible == true && <IconComponent src={EyeClosed} />
}
</div>
</div>
</div>
</div>
);
};
export default GroupItem;

View File

@@ -0,0 +1,71 @@
import { useEffect } from "react";
import { SecondaryButton } from "../../../components/button/SecondaryButton";
import { cn } from "../../../lib/cn";
import { useAppDispatch } from "../../../redux/hooks";
import GroupsBlock from "./GroupsBlock";
import { setMenuActivePage } from "../../../redux/slices/store";
export interface Group {
id: number;
role: "menager" | "member" | "owner" | "viewer";
visible: boolean;
name: string;
}
const Groups = () => {
const dispatch = useAppDispatch();
const groups: Group[] = [
{ id: 1, role: "owner", name: "Main Administration", visible: true },
{ id: 2, role: "menager", name: "Project Managers", visible: true },
{ id: 3, role: "member", name: "Developers", visible: true },
{ id: 4, role: "viewer", name: "QA Viewers", visible: true },
{ id: 5, role: "member", name: "Design Team", visible: true },
{ id: 6, role: "owner", name: "Executive Board", visible: true },
{ id: 7, role: "menager", name: "HR Managers", visible: true },
{ id: 8, role: "viewer", name: "Marketing Reviewers", visible: false },
{ id: 9, role: "member", name: "Content Creators", visible: false },
{ id: 10, role: "menager", name: "Support Managers", visible: true },
{ id: 11, role: "viewer", name: "External Auditors", visible: false },
{ id: 12, role: "member", name: "Frontend Developers", visible: true },
{ id: 13, role: "member", name: "Backend Developers", visible: true },
{ id: 14, role: "viewer", name: "Guest Access", visible: false },
{ id: 15, role: "menager", name: "Operations", visible: true },
];
useEffect(() => {
dispatch(setMenuActivePage("groups"))
}, []);
return (
<div className=" h-full w-[calc(100%+250px)] box-border p-[20px] pt-[20p]">
<div className="h-full box-border">
<div className="relative flex items-center mb-[20px]">
<div className={cn("h-[50px] text-[40px] font-bold text-liquid-white flex items-center")}>
Группы
</div>
<SecondaryButton
onClick={() => { }}
text="Создать группу"
className="absolute right-0"
/>
</div>
<div className="bg-liquid-lighter h-[50px] mb-[20px]">
</div>
<GroupsBlock className="mb-[20px]" title="Управляемые" groups={groups.filter((v) => v.visible && (v.role == "owner" || v.role == "menager"))} />
<GroupsBlock className="mb-[20px]" title="Текущие" groups={groups.filter((v) => v.visible && (v.role == "member" || v.role == "viewer"))} />
<GroupsBlock className="mb-[20px]" title="Скрытые" groups={groups.filter((v) => v.visible == false)} />
</div>
</div>
);
};
export default Groups;

View File

@@ -0,0 +1,60 @@
import { useState, FC } from "react";
import GroupItem from "./GroupItem";
import { cn } from "../../../lib/cn";
import { ChevroneDown } from "../../../assets/icons/groups";
export interface Group {
id: number;
role: "menager" | "member" | "owner" | "viewer";
visible: boolean;
name: string;
}
interface GroupsBlockProps {
groups: Group[];
title: string;
className?: string;
}
const GroupsBlock: FC<GroupsBlockProps> = ({ groups, title, className }) => {
const [active, setActive] = useState<boolean>(title != "Скрытые");
return (
<div className={cn(" border-b-[1px] border-b-liquid-lighter rounded-[10px]",
className
)}>
<div className={cn(" h-[40px] text-[24px] font-bold flex gap-[10px] border-b-[1px] border-b-transparent items-center cursor-pointer transition-all duration-300",
active && " border-b-liquid-lighter"
)}
onClick={() => {
console.log(active);
setActive(!active)
}}>
<span>{title}</span>
<img src={ChevroneDown} className={cn("transition-all duration-300",
active && "rotate-180"
)}/>
</div>
<div className={cn(" grid grid-flow-row grid-rows-[0fr] opacity-0 transition-all duration-300",
active && "grid-rows-[1fr] opacity-100"
)}>
<div className="overflow-hidden">
<div className="grid grid-cols-3 gap-[20px] pt-[20px] pb-[20px] box-border">
{
groups.map((v, i) => <GroupItem key={i} {...v} />)
}
</div>
</div>
</div>
</div>
);
};
export default GroupsBlock;