Files
molecular_frontend/src/Components/ListCard/TeamListCard/TeamMemberCard/TeamMemberCard.tsx
DeOwl 4f983702e2
Some checks failed
Build and Deploy React Package / build-and-publish (push) Failing after 1m38s
fix build errors
2026-05-25 14:06:20 +03:00

261 lines
8.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
Avatar,
Card,
MultiSelect,
Pill,
Stack,
Text,
UnstyledButton,
} from "@mantine/core";
import {
IconCancel,
IconCheck,
IconCrown,
IconForbid,
IconPencil,
IconTrash,
} from "@tabler/icons-react";
import CustomButton from "Components/CustomButton/CustomButton";
import type { Team, TeamMember } from "Types/Team/Team";
import "./TeamMemberCard.css";
import { useState } from "react";
import { addMember, deleteMember } from "Api/QuantumBackend/TeamManagement";
import { useTeamStore } from "Stores/TeamsStore";
import { notifications } from "@mantine/notifications";
function TeamMemberCard(props: { cur_team: Team; member: TeamMember }) {
const { updateTeam } = useTeamStore();
const [is_editing, set_is_editing] = useState<boolean>(false);
const [selected_permissions, set_selected_permissions] = useState<string[]>(
props.member.permissions,
);
return (
<Card
padding="sm"
withBorder
orientation="horizontal"
className="TeamMemberCard"
key={props.member.user.keycloak_id}
>
<Card.Section
inheritPadding
px="xs"
style={{
display: "flex",
alignItems: "center",
flexDirection: "column",
justifyContent:
props.member.user.keycloak_id !=
props.cur_team.creator.user.keycloak_id
? "center"
: "",
}}
>
{props.member.user.keycloak_id ==
props.cur_team.creator.user.keycloak_id && <IconCrown />}
<Avatar radius="xl" src={props.member.user.profile_picture_path} />
</Card.Section>
<Card.Section
withBorder
inheritPadding
px="xs"
style={{ width: "250px" }}
>
<Stack>
<Text size="xl">{props.member.user.username}</Text>
<Text size="md">{props.member.user.email}</Text>
</Stack>
</Card.Section>
<Card.Section
inheritPadding
px="md"
withBorder
style={{
display: "flex",
flexGrow: 1,
alignItems: "center",
}}
>
<Stack>
<div style={{ display: "flex", gap: "20px" }}>
<Text size="md">Разрешения: </Text>
{props.member.user.keycloak_id !=
props.cur_team.creator.user.keycloak_id &&
(is_editing ? (
<div style={{ display: "flex", gap: "10px" }}>
<CustomButton
style="outline"
text="Сохранить"
textSize="sm"
icon={<IconPencil size={15} />}
onClick={() => {
addMember({
team_id: props.cur_team.id,
user_id: props.member.user.keycloak_id,
permissions: selected_permissions,
})
.then((member) => {
if (member) {
updateTeam(props.cur_team.id, {
members: [
...props.cur_team.members.filter(
(member) =>
member.user.keycloak_id !=
props.member.user.keycloak_id,
),
member,
],
});
set_is_editing(false);
notifications.show({
radius: "md",
title: "Права изменены успешно",
message: "",
icon: <IconCheck />,
style: { paddingLeft: "5px" },
});
}
})
.catch(() => {
notifications.show({
radius: "md",
title: "Ошибка изменения прав",
message: "",
color: "red",
icon: <IconForbid />,
style: { paddingLeft: "5px" },
});
});
}}
/>
<CustomButton
style="outline"
text="Отменить"
color="red"
textSize="sm"
icon={<IconPencil size={15} />}
onClick={() => {
set_is_editing(false);
set_selected_permissions(props.member.permissions);
}}
/>
</div>
) : (
<div>
<CustomButton
style="outline"
text="Изменить"
textSize="sm"
icon={<IconPencil size={15} />}
onClick={() => {
set_is_editing(true);
}}
/>
</div>
))}
</div>
<div
style={{
gap: "10px",
display: "flex",
flexDirection: "row",
}}
>
{!is_editing ? (
props.member.permissions.map((perm) => (
<Pill className="TeamPill">{perm}</Pill>
))
) : (
<MultiSelect
value={selected_permissions}
label=""
placeholder="Выберите разрешения"
searchable
data={props.cur_team.creator.permissions}
onChange={(value) => {
set_selected_permissions(value);
}}
/>
)}
</div>
</Stack>
</Card.Section>
<Card.Section
inheritPadding
px="md"
style={{
display: "flex",
flexDirection: "column",
}}
>
<UnstyledButton
onClick={(e: Event) => {
e.stopPropagation();
deleteMember({
team_id: props.cur_team.id,
user_id: props.member.user.keycloak_id,
})
.then(() => {
notifications.show({
radius: "md",
title: "Пользователь удален успешно",
message: "",
icon: <IconCheck />,
style: { paddingLeft: "5px" },
});
updateTeam(props.cur_team.id, {
members: [
...props.cur_team.members.filter(
(member) =>
member.user.keycloak_id !=
props.member.user.keycloak_id,
),
],
});
})
.catch(() => {
notifications.show({
radius: "md",
title: "Пользователя не получилось удалить",
message: "",
color: "red",
icon: <IconCancel />,
style: { paddingLeft: "5px" },
});
});
}}
style={{
cursor: "pointer",
width: "20px",
alignSelf: "flex-end",
}}
>
<IconTrash size={20} />
</UnstyledButton>
<Stack gap={"5px"}>
<Text style={{ alignSelf: "flex-end" }}>Добавлен:</Text>
<div
style={{
display: "flex",
flexDirection: "row",
gap: "5px",
}}
>
<Text size="sm" style={{ textAlign: "right" }}>
{new Date(props.member.joined_at + "Z").toLocaleDateString("ru")}
</Text>
<Text size="sm" style={{ textAlign: "right" }}>
{new Date(props.member.joined_at + "Z").toLocaleTimeString("ru")}
</Text>
</div>
</Stack>
</Card.Section>
</Card>
);
}
export default TeamMemberCard;