Initial commit

This commit is contained in:
2026-03-16 22:05:19 +03:00
commit 8e78b8cb47
71 changed files with 7846 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
import {
Avatar,
Button,
Divider,
Modal,
Stack,
Text,
Title,
UnstyledButton,
useMantineTheme,
} from "@mantine/core";
import "./Sidebar.css";
import {
IconDevicesPc,
IconFileDescription,
IconFlaskFilled,
IconLogout,
IconSettings2,
IconUsers,
type Icon,
type IconProps,
} from "@tabler/icons-react";
import { Link, useLocation } from "react-router";
import { useState, type ForwardRefExoticComponent } from "react";
import { routes } from "Routes/Routes";
import keycloak from "Api/Keycloak/Keycloak";
import { AuthenticationStore } from "Stores/AuthenticationStore";
import { baseUri, baseUrl } from "GlobalVars";
import CustomButton from "Components/CustomButton/CustomButton";
interface SubtleLinkButtonProps {
link: string;
Icon: ForwardRefExoticComponent<IconProps & React.RefAttributes<Icon>>;
text: string;
color: string;
selected?: boolean;
}
function SubtleLinkButton(props: SubtleLinkButtonProps) {
return (
<Link to={props.link} className="invisible_link">
<CustomButton
icon={<props.Icon color={props.color} size={20} />}
style="subtle"
color={props.selected ? props.color : "contrast"}
text={props.text}
textAlign="left"
/>
</Link>
);
}
function Sidebar() {
const { profile } = AuthenticationStore();
const [open, set_open] = useState(false);
const theme = useMantineTheme();
const location = useLocation(); // get current URL
return (
<div className="sidebar">
<Modal
opened={open}
onClose={() => set_open(false)}
title=<Title size="lg">Выйти?</Title>
centered
withCloseButton={false}
size="auto"
>
<div className="sidebar_bottom_bottom">
<CustomButton
text="Подтвердить"
onClick={() => keycloak.logout({ redirectUri: baseUri + baseUrl })}
textSize="lg"
color="contrast"
></CustomButton>
<CustomButton
onClick={() => set_open(false)}
text="Отменить"
textSize="lg"
style="outline"
color="contrast"
></CustomButton>
</div>
</Modal>
<div className="sidebar_top">
<SubtleLinkButton
link={routes.ExperimentsPage.path}
Icon={IconFlaskFilled}
text="Эксперименты"
color={theme.colors.teal[7]}
selected={location.pathname.startsWith(routes.ExperimentsPage.path)}
/>
<SubtleLinkButton
link={routes.MachinesPage.path}
Icon={IconDevicesPc}
text="Вычислительные системы"
color={theme.colors.violet[7]}
selected={location.pathname.startsWith(routes.MachinesPage.path)}
/>
<SubtleLinkButton
link={routes.TeamsPage.path}
Icon={IconUsers}
text="Команды"
color={theme.colors.grape[7]}
selected={location.pathname.startsWith(routes.TeamsPage.path)}
/>
<SubtleLinkButton
link={routes.DocumentationPage.path}
Icon={IconFileDescription}
text="Документация"
color={theme.colors.blue[7]}
selected={location.pathname.startsWith(routes.DocumentationPage.path)}
/>
</div>
<div className="sidebar_bottom">
{keycloak.authenticated && (
<>
<div className="sidebar_bottom_top">
<Avatar radius="xl" />
<Stack className="userInfo">
<Text size="md">{profile?.username}</Text>
<Text size="sm" c="dimmed" truncate="end">
{profile?.email}
</Text>
</Stack>
</div>
<Divider
color="secondaryContrast"
style={{ width: "100%", height: "5px", margin: "5px" }}
/>
<div className="sidebar_bottom_bottom">
<Link to={routes.SettingsPage.path} className="invisible_link">
<CustomButton
style="subtle"
icon={<IconSettings2 size={26} />}
text="Настройки"
color="contrast"
textSize="lg"
/>
</Link>
<CustomButton
style="subtle"
icon={<IconLogout size={26} />}
text="Выйти"
textSize="lg"
color="contrast"
onClick={() => {
set_open(true);
}}
/>
</div>
</>
)}
{!keycloak.authenticated && (
<UnstyledButton onClick={() => keycloak.login()}>
Войти / Зарегестрироваться
</UnstyledButton>
)}
</div>
</div>
);
}
export default Sidebar;