Initial commit
This commit is contained in:
26
src/Pages/DocumentationPage/DocumentationPage.css
Executable file
26
src/Pages/DocumentationPage/DocumentationPage.css
Executable file
@@ -0,0 +1,26 @@
|
||||
.DocumentationPage {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.contents {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tableOfContents {
|
||||
position: sticky;
|
||||
top: 60px;
|
||||
width: 150px;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.docTitle {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.hoverCard {
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
}
|
||||
103
src/Pages/DocumentationPage/DocumentationPage.tsx
Executable file
103
src/Pages/DocumentationPage/DocumentationPage.tsx
Executable file
@@ -0,0 +1,103 @@
|
||||
import {
|
||||
ActionIcon,
|
||||
Box,
|
||||
Divider,
|
||||
Menu,
|
||||
TableOfContents,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import "./DocumentationPage.css";
|
||||
import { IconMenu2 } from "@tabler/icons-react";
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
function DocumentationPage() {
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Documentation | QMolSim</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="See the documentation on how to setup and use the qunatum computational system"
|
||||
/>
|
||||
</Helmet>
|
||||
<Title order={1} className="docTitle">
|
||||
Документация
|
||||
</Title>
|
||||
<Divider />
|
||||
<div className="DocumentationPage">
|
||||
<Box className="tableOfContents" visibleFrom="md">
|
||||
<TableOfContents
|
||||
variant="light"
|
||||
color="accent"
|
||||
size="sm"
|
||||
radius="sm"
|
||||
scrollSpyOptions={{
|
||||
selector: "section h2",
|
||||
}}
|
||||
getControlProps={({ data }) => ({
|
||||
onClick: () =>
|
||||
data
|
||||
.getNode()
|
||||
.scrollIntoView({ behavior: "smooth", block: "center" }),
|
||||
children: data.value,
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
<Box className="hoverCard" hiddenFrom="md">
|
||||
<Menu
|
||||
width={280}
|
||||
shadow="md"
|
||||
openDelay={100}
|
||||
closeDelay={100}
|
||||
closeOnClickOutside
|
||||
closeOnItemClick
|
||||
floatingStrategy="fixed"
|
||||
>
|
||||
<Menu.Target>
|
||||
<ActionIcon
|
||||
aria-label="navigation"
|
||||
variant="gradient"
|
||||
gradient={{ from: "blue", to: "cyan", deg: 90 }}
|
||||
radius={"50%"}
|
||||
size={40}
|
||||
>
|
||||
<IconMenu2 size={25} />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<TableOfContents
|
||||
variant="light"
|
||||
color="accent"
|
||||
size="sm"
|
||||
radius="sm"
|
||||
scrollSpyOptions={{
|
||||
selector: "section h2",
|
||||
}}
|
||||
getControlProps={({ data }) => ({
|
||||
onClick: () =>
|
||||
data
|
||||
.getNode()
|
||||
.scrollIntoView({ behavior: "smooth", block: "center" }),
|
||||
children: data.value,
|
||||
})}
|
||||
/>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</Box>
|
||||
<div className="contents">
|
||||
<section id="introduction" style={{ height: 1000 }}>
|
||||
<Title order={2}>Introduction</Title>
|
||||
</section>
|
||||
<section id="features" style={{ height: 1000 }}>
|
||||
<Title order={2}>features</Title>
|
||||
</section>
|
||||
<section id="conclusion" style={{ height: 1000 }}>
|
||||
<Title order={2}>Conslusion</Title>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default DocumentationPage;
|
||||
16
src/Pages/ExperimentsPage/ExperimentPage.css
Normal file
16
src/Pages/ExperimentsPage/ExperimentPage.css
Normal file
@@ -0,0 +1,16 @@
|
||||
.ExperimentPage {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.experimentButtons {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
width: fit-content;
|
||||
margin-left: auto;
|
||||
flex-wrap: nowrap;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
108
src/Pages/ExperimentsPage/ExperimentPage.tsx
Normal file
108
src/Pages/ExperimentsPage/ExperimentPage.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import { Alert, Center, Text } from "@mantine/core";
|
||||
import "./ExperimentPage.css";
|
||||
import { PaginationContainer } from "Components/PaginationContainer/PaginationContainer";
|
||||
import { NewMoleculeModal } from "Modals/NewMolecule/NewMolecule";
|
||||
import { useState } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { IconPlus, IconSettings } from "@tabler/icons-react";
|
||||
import { useParams } from "react-router";
|
||||
import {
|
||||
useExperimentStore,
|
||||
useSelectedExperiment,
|
||||
} from "Stores/ExperimentStore";
|
||||
import CustomButton from "Components/CustomButton/CustomButton";
|
||||
function ExperimentPage() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { experiment_id } = useParams();
|
||||
const { selectedExperimentId, selectExperiment } = useExperimentStore();
|
||||
|
||||
if (
|
||||
!selectedExperimentId ||
|
||||
(Number(experiment_id) != selectedExperimentId && experiment_id)
|
||||
) {
|
||||
console.log(Number(experiment_id));
|
||||
selectExperiment(Number(experiment_id));
|
||||
}
|
||||
|
||||
const experiment = useSelectedExperiment();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>
|
||||
{experiment
|
||||
? "Experiment " + experiment.id + " | QMolSim"
|
||||
: "Error |QmolSim"}
|
||||
</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="See the documentation on how to setup and use the qunatum computational system"
|
||||
/>
|
||||
</Helmet>
|
||||
{experiment && (
|
||||
<div className="ExperimentPage">
|
||||
<NewMoleculeModal
|
||||
isOpened={isOpen}
|
||||
setIsOpened={(toOpen: boolean) => setIsOpen(toOpen)}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "10px",
|
||||
marginBottom: "15px",
|
||||
}}
|
||||
>
|
||||
<div className="experimentButtons">
|
||||
<CustomButton
|
||||
color="contrast"
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
}}
|
||||
icon={<IconPlus />}
|
||||
text="Добавить задачу"
|
||||
/>
|
||||
<CustomButton
|
||||
color="contrast"
|
||||
style="outline"
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
}}
|
||||
icon={<IconSettings />}
|
||||
text="Параметры эксперимента"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{experiment.tasks_ids.length > 0 && (
|
||||
<PaginationContainer>
|
||||
{experiment.tasks_ids.map((task: ExperimentTask) => {
|
||||
return <div>{task.data.name}</div>;
|
||||
})}
|
||||
</PaginationContainer>
|
||||
)}
|
||||
{experiment.tasks_ids.length == 0 && (
|
||||
<Alert>
|
||||
<Center>
|
||||
<Text size={"xl"} c="contrast">
|
||||
Нет задач
|
||||
</Text>
|
||||
</Center>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!experiment && (
|
||||
<Alert color="red">
|
||||
<Center>
|
||||
{" "}
|
||||
<Text c="contrast" size={"xl"} size="md">
|
||||
Ошибка. Эксперимент не найден
|
||||
</Text>{" "}
|
||||
</Center>
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExperimentPage;
|
||||
14
src/Pages/ExperimentsPage/ExperimentsPage.css
Normal file
14
src/Pages/ExperimentsPage/ExperimentsPage.css
Normal file
@@ -0,0 +1,14 @@
|
||||
.ExperimentsPage {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.experimentsButtons {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
width: fit-content;
|
||||
margin-left: auto;
|
||||
}
|
||||
67
src/Pages/ExperimentsPage/ExperimentsPage.tsx
Normal file
67
src/Pages/ExperimentsPage/ExperimentsPage.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
import "./ExperimentsPage.css";
|
||||
import { PaginationContainer } from "Components/PaginationContainer/PaginationContainer";
|
||||
import { useState } from "react";
|
||||
import { IconMicroscope } from "@tabler/icons-react";
|
||||
import { NewExperimentModal } from "Modals/NewExperiment/NewExperiment";
|
||||
import ExperimentsListCard from "Components/ListCard/ExperimentsListCard";
|
||||
import { useExperimentStore } from "Stores/ExperimentStore";
|
||||
import type { Experiment } from "Types/Experiment/Experiment";
|
||||
import CustomButton from "Components/CustomButton/CustomButton";
|
||||
|
||||
function ExperimentsPage() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { experiments, teams, tasks } = useExperimentStore();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Experiments Page | QMolSim</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="See the list of all of users experiments"
|
||||
/>
|
||||
</Helmet>
|
||||
<NewExperimentModal isOpened={isOpen} setIsOpened={setIsOpen} />
|
||||
<div className="ExperimentsPage">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "10px",
|
||||
marginBottom: "20px",
|
||||
}}
|
||||
>
|
||||
<div className="experimentsButtons">
|
||||
<CustomButton
|
||||
color="contrast"
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
}}
|
||||
icon={<IconMicroscope />}
|
||||
text="Создать эксперимент"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<PaginationContainer>
|
||||
{experiments.map((exp: Experiment) => {
|
||||
return (
|
||||
<ExperimentsListCard
|
||||
id={exp.id}
|
||||
name={exp.name}
|
||||
description={exp.description}
|
||||
team_id={exp.team_id}
|
||||
tasks_ids={exp.tasks_ids}
|
||||
date_created={exp.date_created}
|
||||
experiment_status={exp.experiment_status}
|
||||
experiment_type="A"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</PaginationContainer>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExperimentsPage;
|
||||
65
src/Pages/ExperimentsPage/MoleculePage.css
Executable file
65
src/Pages/ExperimentsPage/MoleculePage.css
Executable file
@@ -0,0 +1,65 @@
|
||||
.MoleculeEdit {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.MoleculeEditWrapper {
|
||||
display: flex !important;
|
||||
flex: 1 !important;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-color: var(--mantine-color-secondary-filled);
|
||||
}
|
||||
|
||||
.MoleculeEditLineNumber {
|
||||
height: 100%;
|
||||
padding-top: calc(1px + var(--input-padding-y, 0rem));
|
||||
padding-bottom: calc(1px + var(--input-padding-y, 0rem));
|
||||
font-family:
|
||||
"Fira Code", "Courier New", Courier, monospace; /* Monospace fonts */
|
||||
font-size: 14px; /* Comfortable size */
|
||||
line-height: 1.5; /* Spacing like an editor */
|
||||
letter-spacing: 0; /* Keeps punctuation aligned */
|
||||
white-space: pre-line;
|
||||
overflow: scroll;
|
||||
scrollbar-width: none;
|
||||
overscroll-behavior: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.MoleculeEditInput {
|
||||
font-family:
|
||||
"Fira Code", "Courier New", Courier, monospace; /* Monospace fonts */
|
||||
font-size: 14px; /* Comfortable size */
|
||||
line-height: 1.5; /* Spacing like an editor */
|
||||
letter-spacing: 0; /* Keeps punctuation aligned */
|
||||
white-space: pre; /* preserves spaces & tabs */
|
||||
overflow-x: auto; /* horizontal scroll when needed */
|
||||
overflow-y: auto; /* vertical scroll when needed */
|
||||
word-wrap: normal; /* prevent wrapping */
|
||||
overscroll-behavior: none;
|
||||
background-color: var(--mantine-color-secondary-filled);
|
||||
}
|
||||
|
||||
.Separator {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.moleculeInput {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.moleculeInputWrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.moleculeInputWrapper > * {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tabPanel {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border-left: 1px solid var(--tab-border-color);
|
||||
border-right: 1px solid var(--tab-border-color);
|
||||
border-bottom: 1px solid var(--tab-border-color);
|
||||
}
|
||||
113
src/Pages/ExperimentsPage/MoleculePage.tsx
Executable file
113
src/Pages/ExperimentsPage/MoleculePage.tsx
Executable file
@@ -0,0 +1,113 @@
|
||||
import MoleculeViewer from "Components/MoleculeViewer/MoleculeViewer";
|
||||
import {
|
||||
Button,
|
||||
Center,
|
||||
Divider,
|
||||
Tabs,
|
||||
Text,
|
||||
useMantineTheme,
|
||||
} from "@mantine/core";
|
||||
import { Group, Panel, Separator } from "react-resizable-panels";
|
||||
import "./MoleculePage.css";
|
||||
import {
|
||||
IconCheck,
|
||||
IconCode,
|
||||
IconGripVertical,
|
||||
IconList,
|
||||
IconX,
|
||||
} from "@tabler/icons-react";
|
||||
import { useMoleculeEditStore } from "Stores/MoleculeEditStore";
|
||||
import { CodeTextArea } from "Components/CodeTextArea/CodeTextArea";
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
function MoleculeEditorPage() {
|
||||
const {
|
||||
currentMoleculeString,
|
||||
setCurrentMoleculeString,
|
||||
selectedAtom,
|
||||
setSelectedAtom,
|
||||
} = useMoleculeEditStore();
|
||||
const theme = useMantineTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Molecule Page | QMolSim</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Edit the atomic structure of a molecule"
|
||||
/>
|
||||
</Helmet>
|
||||
<div className="experimentButtons">
|
||||
<Button color="secondary" onClick={() => {}}>
|
||||
<IconCheck style={{ marginRight: "10px" }} />
|
||||
<Text c="contrast">Сохранить</Text>
|
||||
</Button>
|
||||
<Button color="contrast" onClick={() => {}}>
|
||||
<IconX style={{ marginRight: "10px" }} color="black" />
|
||||
<Text c="secondary">Отменить</Text>
|
||||
</Button>
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "column", height: "85vh" }}>
|
||||
<Divider style={{ margin: "10px" }} />
|
||||
<Group style={{ flex: 1, gap: "5px" }}>
|
||||
<Panel minSize={200} defaultSize={500}>
|
||||
<Tabs
|
||||
variant="outline"
|
||||
style={{
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
radius="lg"
|
||||
defaultValue="code"
|
||||
classNames={{ panel: "tabPanel" }}
|
||||
>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="code" leftSection={<IconCode size={12} />}>
|
||||
Код
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value="list" leftSection={<IconList size={12} />}>
|
||||
Список
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="code">
|
||||
<CodeTextArea
|
||||
text={currentMoleculeString}
|
||||
onTextChange={(text: string) => {
|
||||
setCurrentMoleculeString(text);
|
||||
}}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="list">
|
||||
<></>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</Panel>
|
||||
<Separator>
|
||||
<Center
|
||||
style={{
|
||||
height: "100%",
|
||||
background: theme.colors.dark[4],
|
||||
borderRadius: "5px",
|
||||
}}
|
||||
>
|
||||
<IconGripVertical size={12} />
|
||||
</Center>
|
||||
</Separator>
|
||||
<Panel style={{ flexShrink: 0 }} minSize={200}>
|
||||
<MoleculeViewer
|
||||
moleculeData={currentMoleculeString}
|
||||
selectedAtom={selectedAtom}
|
||||
setSelectedAtom={setSelectedAtom}
|
||||
/>
|
||||
</Panel>
|
||||
</Group>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default MoleculeEditorPage;
|
||||
41
src/Pages/MainPage/MainPage.css
Executable file
41
src/Pages/MainPage/MainPage.css
Executable file
@@ -0,0 +1,41 @@
|
||||
.background_holder {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.slogan {
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 5vh;
|
||||
padding-bottom: 10vh;
|
||||
z-index: 1;
|
||||
}
|
||||
.slogan > * {
|
||||
font-family: "Quicking";
|
||||
text-align: center;
|
||||
color: var(--mantine-color-contrast-filled);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tiles {
|
||||
width: 100%;
|
||||
align-items: stretch;
|
||||
gap: 40px 0px;
|
||||
}
|
||||
|
||||
#documentationButton {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 10vh;
|
||||
text-decoration: underline;
|
||||
}
|
||||
63
src/Pages/MainPage/MainPage.tsx
Executable file
63
src/Pages/MainPage/MainPage.tsx
Executable file
@@ -0,0 +1,63 @@
|
||||
import { Title, Button, Group } from "@mantine/core";
|
||||
import Background from "Components/StripedBg/Background";
|
||||
import "./MainPage.css";
|
||||
import { Helmet } from "react-helmet";
|
||||
import ButtonWithText from "Components/CardWithButton/CardWithButton";
|
||||
import { Link } from "react-router";
|
||||
import { routes } from "Routes/Routes";
|
||||
function MainPage() {
|
||||
return (
|
||||
<div>
|
||||
<Helmet>
|
||||
<title>Landing Page | QMolSim</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Description of the main functionaity of the QMolSim service"
|
||||
/>
|
||||
</Helmet>
|
||||
|
||||
<div className="background_holder">
|
||||
<Background />
|
||||
</div>
|
||||
|
||||
<div className="slogan">
|
||||
<Title size={50} textWrap="balance">
|
||||
Quantum Chemistry Made easy
|
||||
</Title>
|
||||
</div>
|
||||
|
||||
<Group className="tiles" justify="space-evenly">
|
||||
<ButtonWithText
|
||||
title="Работа с молекулами"
|
||||
text="Вводите информацию о молекулах любым удобным способом. Визуализируйте и
|
||||
редактируйте молекулы в простом интерфейсе."
|
||||
buttonText="Начать Эксперимент"
|
||||
link={routes.ExperimentsPage.path}
|
||||
/>
|
||||
<ButtonWithText
|
||||
title="Параллельные вычисления"
|
||||
text="Запускайте квантовые вычисления сразу на нескольких машинах.
|
||||
Упарвляйте и следите за машинами в одном месте."
|
||||
buttonText="Подключить Машину"
|
||||
link={routes.MachinesPage.path}
|
||||
/>
|
||||
<ButtonWithText
|
||||
title="Работа в команде"
|
||||
text="Создавайте команы с другими людьми и настраивайте доступ ко всем
|
||||
аспектам работы"
|
||||
buttonText="Создать Команду"
|
||||
link={routes.TeamsPage.path}
|
||||
/>
|
||||
</Group>
|
||||
<Link className="invisible_link" to={routes.DocumentationPage.path}>
|
||||
<div id="documentationButton">
|
||||
<Button variant="subtle" color="secondaryContrast">
|
||||
Документация
|
||||
</Button>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MainPage;
|
||||
4
src/Pages/TeamsPage/TeamsPage.css
Normal file
4
src/Pages/TeamsPage/TeamsPage.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.TeamsPage {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
}
|
||||
22
src/Pages/TeamsPage/TeamsPage.tsx
Normal file
22
src/Pages/TeamsPage/TeamsPage.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
import "./TeamsPage.css";
|
||||
import { PaginationContainer } from "Components/PaginationContainer/PaginationContainer";
|
||||
|
||||
function TeamsPage() {
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Teams Page | QMolSim</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="See the documentation on how to setup and use the qunatum computational system"
|
||||
/>
|
||||
</Helmet>
|
||||
<div className="TeamsPage">
|
||||
<PaginationContainer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default TeamsPage;
|
||||
12
src/Pages/UserPage/UserPage.css
Normal file
12
src/Pages/UserPage/UserPage.css
Normal file
@@ -0,0 +1,12 @@
|
||||
.tabPanel {
|
||||
flex-grow: 1;
|
||||
padding: 10px;
|
||||
border-left: 1px solid var(--tab-border-color);
|
||||
border-right: 1px solid var(--tab-border-color);
|
||||
border-bottom: 1px solid var(--tab-border-color);
|
||||
}
|
||||
|
||||
.userPage {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
}
|
||||
166
src/Pages/UserPage/UserPage.tsx
Normal file
166
src/Pages/UserPage/UserPage.tsx
Normal file
@@ -0,0 +1,166 @@
|
||||
import {
|
||||
Button,
|
||||
Title,
|
||||
Tabs,
|
||||
TextInput,
|
||||
SimpleGrid,
|
||||
Chip,
|
||||
Text,
|
||||
Divider,
|
||||
Switch,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconChartCandle,
|
||||
IconCheck,
|
||||
IconUserFilled,
|
||||
IconCancel,
|
||||
IconSun,
|
||||
IconMoonStars,
|
||||
} from "@tabler/icons-react";
|
||||
import keycloak from "Api/Keycloak/Keycloak";
|
||||
import { useEffect } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { AuthenticationStore } from "Stores/AuthenticationStore";
|
||||
import "./UserPage.css";
|
||||
import { useUserPreferencesStore } from "Stores/PreferencesStore";
|
||||
import CustomButton from "Components/CustomButton/CustomButton";
|
||||
function UserPage() {
|
||||
const { profile, token } = AuthenticationStore();
|
||||
const { theme, set_theme } = useUserPreferencesStore();
|
||||
|
||||
useEffect(() => {
|
||||
console.log(token);
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>User Page | QMolSim</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="See the documentation on how to setup and use the qunatum computational system"
|
||||
/>
|
||||
</Helmet>
|
||||
<div className="userPage">
|
||||
<Tabs
|
||||
variant="outline"
|
||||
style={{
|
||||
display: "flex",
|
||||
flexGrow: 1,
|
||||
flexDirection: "column",
|
||||
}}
|
||||
radius="lg"
|
||||
defaultValue="profile"
|
||||
classNames={{ panel: "tabPanel" }}
|
||||
>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab
|
||||
value="profile"
|
||||
leftSection={<IconUserFilled size={20} />}
|
||||
>
|
||||
Профиль
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
value="preference"
|
||||
leftSection={<IconChartCandle size={20} />}
|
||||
>
|
||||
Предпочтения
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="profile">
|
||||
<SimpleGrid verticalSpacing="lg" cols={2}>
|
||||
<Title size="lg">Имя пользователя:</Title>
|
||||
<TextInput size="md" value={profile?.username} />
|
||||
<Title size="lg">Почта:</Title>
|
||||
<TextInput size="md" value={profile?.email} />
|
||||
<CustomButton color="accent" text="Сохранить" />
|
||||
<CustomButton color="error" text="Отменить" />
|
||||
</SimpleGrid>
|
||||
<Divider my="lg" />
|
||||
<SimpleGrid verticalSpacing={"lg"} cols={2}>
|
||||
<Title
|
||||
size="lg"
|
||||
style={{ display: "flex", alignItems: "center" }}
|
||||
>
|
||||
Почта верифицирована:{" "}
|
||||
<Chip mx="lg" size="auto" checked={profile?.emailVerified}>
|
||||
{profile?.emailVerified ? (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<IconCheck
|
||||
size={25}
|
||||
color={"green"}
|
||||
style={{ verticalAlign: "center", margin: "5px" }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<IconCancel
|
||||
size={25}
|
||||
color="red"
|
||||
style={{
|
||||
verticalAlign: "center",
|
||||
margin: "5px",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Chip>
|
||||
</Title>
|
||||
{!profile?.emailVerified && (
|
||||
<CustomButton
|
||||
style="outline"
|
||||
color="contrast"
|
||||
text="Подтвердить почту"
|
||||
/>
|
||||
)}
|
||||
{profile?.emailVerified && <div></div>}
|
||||
<Title size="lg">Пароль:</Title>
|
||||
<CustomButton
|
||||
style="outline"
|
||||
color="contrast"
|
||||
text="Изменить пароль"
|
||||
/>
|
||||
</SimpleGrid>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="preference">
|
||||
<Switch
|
||||
size="xl"
|
||||
onChange={(event) =>
|
||||
set_theme(!event.currentTarget.checked ? "dark" : "light")
|
||||
}
|
||||
onLabel={
|
||||
<IconSun
|
||||
size={16}
|
||||
stroke={2.5}
|
||||
color="var(--mantine-color-yellow-4)"
|
||||
/>
|
||||
}
|
||||
offLabel={
|
||||
<IconMoonStars
|
||||
size={16}
|
||||
stroke={2.5}
|
||||
color="var(--mantine-color-blue-6)"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default UserPage;
|
||||
Reference in New Issue
Block a user